我试图升级一个遗留的邮件机器人,使其通过Oauth2进行身份验证,而不是基本的身份验证,因为它是从现在起两天后就被否决了。
文档状态应用程序可以保留它们的原始逻辑,同时只交换身份验证位。
构建了使用这些协议发送、读取或以其他方式处理电子邮件的应用程序的应用程序开发人员将能够保持相同的协议,但需要为其用户实现安全的现代身份验证体验。此功能构建在Microsoft Identity platform v2.0之上,并支持访问Microsoft 365电子邮件帐户。
注意,我显式地选择了客户凭证流,因为文档声明
这种类型的授权通常用于必须在后台运行的服务器到服务器之间的交互,而不需要立即与用户进行交互。
因此,我有一个python脚本,它使用MSAL python库检索访问令牌。现在,我正在尝试使用该访问令牌与IMAP服务器进行身份验证。有一些现有的线程显示了如何连接到谷歌,我想我的情况非常接近这一个,除了连接到Office365IMAP服务器之外。这是我的剧本
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://outlook.office.com/IMAP.AccessAsUser.All
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
发布于 2022-10-19 20:06:18
发生imaplib.IMAP4.error: AUTHENTICATE failed
错误是因为文档中有一点不太清楚。
通过Powershell设置服务主体时,需要输入App和对象ID。许多人会认为,这是您在注册应用程序的概述页面上看到的对象ID,但它不是!此时,您需要"Azure Active Directory -> Enterprise应用程序-> you -App-> Object-ID"中的对象ID
New-ServicePrincipal -AppId <APPLICATION_ID> -ServiceId <OBJECT_ID> [-Organization <ORGANIZATION_ID>]
微软说:
OBJECT_ID是用于应用程序注册的企业应用程序节点(Azure )概述页面中的对象ID。它不是App注册节点概述中的对象ID。使用不正确的对象ID将导致身份验证失败。
当然,您需要注意API-权限和其他东西,但这对我来说是重点。因此,让我们再一次处理它,就像文档页面中解释的那样。使用OAuth验证IMAP、POP或SMTP连接
这就是我用来测试它的代码:
import imaplib
import msal
import pprint
conf = {
"authority": "https://login.microsoftonline.com/XXXXyourtenantIDXXXXX",
"client_id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXX", #AppID
"scope": ['https://outlook.office365.com/.default'],
"secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", #Key-Value
"secret-id": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", #Key-ID
}
def generate_auth_string(user, token):
return f"user={user}\x01auth=Bearer {token}\x01\x01"
if __name__ == "__main__":
app = msal.ConfidentialClientApplication(conf['client_id'], authority=conf['authority'],
client_credential=conf['secret'])
result = app.acquire_token_silent(conf['scope'], account=None)
if not result:
print("No suitable token in cache. Get new one.")
result = app.acquire_token_for_client(scopes=conf['scope'])
if "access_token" in result:
print(result['token_type'])
pprint.pprint(result)
else:
print(result.get("error"))
print(result.get("error_description"))
print(result.get("correlation_id"))
imap = imaplib.IMAP4('outlook.office365.com')
imap.starttls()
imap.authenticate("XOAUTH2", lambda x: generate_auth_string("target_mailbox@example.com", result['access_token']).encode("utf-8"))
设置服务主体并让应用程序完全访问邮箱后,等待15-30分钟才能使更改生效并进行测试。
发布于 2022-10-12 09:08:50
试试下面的步骤。
对于客户端凭据流,您需要在应用程序注册中分配“应用程序权限”,而不是“委托权限”。
现在,您可以通过将该访问令牌和邮箱用户名组合起来使用IMAP4进行身份验证来生成SALS身份验证字符串。
#Python代码
def get_access_token():
tenantID = 'abc’
authority = 'https://login.microsoftonline.com/' + tenantID
clientID = 'abc’
clientSecret = 'abc
scope = ['https://outlook.office365.com/.default']
app = ConfidentialClientApplication(clientID,
authority=authority,
client_credential = clientSecret)
access_token = app.acquire_token_for_client(scopes=scope)
return access_token
def generate_auth_string(user, token):
auth_string = f"user={user}\1auth=Bearer {token}\1\1"
return auth_string
#IMAP AUTHENTICATE
imap = imaplib.IMAP4_SSL(imap_host, 993)
imap.debug = 4
access_token = get_access_token_to_authenticate_imap()
imap.authenticate("XOAUTH2", lambda x:generate_auth_string(
'useremail',
access_token['access_token']))
imap.select('inbox')
发布于 2022-09-30 09:28:41
尝试使用以下脚本:
import json
import msal
import requests
client_id = '***'
client_secret = '***'
tenant_id = '***'
authority = f"https://login.microsoftonline.com/{tenant_id}"
app = msal.ConfidentialClientApplication(
client_id=client_id,
client_credential=client_secret,
authority=authority)
scopes = ["https://graph.microsoft.com/.default"]
result = None
result = app.acquire_token_silent(scopes, account=None)
if not result:
print(
"No suitable token exists in cache. Let's get a new one from Azure Active Directory.")
result = app.acquire_token_for_client(scopes=scopes)
# if "access_token" in result:
# print("Access token is " + result["access_token"])
if "access_token" in result:
userId = "***"
endpoint = f'https://graph.microsoft.com/v1.0/users/{userId}/sendMail'
toUserEmail = "***"
email_msg = {'Message': {'Subject': "Test Sending Email from Python",
'Body': {'ContentType': 'Text', 'Content': "This is a test email."},
'ToRecipients': [{'EmailAddress': {'Address': toUserEmail}}]
},
'SaveToSentItems': 'true'}
r = requests.post(endpoint,
headers={'Authorization': 'Bearer ' + result['access_token']}, json=email_msg)
if r.ok:
print('Sent email successfully')
else:
print(r.json())
else:
print(result.get("error"))
print(result.get("error_description"))
print(result.get("correlation_id"))
来源:https://kontext.tech/article/795/python-send-email-via-microsoft-graph-api
https://stackoverflow.com/questions/73902642
复制相似问题