【问题标题】:Microsoft OAuth2 SMTP微软 OAuth2 SMTP
【发布时间】:2021-12-03 20:43:53
【问题描述】:

我正在尝试构建一个应用程序,从我的 Microsoft Office 电子邮件帐户发送电子邮件,在 Python 中使用 SMTP 进行发送,使用 OAuth2 进行身份验证。身份验证不起作用,我收到reply: retcode (535); Msg: b'5.7.3 Authentication unsuccessful [LO2P265CA0061.GBRP265.PROD.OUTLOOK.COM]'

我在 azure 上创建了一个 AAD 应用程序,并在设置凭据后下载了那里提供的示例 flask 应用程序,我知道这就是 repo

我已经使用了这个应用程序(从 AAD 门户下载,其中包含我的秘密)并尝试使用给定的令牌进行 SMTP 身份验证,使用来自

的信息

使用我的办公室电子邮件帐户登录有效,/graphcall 也有效。但是 SMTP 身份验证不起作用,我收到了 reply: retcode (535); Msg: b'5.7.3 Authentication unsuccessful [LO2P265CA0061.GBRP265.PROD.OUTLOOK.COM]'

我要求的令牌范围是SCOPE = ["User.ReadBasic.All", "https://outlook.office.com/SMTP.Send"],并且该应用在配置文件中打开了SMTP.send

这是一个扩展 smtplib.SMTP 的类,我基于这些编写:


import smtplib
import base64


class MicrosoftSMTP(smtplib.SMTP):
    def __init__(self, host="smtp.office365.com", port=587, **kwargs):
        super().__init__(host=host, port=port, **kwargs)

    @staticmethod
    def encode_auth_token(username, token):
        just_a_str = f"user={username}\x01auth=Bearer {token}\x01\x01"
        xoauth2_token = base64.b64encode(just_a_str.encode())

        return xoauth2_token

    def authenticate(self, username, token):
        self.helo()

        # first step, we
        code, msg = self.docmd("auth", "XOAUTH2")
        if code != 334:
            raise Exception(msg.decode())

        # send the token
        self.send(self.encode_auth_token(username, token))

以及用于连接应用程序凭据的代码,并添加一个页面,我在其中显示令牌 json 以进行完整性检查:


@app.route("/send_to_self")
def send_to_self():
    token = _get_token_from_cache(app_config.SCOPE)
    if not token:
        return redirect(url_for("login"))

    # connect to the server
    connection = MicrosoftSMTP()
    connection.set_debuglevel(True)  # for output
    connection.starttls()
    connection.authenticate(
        # same as session["user"]["preferred_username"]
        token["id_token_claims"]["preferred_username"],
        token["access_token"],
    )

    # ... would write an email here with connection.sendmail( ... )

    connection.quit()

    return render_template(
        "send_to_self.html",
        data=token,
        data_session=session["flow"],
        data_user=session["user"],
    )

身份验证失败,这是完整的日志:

send: 'ehlo 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa\r\n'
reply: b'250-LO2P265CA0516.outlook.office365.com Hello [<A.GENERAL.IP>]\r\n'
reply: b'250-SIZE 157286400\r\n'
reply: b'250-PIPELINING\r\n'
reply: b'250-DSN\r\n'
reply: b'250-ENHANCEDSTATUSCODES\r\n'
reply: b'250-STARTTLS\r\n'
reply: b'250-8BITMIME\r\n'
reply: b'250-BINARYMIME\r\n'
reply: b'250-CHUNKING\r\n'
reply: b'250 SMTPUTF8\r\n'
reply: retcode (250); Msg: b'LO2P265CA0516.outlook.office365.com Hello [<A.GENERAL.IP>]\nSIZE 157286400\nPIPELINING\nDSN\nENHANCEDSTATUSCODES\nSTARTTLS\n8BITMIME\nBINARYMIME\nCHUNKING\nSMTPUTF8'
send: 'STARTTLS\r\n'
reply: b'220 2.0.0 SMTP server ready\r\n'
reply: retcode (220); Msg: b'2.0.0 SMTP server ready'
send: 'helo 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa\r\n'
reply: b'250 LO2P265CA0516.outlook.office365.com Hello [<A.GENERAL.IP>]\r\n'
reply: retcode (250); Msg: b'LO2P265CA0516.outlook.office365.com Hello [<A.GENERAL.IP>]'
send: 'auth XOAUTH2\r\n'
reply: b'334 \r\n'
reply: retcode (334); Msg: b''
send: b'dX......EB'
send: 'quit\r\n'
reply: b'535 5.7.3 Authentication unsuccessful [LO2P265CA0516.GBRP265.PROD.OUTLOOK.COM]\r\n'
reply: retcode (535); Msg: b'5.7.3 Authentication unsuccessful [LO2P265CA0516.GBRP265.PROD.OUTLOOK.COM]'

我曾遇到过的事情:

  1. 我们允许此邮箱使用 SMTP
  2. 令牌允许 SMTP
  3. XOAUTH2 令牌编码器的输出与网站上的示例相匹配

仅供参考,令牌数据如下所示,已删除令牌和用户名

{
    "access_token": "ey<...>aw",
    "client_info": "ey<...>In0",
    "expires_in": 3599,
    "ext_expires_in": 3599,
    "id_token": "ey<...>jQ",
    "id_token_claims": {
        "aud": "8<...>9",
        "exp": 1634319637,
        "iat": 1634315737,
        "iss": "https://login.microsoftonline.com/5<...>1/v2.0",
        "name": "<Name of the user>",
        "nbf": 1634315737,
        "nonce": "c1<...>d0",
        "oid": "cd<...>1b",
        "preferred_username": "user.name@company.com",
        "rh": "0.A<...>As.",
        "sub": "2w<...>ww",
        "tid": "50<...>31",
        "uti": "8W<...>AA",
        "ver": "2.0"
    },
    "refresh_token": "0.A<...>4Y",
    "scope": "openid profile SMTP.Send User.ReadBasic.All email",
    "token_type": "Bearer"
}

【问题讨论】:

  • 同时我发现python O365可以在不需要SMTP的情况下执行相同的任务,并且可以本地发送电子邮件

标签: python oauth smtp msal smtplib


【解决方案1】:
  1. 通过将启用安全默认设置切换为否来禁用 Azure 安全默认设置:

    • 以安全管理员、条件访问管理员或全局管理员身份登录 Azure 门户。
    • 浏览到 Azure Active Directory -> 属性。
    • 选择管理安全默认值。
    • 将启用安全默认设置开关设置为否。
    • 选择保存。
  2. 从阻止旧式身份验证的条件访问策略中排除用户:

    • 以安全管理员、条件访问管理员或全局管理员身份登录 Azure 门户。
    • 浏览到 Azure Active Directory > 安全 > 条件访问。
    • 在阻止旧式身份验证的策略中,在“用户和组”>“排除”下排除正在使用的邮箱。
    • 选择保存。

您应该使用 SMTP 服务器:apicalsolutions-com.mail.protection.outlook.com端口 25。作为用户使用您域的任何用户。即使它没有链接邮箱也可以用来登录。

阅读更多here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多