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

React应用调用Microsoft Graph API发邮件遇401及租户GUID不存在错误

问题:React应用调用Microsoft Graph API发送邮件时出现401 Unauthorized及OrganizationFromTenantGuidNotFound错误

我正在开发一个React应用,尝试通过OAuth2认证使用Microsoft Graph API发送邮件,但调用时出现401 Unauthorized错误。操作流程如下:

  • 用户使用MSAL(Microsoft Authentication Library)登录,并授予Mail.Send和User.Read权限;
  • 通过msalInstance.acquireTokenPopup()获取访问令牌;
  • 使用axios.post()调用Microsoft Graph API,将访问令牌放入Authorization请求头发送邮件。

遇到的错误信息

POST https://graph.microsoft.com/v1.0/me/sendMail 401 (Unauthorized)
Error message:
Error during login or sending email: 
AxiosError {message: 'Request failed with status code 401', name: 'AxiosError', code: 'ERR_BAD_REQUEST', ...}
Response error:
{error: {code: "OrganizationFromTenantGuidNotFound", message: "The tenant for tenant guid 'd600ee99-eb85-4281-a0c5-18cc87425a9e' does not exist."}}

已尝试的操作

  • 反复检查Mail.Send和User.Read权限(附API权限截图);
  • 确认使用正确的Microsoft租户和订阅;
  • 确保账户已登录且令牌获取正常;
  • 查看邮件未收到相关问题截图。

代码实现

export const msalConfig = {
    auth: {
      clientId: "my-client-id", 
      authority: "https://login.microsoftonline.com/<tenand-id>", 
      redirectUri: "http://localhost:3000", // Adjust as per your app
    },
  };

import React from "react";
import { PublicClientApplication } from "@azure/msal-browser";
import { msalConfig } from "./msalConfig";
import axios from "axios";

const GraphApiTest = () => {
  const loginAndSendEmail = async () => {
    const msalInstance = new PublicClientApplication(msalConfig);
    await msalInstance.initialize();

    try {
      // Login and acquire access token
      const loginResponse = await msalInstance.loginPopup({
        scopes: ["Mail.Send", "User.Read"],
      });
      console.log("Login successful:", loginResponse);

      const account = msalInstance.getAllAccounts()[0];
      const tokenResponse = await msalInstance.acquireTokenPopup({
        account,
        scopes: ["Mail.Send", "User.Read"],
      });

      const accessToken = tokenResponse.accessToken;
      console.log("Access Token acquired:", accessToken);

      const emailPayload = {
        message: {
          subject: "Test Email from React App",
          body: {
            contentType: "Text",
            content: "This is a test email sent from my React app via Microsoft Graph API.",
          },
          toRecipients: [
            {
              emailAddress: {
                address: "gulzarjavaria2@gmail.com",
              },
            },
          ],
        },
        saveToSentItems: "true",
      };

      const response = await axios.post(
        "https://graph.microsoft.com/v1.0/me/sendMail",
        emailPayload,
        {
          headers: {
            Authorization: `Bearer ${accessToken}`,
            "Content-Type": "application/json",
          },
        }
      );

      console.log("Email sent successfully:", response.data);
    } catch (error) {
      console.error("Error during login or sending email:", error);

      if (error.response) {
        console.error("Response error:", error.response.data);
      }
    }
  };

  return (
    <div>
      <button onClick={loginAndSendEmail}>Send Email via Outlook</button>
    </div>
  );
};

export default GraphApiTest;

疑问

能否解释为何会出现"OrganizationFromTenantGuidNotFound"和"401 Unauthorized"错误?错误提示租户ID存在问题,我该采取哪些步骤解决此问题并成功通过Microsoft Graph API发送邮件?


解答

错误原因分析

  1. OrganizationFromTenantGuidNotFound:该错误直接指向配置的租户ID无效或不存在,可能的触发场景包括:

    • msalConfig中authority字段的<tenand-id>存在拼写错误(代码中写的是tenand-id而非正确的tenant-id,属于明显笔误);
    • 配置的租户ID与登录用户所属的租户不匹配;
    • 该租户已被删除或未在Azure AD中完成注册。
  2. 401 Unauthorized:这是租户ID错误引发的连锁问题——基于无效租户生成的访问令牌无法被Graph API识别,因此请求被拒绝。

解决步骤

1. 修正租户ID的拼写与正确性

  • 登录Azure Portal,进入Azure Active Directory,在概述页面复制正确的租户ID;
  • 更新msalConfig中的authority字段,替换为正确的租户ID,同时修正字段名笔误:
    authority: "https://login.microsoftonline.com/你的实际租户ID",
    

2. 验证用户与租户的关联关系

  • 确认你使用的.onmicrosoft.com结尾的用户确实属于上述Azure AD租户;
  • 可在Azure AD的用户列表中搜索该用户,检查其所属租户是否与配置的租户ID一致。

3. 确认应用注册的权限配置

  • 登录Azure Portal,进入你的应用注册页面,确保:
    • API权限中已添加Mail.Send和User.Read的委托权限;
    • 权限状态为已授予管理员同意(租户内用户发送邮件需管理员提前同意权限,否则普通用户无法获取有效令牌)。

4. 优化MSAL实例初始化逻辑

当前代码每次点击按钮都会创建新的PublicClientApplication实例,易导致状态不一致。建议全局初始化MSAL实例:

// 在组件外部全局初始化MSAL实例
const msalInstance = new PublicClientApplication(msalConfig);
msalInstance.initialize();

const GraphApiTest = () => {
  const loginAndSendEmail = async () => {
    try {
      // 后续逻辑直接使用全局msalInstance,无需重复创建
      // ...
    } catch (error) {
      // 错误处理
    }
  };
  // ...
};

5. 验证访问令牌有效性

获取令牌后,使用JWT解析工具检查:

  • tid字段是否为正确的租户ID;
  • scp字段是否包含Mail.Send和User.Read权限;
  • 令牌是否未过期(exp字段为过期时间戳)。

6. 修正请求体格式

Graph API要求saveToSentItems为布尔类型,将代码中的字符串"true"改为布尔值true:

saveToSentItems: true,

验证测试

完成上述修正后重新运行应用:

  1. 点击登录按钮,确认登录流程正常,获取到包含正确租户ID和权限的访问令牌;
  2. 调用发送邮件接口,检查是否返回202 Accepted状态码,同时确认收件人收到邮件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 00:52:34