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

如何获取有效令牌调用Microsoft Graph API,解决EWS令牌受众无效问题?

解决EWS令牌调用Graph API的受众无效问题及替代方案

错误原因

你遇到的Access token validation failure. Invalid audience错误,本质是EWS令牌的受众(aud字段)是EWS服务端点(比如https://outlook.office365.com/EWS/Exchange.asmx),而Microsoft Graph API要求令牌的受众必须是https://graph.microsoft.com,所以直接用EWS令牌调用Graph肯定会被拒绝。

下面是几种可行的解决办法:

方案1:令牌交换(Token Exchange)获取Graph有效令牌

通过OAuth 2.0的令牌交换流程,把你的EWS访问令牌转换成针对Graph的访问令牌,步骤如下:

  • 向Azure AD的令牌端点发送POST请求,参数包括:
    • grant_type: urn:ietf:params:oauth:grant-type:token-exchange
    • client_id: 你的Azure AD应用客户端ID(需提前注册并配置对应权限)
    • client_secret: 应用客户端密钥(后端服务调用场景需要)
    • subject_token: 你现有的EWS访问令牌
    • subject_token_type: urn:ietf:params:oauth:token-type:access_token
    • resource: https://graph.microsoft.com
  • 成功请求后会返回针对Graph的访问令牌,用这个令牌调用https://graph.microsoft.com/v1.0/me/messages/${itemId}/attachments/${attachmentId}即可获取附件内容。
  • 注意:你的Azure AD应用需要拥有Mail.Read的Graph权限,且EWS令牌的权限范围要覆盖对应邮件访问权限。

方案2:直接用EWS API获取附件(无需Graph)

既然你已经有合法的EWS令牌,直接用EWS API获取附件反而更直接,不用绕令牌交换:

  • 用ews-javascript-api的Node.js示例代码:
const ews = require('ews-javascript-api');

// 初始化EWS服务
const service = new ews.ExchangeService(ews.ExchangeVersion.Exchange2016);
service.Credentials = new ews.OAuthCredentials(你的EWS令牌);
service.Url = new ews.Uri("https://outlook.office365.com/EWS/Exchange.asmx");

// 获取附件并转Base64
async function getAttachment(attachmentId) {
  const attachment = await service.GetAttachment(new ews.AttachmentId(attachmentId), ews.BodyType.Text);
  const base64Content = Buffer.from(attachment.Content).toString('base64');
  // 后续调用AWS SDK的putObject方法上传到S3即可
}

方案3:Outlook加载项前端场景直接用Office.js获取附件

如果你的流程是从Outlook加载项发起的,完全可以跳过后端的EWS/Graph调用,直接在前端用Office.js获取附件:

// 假设已拿到目标附件ID
Office.context.mailbox.item.attachments.getAsync(attachmentId, function(result) {
  if (result.status === Office.AsyncResultStatus.Succeeded) {
    const attachment = result.value;
    // 获取附件内容
    attachment.getContentAsync(function(contentResult) {
      if (contentResult.status === Office.AsyncResultStatus.Succeeded) {
        // 将ArrayBuffer转为Base64
        const base64Content = btoa(String.fromCharCode(...new Uint8Array(contentResult.value)));
        // 可通过后端接口中转或直接用AWS SDK前端上传到S3
      }
    });
  }
});

这个方案最简洁,无需处理令牌相关问题,直接利用Office.js原生能力。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 11:50:21