You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Microsoft Graph API访问非登录用户的外部邮箱?

问题描述

我在Azure注册了应用,已获取User.Read和Mail.Read权限,想读取外部邮件账户的邮箱(不是登录用户自己的邮箱)。该外部邮箱已加入应用所属组的成员,请问怎么授权应用访问这个外部邮箱?是否可行?

我试过两种代码方案,但都失败:

  • 使用msgraph的用户名密码认证方式,调用graph_client.me.messages无结果;
  • 使用msal的客户端凭证模式获取令牌,调用https://graph.microsoft.com/v1.0/users/{userId}/messages时返回ErrorAccessDenied错误:
    {'error': {'code': 'ErrorAccessDenied', 'message': 'Access is denied. Check credentials and try again.'}}
    
解决方案

一、可行性确认

可行,但需要调整权限类型和授权方式:

  • 当前使用的委托权限(User.Read/Mail.Read)仅能访问登录用户自身的邮箱,无法直接访问其他用户(包括外部账户)的邮箱;
  • 要访问其他用户邮箱,需使用应用权限,并配置对应邮箱访问权限。

二、具体配置步骤

  1. 添加应用权限
    在Azure Portal的应用注册页面:

    • 进入「API权限」>「添加权限」>「Microsoft Graph」>「应用权限」;
    • 添加Mail.Read应用权限(注意区分委托权限);
    • 点击「授予管理员同意」(必须完成此步骤,否则权限无法生效)。
  2. 调整认证方式
    不能再使用用户名密码的委托模式,需采用客户端凭证模式(对应你第二种msal的实现方式,但需修正权限和代码细节)。

三、代码修正

1. MSAL代码问题修正

  • 请求URL语法错误:$select前应使用?而非$,正确URL格式为:
    endpoint = f'https://graph.microsoft.com/v1.0/users/{userId}/messages?select=sender,subject'
    
  • 权限范围需改为应用权限格式:['https://graph.microsoft.com/.default'](应用权限必须使用此格式)。

修正后的完整MSAL代码:

import requests
import msal

CLIENT_ID = "你的客户端ID"
CLIENT_SECRET = "你的客户端密钥"
AUTHORITY = "https://login.microsoftonline.com/你的租户ID"  # 请勿使用common,填写实际租户ID
USER_ID = "外部邮箱的用户ID或邮箱地址"
SCOPE = ['https://graph.microsoft.com/.default']

app = msal.ConfidentialClientApplication(
    client_id=CLIENT_ID,
    client_credential=CLIENT_SECRET,
    authority=AUTHORITY
)

result = app.acquire_token_silent(SCOPE, account=None)

if not result:
    print("缓存中无合适令牌,从AAD获取新令牌")
    result = app.acquire_token_for_client(scopes=SCOPE)

if "access_token" in result:
    # 修正URL语法错误
    endpoint = f'https://graph.microsoft.com/v1.0/users/{USER_ID}/messages?select=sender,subject'
    r = requests.get(
        endpoint,
        headers={'Authorization': 'Bearer ' + result['access_token']}
    )
    if r.ok:
        print('成功获取邮件')
        data = r.json()
        for email in data['value']:
            print(f"{email['subject']} ({email['sender']['emailAddress']['name']})")
    else:
        print(r.json())
else:
    print(f"获取令牌失败: {result.get('error_description')}")

2. 第一种方法失效原因

graph_client.me.messages中的me指代当前登录用户(代码中的adelev@contoso.com),因此只能读取该用户自身的邮箱,无法访问外部账户。即使使用委托模式,也需要登录用户拥有该外部邮箱的访问权限(如邮箱共享),但此类场景更适合使用应用权限实现。

四、额外注意事项

  • 外部账户必须是Azure AD中的有效用户(你已将其加入组,满足该条件);
  • 应用权限需要全局管理员授予同意,否则会提示权限不足;
  • 确保用户ID或邮箱地址输入正确,避免拼写错误。

内容的提问来源于stack exchange,提问作者Renmy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 12:27:32