使用Python的exchangelib通过OAuth访问Exchange邮箱报错排查
问题:使用exchangelib OAuth2访问Exchange邮箱时报错
The SMTP address has no mailbox associated with it 背景
微软已弃用Exchange邮箱的基本认证方式,将代码升级为基于OAuth的访问方式,并按官方文档配置了Azure AD应用。使用exchangelib库的OAuth2Credentials编写代码访问邮箱时,报错The SMTP address has no mailbox associated with it,但该SMTP地址对应的Exchange邮箱真实存在且可通过Outlook正常登录。
代码示例
from exchangelib import Account, OAuth2Credentials AZURE_CLIENT_ID = "MY_CLIENT_ID" AZURE_TENANT_ID = "MY_TENANT_ID" AZURE_CLIENT_CREDENTIAL = "MY_CLIENT_CREDENTIAL" MY_EMAIL = "me@example.com" credentials = OAuth2Credentials( client_id=AZURE_CLIENT_ID, client_secret=AZURE_CLIENT_CREDENTIAL, tenant_id=AZURE_TENANT_ID ) account = Account(primary_smtp_address=MY_EMAIL, credentials=credentials, autodiscover=True) for item in account.inbox.all().order_by('-datetime_received')[:100]: print(item.subject, item.sender, item.datetime_received)
报错堆栈
Traceback (most recent call last): File "exchangelib_test.py", line 19, in <module> account = Account(primary_smtp_address=MY_EMAIL, credentials=credentials, autodiscover=True) File "/home/me/.local/lib/python3.6/site-packages/exchangelib/account.py", line 119, in __init__ email=primary_smtp_address, credentials=credentials, auth_type=auth_type, retry_policy=retry_policy File "/home/me/.local/lib/python3.6/site-packages/exchangelib/autodiscover/discovery.py", line 114, in discover ad_response = self._quick(protocol=ad_protocol) File "/home/me/.local/lib/python3.6/site-packages/exchangelib/autodiscover/discovery.py", line 201, in _quick return self._step_5(ad=ad) File "/home/me/.local/lib/python3.6/site-packages/exchangelib/autodiscover/discovery.py", line 531, in _step_5 ad.raise_errors() File "/home/me/.local/lib/python3.6/site-packages/exchangelib/autodiscover/properties.py", line 313, in raise_errors raise ErrorNonExistentMailbox('The SMTP address has no mailbox associated with it') exchangelib.errors.ErrorNonExistentMailbox: The SMTP address has no mailbox associated with it
问题原因及解决办法
1. OAuth2凭证模式不匹配
当前代码使用客户端凭证模式(通过client_secret认证),这种模式下应用以自身身份访问资源,而非模拟用户:
- 若采用客户端凭证模式:
- 在Azure AD应用中添加应用权限(而非委托权限),比如
Exchange.ManageAsApp,并由全局管理员完成权限同意 - 通过PowerShell给Azure AD应用的服务主体授予目标邮箱的FullAccess权限:
Add-MailboxPermission -Identity "me@example.com" -User "AzureAD应用服务主体ID" -AccessRights FullAccess
- 在Azure AD应用中添加应用权限(而非委托权限),比如
- 若需模拟用户访问,应改用授权码模式,需获取用户的授权token,而非仅用client_id/secret/tenant_id。
2. Autodiscover自动发现失败
Autodiscover可能无法正确解析邮箱的Exchange服务器地址,尝试手动指定服务器:
from exchangelib import Account, OAuth2Credentials, Configuration # 根据Exchange环境调整服务器地址,Office 365用outlook.office365.com config = Configuration(server='outlook.office365.com', credentials=credentials) account = Account(primary_smtp_address=MY_EMAIL, config=config, autodiscover=False)
3. Azure AD应用权限配置错误
检查权限类型是否匹配:
- 客户端凭证模式必须使用应用权限,且需管理员同意
- 用户委托模式使用委托权限(如
EWS.AccessAsUser.All),需用户或管理员同意
4. exchangelib版本兼容问题
Python3.6对新版本exchangelib支持有限,当前版本可能存在OAuth2适配问题。建议升级到Python3.6兼容的最高版本exchangelib:
pip install exchangelib==4.9.0
内容的提问来源于stack exchange,提问作者Benjamin Gorman
相关产品推荐
相关产品推荐

