【问题标题】:How to send SMTP email for office365 with python using tls/ssl如何使用 tls/ssl 使用 python 为 office365 发送 SMTP 电子邮件
【发布时间】:2018-02-20 00:02:06
【问题描述】:

我正在尝试使用 python 从我的 office365 公司帐户发送一封电子邮件。我是 python 新手。此代码以前在使用我的 hotmail 帐户时有效,但是现在我需要发送机密信息,我必须使用我的公司电子邮件。

我已经尝试了几件事。

  • 已验证我的用户名和密码是否正确。
  • 同时使用了 python2 和 python3。两者都给出相同的错误:535 5.7.3 Authentication unsuccessful
  • 我以前使用 ma​​ilserver.starttls() 时获得 上面报错,后来经过一番研究,我试图通过一个
    证书。ma​​ilserver.starttls(certfile='office365.cer')

我不清楚证书部分,但我的步骤包括,在网上查找如何导出证书。使用 chrome 浏览器,microsoftonline.com 有一个链式证书。我可以导出根目录和根目录下方的级别,但不能导出最后一级。我不知道如何通过这两个文件,所以我只是通过了根证书。此时我得到错误:ssl.SSLError: [SSL] PEM lib (_ssl.c:3309)

我在这一点上卡住了。任何帮助表示赞赏。 下面使用的代码

import smtplib

mailserver = smtplib.SMTP('smtp.office365.com',587)
mailserver.ehlo()
mailserver.starttls(certfile='office365.cer')
mailserver.ehlo()
mailserver.login('user@company.co', 'password')
mailserver.sendmail('user@company.co','user@company.co','python email')
mailserver.quit()

【问题讨论】:

    标签: python email ssl office365


    【解决方案1】:

    我找到了一个对我有用的库:

    https://github.com/O365/python-o365

    https://pypi.python.org/pypi/O365

    使用 PIP 安装它,然后:

    from O365 import Message
    o365_auth = ('YourAccount@office365.com','YourPassword')
    m = Message(auth=o365_auth)
    m.setRecipients('reciving@office365.com')
    m.setSubject('I made an email script.')
    m.setBody('Talk to the computer, cause the human does not want to hear it any more.')
    m.sendMessage()
    

    【讨论】:

    • 我只是想为将来看到这一点的人指出;虽然这个库可以工作,但它不使用 SMTP。它使用 Microsoft Outlook/Graph API 来访问您的 Office 365 帐户并发送电子邮件。如果您想使用 SMTP,请参阅下面 Gal 的回答。
    • @BigGerman 对于我们这些凡人来说,你能解释一下区别吗,这段代码的使用与上面的有什么不同?
    • @Datanovice SMTP 是一种用于发送电子邮件的协议,使用 smtplib,您可以使用 SMTP 协议将电子邮件直接发送到 Office365 邮件服务器。使用 nacho-parra 的回答,您正在使用 Python 模块 (O365),该模块使用向 Microsoft Graph API 发送 HTTP 请求,然后发送电子邮件。结果基本相同(发送电子邮件),但方法不同。最初的问题是询问有关使用 SMTP 发送的问题,因此 gal-silberman 的答案实际上展示了如何实现这一点。
    • @BigGerman 你就是那个人,非常简洁和中肯的版本,干杯。我想知道哪个资源更昂贵,或者 api 是否对电子邮件有限制。
    • @Datanovice SMTP 对于发送基本电子邮件来说绝对更简单,但图形 API 允许您做更多事情,而不仅仅是发送电子邮件。至于 API 的速率限制,它们非常慷慨,但确实有一些 throttling。我唯一一次遇到限制是从电子邮件收件箱中检索超过 10,000 条消息时。不过,SMTP 服务器也可以由提供商设置自己的限制,请参阅here
    【解决方案2】:

    嗯,你快到了。以下代码可以解决问题:

    import smtplib
    
    mailserver = smtplib.SMTP('smtp.office365.com',587)
    mailserver.ehlo()
    mailserver.starttls()
    mailserver.login('user@company.co', 'password')
    #Adding a newline before the body text fixes the missing message body
    mailserver.sendmail('user@company.co','user@company.co','\npython email')
    mailserver.quit()
    

    使用以下链接了解更多信息:

    http://www.aventistech.com/2016/03/07/python-send-email-via-office-365-tls/

    https://docs.python.org/3/library/smtplib.html

    https://gist.github.com/jasonjoh/3ec367594c3fa662ee983a617bdc7deb

    【讨论】:

    • 注意:使用 smtplib.SMTP() 代替 smtplib.SMTP_SSL() !使用 smtplib.SMTP_SSL() 您仍然会收到“[SSL: WRONG_VERSION_NUMBER]”错误。用 smtplib.SMTP() 替换它对我有用。
    • 这段代码的安全性如何?如果服务器拒绝使用 TLS 会发生什么?连接会不加密还是中止?
    • 我能问个问题吗? Gal Silberman 的回答对我来说“有效”,因为收件人收到了我的电子邮件,但是,电子邮件是空的(他们甚至看不到“python 电子邮件”字符串)。有人知道为什么会这样吗?我没有收到错误,所以很难诊断。
    • @Kela,你应该用你所做的一切在不同的线程中提出一个新问题。
    • 也许这很明显,但是如果您的公司帐户需要多因素身份验证,则用户名和密码不足以进行身份​​验证。
    【解决方案3】:

    代码略有更改。上面的代码不起作用。请使用以下代码。 Reference

    from O365 import Account
    
    credentials = ('client_id', 'client_secret')
    
    account = Account(credentials)
    m = account.new_message()
    m.to.add('to_example@example.com')
    m.subject = 'Testing!'
    m.body = "George Best quote: I've stopped drinking, but only while I'm asleep."
    m.send()
    

    【讨论】:

    • 我在使用这个时收到以下错误。“RuntimeError: No auth token found. Authentication Flow required”
    • @ShashiShankarSingh 您是否在 Azure 中设置了客户端令牌?
    • @Shashi Shankar Singh 查看我的回答stackoverflow.com/a/71148071/9160306 我能够解决这个问题。
    【解决方案4】:

    很可能,问题不在于您的代码,而在于 Exchange Online 配置。

    我敢打赌,535 5.7.3 Authentication unsuccessful 被抛出是因为在您的 Exchange Online 组织中禁用了经过身份验证的 SMTP(SMTP AUTH 协议)。

    Here 您可以找到我的答案,解释如何为您发送电子邮件的用户启用 SMTP AUTH。您必须是 Office 365 组织管理员才能执行此操作,或者您可以向您的管理员寻求帮助。

    之后mailserver.starttls() 应该可以工作了。请注意,您不需要在该调用中指定证书。

    【讨论】:

      【解决方案5】:

      对我来说,@Prometheus 提供的答案是评论中提到的“RuntimeError: No auth token found . Authentication Flow required”。这可能是因为我的公司电子邮件启用了 2fa。所以我必须按照https://github.com/janscas/pyo365#authenticationhttps://pypi.org/project/O365/#authentication 中提供的步骤进行操作

      要使用 oauth,您首先需要在 Microsoft 应用程序注册门户注册您的应用程序。

      1. 登录Microsoft Application Registration Portal
      2. 创建一个应用,记下您的应用 ID (client_id)
      3. 在“应用程序机密”部分下生成新密码 (client_secret) 在“平台”部分下,添加新的 Web 平台并将 https://login.microsoftonline.com/common/oauth2/nativeclient" 设置为重定向 URL
      4. 转到 API 权限 > 添加权限 > Microsoft Graph > 委派权限,添加以下权限:
        • IMAP.AccessAsUser.All

        • 邮件.发送

        • POP.AccessAsUser.All

        • 用户.读取

        • SMTP.发送

        • offline_access # 如果您希望刷新令牌在 o365_token.txt 中可用。否则,您需要每 1 小时获取一次访问令牌。

      5. 在 python 脚本下面运行获取访问令牌,该令牌将存储在当前目录中名为 o365_token.txt 的文件中
      from O365 import Account
      
      scopes =  ["IMAP.AccessAsUser.All", "POP.AccessAsUser.All", "SMTP.Send", "Mail.Send", "offline_access"]
      
      account = Account(credentials=('client_id_of_azureapp', 'client_secret_of_azureapp'))
      result = account.authenticate(scopes=scopes)  # request a token for this scopes
      
      1. 通过提供上一步生成的 authtoken 文件,使用以下脚本发送电子邮件。
      from O365 import Account
      from O365.utils.token import FileSystemTokenBackend
      tk = FileSystemTokenBackend(token_path=".", token_filename="o365_token.txt")
      
      credentials = ('client_id') # client secret not required
      
      account = Account(credentials, auth_flow_type = 'public',token_backend=tk)
      m = account.new_message()
      m.to.add('user@company.com')
      m.subject = 'Testing!'
      m.body = "George Best quote: I've stopped drinking, but only while I'm asleep."
      m.send()
      

      注意: 如果您已获得管理员同意,或者您是管理员或 Azure 帐户,则可以跳过第 4、5、6 步并直接使用以下代码。

      from O365 import Account
      from O365.utils.token import FileSystemTokenBackend
      tk = FileSystemTokenBackend(token_path=".", token_filename="o365_token.txt")
      
      credentials = ('client_id', 'client_secret') # from step 2,3
      account = Account(credentials, auth_flow_type = 'credentials', tenant_id="your_app_tenant_id") # tenant_id (required) available just below client_id in azure
      
      if account.authenticate():
          print('Authenticated!')
      
      mailbox = account.mailbox("user@company.com") # Your email (required) from which you want to send email (your app should have permission to this email)
      m = mailbox.new_message()
      m.to.add('touser@company.com')
      m.subject = 'Testing!'
      m.body = "George Best quote: I've stopped drinking, but only while I'm asleep."
      m.send()
      

      【讨论】:

        猜你喜欢
        • 2019-07-06
        • 2019-05-29
        • 2017-10-12
        • 1970-01-01
        • 1970-01-01
        • 2011-11-29
        • 2017-02-17
        • 2012-08-30
        • 2010-11-03
        相关资源
        最近更新 更多