微软关闭IMAP协议后,Python用imaplib连Office365遇LOGIN失败求助
解决Office 365邮件读取的替代方案(替代IMAP基本认证)
问题原因
你遇到的b'LOGIN failed'并非IMAP协议被完全关闭,而是微软已停止支持Office 365账户的IMAP基本认证(用户名+密码直接登录),必须采用OAuth 2.0认证方式,或使用更推荐的Microsoft Graph API进行邮件操作。
方案一:使用Microsoft Graph API(推荐)
微软当前主推Graph API作为Office 365服务的统一访问接口,功能更全面,也符合平台未来迭代方向。
前置准备
- 在Azure Active Directory中注册应用:
- 登录Azure门户,进入「应用注册」页面创建新注册
- 设置重定向URI(例如
http://localhost:8000) - 为应用添加委托权限:
Mail.Read,并完成管理员同意(针对企业租户账户) - 记录租户ID、客户端ID、客户端密码(或生成证书)
Python代码示例
使用requests库实现邮件读取:
import requests # 配置信息 tenant_id = "你的租户ID" client_id = "你的客户端ID" client_secret = "你的客户端密码" user_email = "test@abc.com" # 获取访问令牌 token_url = f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token" token_data = { "grant_type": "client_credentials", "client_id": client_id, "client_secret": client_secret, "scope": "https://graph.microsoft.com/.default" } token_response = requests.post(token_url, data=token_data) access_token = token_response.json()["access_token"] # 调用Graph API读取最近10封邮件 mail_api_url = f"https://graph.microsoft.com/v1.0/users/{user_email}/messages?$top=10&$select=subject,from,receivedDateTime" headers = {"Authorization": f"Bearer {access_token}"} mail_response = requests.get(mail_api_url, headers=headers) if mail_response.status_code == 200: messages = mail_response.json()["value"] for msg in messages: print(f"主题: {msg['subject']}") print(f"发件人: {msg['from']['emailAddress']['name']} <{msg['from']['emailAddress']['address']}>") print(f"接收时间: {msg['receivedDateTime']}\n") else: print(f"请求失败: {mail_response.text}")
方案二:使用OAuth 2.0认证的IMAP
如果坚持使用IMAP协议,需通过OAuth 2.0获取认证令牌后登录:
Python代码示例(使用msal库)
import imaplib import msal # 配置信息 tenant_id = "你的租户ID" client_id = "你的客户端ID" client_secret = "你的客户端密码" user_email = "test@abc.com" imap_server = "outlook.office365.com" imap_port = 993 # 初始化MSAL客户端 app = msal.ConfidentialClientApplication( client_id, authority=f"https://login.microsoftonline.com/{tenant_id}", client_credential=client_secret ) # 获取IMAP访问令牌 scopes = ["https://outlook.office365.com/IMAP.AccessAsUser.All"] result = app.acquire_token_for_client(scopes=scopes) access_token = result.get("access_token") if not access_token: print(f"获取令牌失败: {result.get('error_description')}") exit() # 连接IMAP服务器并登录 imap_session = imaplib.IMAP4_SSL(imap_server, imap_port) imap_session.authenticate("XOAUTH2", lambda: f"user={user_email}\1auth=Bearer {access_token}\1\1") # 示例:读取收件箱邮件数量 imap_session.select("INBOX") status, count = imap_session.search(None, "ALL") print(f"收件箱共有 {len(count[0].split())} 封邮件") imap_session.close() imap_session.logout()
内容的提问来源于stack exchange,提问作者Enes KÖKÇÜ
相关产品推荐
相关产品推荐

