调用Microsoft Graph API users/{email}/messages遇权限拒绝错误求助
问题原因及解决方法
核心错误:身份验证流与权限类型不兼容
你当前用的是客户端凭证流(Client Credentials Flow)(通过acquire_token_for_client获取token),但仅给应用配置了委托权限(Delegated Permissions)——这两者完全不匹配:
- 委托权限是代表具体用户访问资源,必须有用户参与登录流程(比如授权码流、设备码流);
- 客户端凭证流是应用自身直接访问资源,无需用户介入,必须配置应用权限(Application Permissions)。
你能获取到token是因为客户端凭证流仅验证应用身份,但该token没有访问邮件的有效权限,所以调用Graph API时被拒绝。
两种解决路径
路径1:改用用户上下文的身份验证流(推荐,匹配你之前用me/messages的场景)
如果需要继续代表特定用户访问邮箱,适合用设备码流(Device Code Flow),适配Databricks这类无UI环境,步骤如下:
- 保留现有委托权限,确保权限已完成管理员同意(租户级应用需全局管理员授权);
- 修改代码替换身份验证流:
import msal import requests authority = f"https://login.microsoftonline.com/{tenant_id}" scope = ["https://graph.microsoft.com/Mail.Read"] app = msal.PublicClientApplication( client_id, authority=authority ) # 初始化设备码流 flow = app.initiate_device_flow(scopes=scope) if "user_code" not in flow: raise ValueError(f"启动设备码流失败: {flow.get('error')}") # 打印登录提示,引导用户在浏览器完成验证 print(flow["message"]) result = app.acquire_token_by_device_flow(flow) if "access_token" in result: print('使用access token访问API...') headers = {'Authorization': 'Bearer ' + result['access_token']} # 用户上下文可直接使用me/messages端点 graph_endpoint = 'https://graph.microsoft.com/v1.0/me/messages' response = requests.get(graph_endpoint, headers=headers) if response.status_code == 200: emails = response.json() print(emails) else: print(f"获取邮件失败: {response.status_code}") print(response.json()) else: print(f"获取token失败: {result.get('error')}, {result.get('error_description')}")
路径2:改用应用权限(适合后台服务,无需用户参与)
如果场景是应用自身直接访问邮箱(无需用户登录),需按以下操作:
- 在Azure门户的应用注册中,切换到应用权限标签,添加
Mail.Read(或Mail.ReadWrite)应用权限,点击授予管理员同意; - 保留客户端凭证流代码,scope保持
["https://graph.microsoft.com/.default"](该scope会自动包含所有已授予的应用权限); - 确保
users/{email}/messages中的目标邮箱是租户内有效账号,且应用权限覆盖该账号。
额外检查项
- 确认租户ID、客户端ID、密钥无输入错误;
- 若用委托权限,需确保用户账号有权访问目标邮箱,且权限已完成管理员同意;
- 调用
users/{email}/messages时,目标邮箱必须是租户内的有效账号,不能是外部邮箱。
内容的提问来源于stack exchange,提问作者LunaLoveDove
相关产品推荐
相关产品推荐

