我正在尝试将一个传统的邮件机器人升级,以便通过Oauth2进行身份验证,而不是使用基本身份验证,因为基本身份验证将在两天后被废弃。
文档指出,应用程序可以保留其原始逻辑,只需更换身份验证部分即可。
构建使用这些协议发送、读取或处理电子邮件的应用程序开发人员将能够保持相同的协议,但需要为其用户实现安全的现代身份验证体验。此功能基于Microsoft Identity平台v2.0构建,并支持访问Microsoft 365电子邮件帐户。
请注意,我明确选择了客户端凭据流程,因为文档指出:
此类授权通常用于必须在后台运行而不需要与用户立即交互的服务器间交互。
因此,我有一个使用MSAL python库检索访问令牌的Python脚本。现在我正在尝试使用该访问令牌进行与IMAP服务器的身份验证。有一些现有的线程展示了如何连接到Google,我想我的情况非常接近这个,只不过我要连接到Office 365 IMAP服务器。以下是我的脚本:
import imaplib
import msal
import logging
app = msal.ConfidentialClientApplication(
'client-id',
authority='https://login.microsoftonline.com/tenant-id',
client_credential='secret-key'
)
result = app.acquire_token_for_client(scopes=['https://graph.microsoft.com/.default'])
def generate_auth_string(user, token):
return 'user=%s\1auth=Bearer %s\1\1' % (user, token)
# IMAP time!
mailserver = 'outlook.office365.com'
imapport = 993
M = imaplib.IMAP4_SSL(mailserver,imapport)
M.debug = 4
M.authenticate('XOAUTH2', lambda x: generate_auth_string('user@mydomain.com', result['access_token']))
print(result)
IMAP认证失败,尽管设置了M.debug = 4
,输出并不是很有帮助。
22:56.53 > b'DBDH1 AUTHENTICATE XOAUTH2'
22:56.53 < b'+ '
22:56.53 write literal size 2048
22:57.84 < b'DBDH1 NO AUTHENTICATE failed.'
22:57.84 NO response: b'AUTHENTICATE failed.'
Traceback (most recent call last):
File "/home/ubuntu/mini-oauth.py", line 21, in <module>
M.authenticate("XOAUTH2", lambda x: generate_auth_string('user@mydomain.com', result['access_token']))
File "/usr/lib/python3.10/imaplib.py", line 444, in authenticate
raise self.error(dat[-1].decode('utf-8', 'replace'))
imaplib.IMAP4.error: AUTHENTICATE failed.
有任何想法我可能做错了什么,或怎样从IMAP服务器获取更强大的信息来解决认证失败的问题?
我看过的东西
请注意这个答案不再有效,因为建议的作用域无法生成访问令牌。
客户端凭据流似乎需要
https://graph.microsoft.com/.default
授权。我不确定是否包括所需的IMAP资源范围https://outlook.office.com/IMAP.AccessAsUser.All
?根据MS文档上的示例,验证从Google线程中提取的代码正确地生成SASL XOAUTH2字符串。
import base64
user = 'test@contoso.onmicrosoft.com'
token = 'EwBAAl3BAAUFFpUAo7J3Ve0bjLBWZWCclRC3EoAA'
xoauth = "user=%s\1auth=Bearer %s\1\1" % (user, token)
xoauth = xoauth.encode('ascii')
xoauth = base64.b64encode(xoauth)
xoauth = xoauth.decode('ascii')
xsanity = 'dXNlcj10ZXN0QGNvbnRvc28ub25taWNyb3NvZnQuY29tAWF1dGg9QmVhcmVyIEV3QkFBbDNCQUFVRkZwVUFvN0ozVmUwYmpMQldaV0NjbFJDM0VvQUEBAQ=='
print(xoauth == xsanity) # prints True
- 这个帖子 建议需要获取多个令牌,一个用于Graph API,另一个则用于IMAP连接;那可能是我遗漏的吗?