无需授权链接,Python在Linux无干预读取Office365邮件问题
解决Office365委派权限下无交互令牌刷新问题
核心方案:持久化刷新令牌
委派权限模式下,首次手动授权后会生成刷新令牌(默认有效期90天),利用它可以自动获取新的访问令牌,无需重复手动登录。关键是安全存储刷新令牌,后续脚本直接调用刷新流程即可。
步骤1:首次授权时保存刷新令牌
使用office365-REST-Python-Client完成首次手动授权后,将刷新令牌写入本地安全存储(比如加密文件或系统密钥管理工具):
from office365.runtime.auth.authentication_context import AuthenticationContext ctx_auth = AuthenticationContext("https://outlook.office365.com/") # 首次运行会触发浏览器授权流程,完成后获取令牌 auth_result = ctx_auth.acquire_token_for_user( username="your_delegated_user@example.com", password=None, client_id="your_azure_app_client_id", client_secret="your_azure_app_client_secret", redirect_uri="https://localhost" ) # 保存刷新令牌(建议加密存储,避免明文泄露) if "refresh_token" in auth_result: with open("/path/to/secure/refresh_token.txt", "w") as f: f.write(auth_result["refresh_token"])
步骤2:后续无交互运行时复用刷新令牌
每次脚本启动,读取保存的刷新令牌,调用刷新接口获取新的访问令牌,全程无需人工干预:
from office365.runtime.auth.authentication_context import AuthenticationContext from office365.sharepoint.client_context import ClientContext ctx_auth = AuthenticationContext("https://outlook.office365.com/") # 读取已保存的刷新令牌 with open("/path/to/secure/refresh_token.txt", "r") as f: refresh_token = f.read().strip() # 用刷新令牌获取新的访问令牌 refresh_result = ctx_auth.acquire_token_by_refresh_token( refresh_token, client_id="your_azure_app_client_id", client_secret="your_azure_app_client_secret" ) # 处理刷新令牌过期的情况(90天后需重新手动授权一次) if not refresh_result.get("access_token"): raise Exception("刷新令牌已过期,请手动完成一次授权后重新运行脚本") # 后续执行邮件恢复逻辑:获取特定发件人的邮件 ctx = ClientContext("https://outlook.office365.com/").with_auth(ctx_auth) messages = ctx.me.mail_folders["Inbox"].messages.filter( f"sender/emailAddress/address eq 'sender@example.com'" ).get().execute_query()
关键配置与注意事项
- Azure AD应用权限:必须为应用添加
offline_access委派权限,否则无法获取刷新令牌。 - 刷新令牌安全:禁止明文存储,可使用Linux的
keyring工具或加密文件保护,防止令牌泄露。 - 有效期限制:刷新令牌默认90天过期,过期后需手动完成一次授权,之后可继续自动刷新。
备选方案:用户名密码流(仅限无MFA场景)
如果委派账号未启用多因素认证(MFA),可直接使用用户名密码流实现完全无交互,但安全性较低,不建议生产环境使用:
auth_result = ctx_auth.acquire_token_for_user( username="your_delegated_user@example.com", password="your_user_password", client_id="your_azure_app_client_id", client_secret="your_azure_app_client_secret" )
内容的提问来源于stack exchange,提问作者APP_BL15
相关产品推荐
相关产品推荐

