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

使用Graph API读取Outlook邮件时‘Resource not found for the segment’错误排查

问题:Outlook Web加载项调用Graph API时出现“Resource not found for the segment”错误

背景

我开发了一款Outlook Web加载项,通过Graph API读取Exchange Server中当前选中的邮件并做后续处理,采用Nested App Authentication(NAA)认证方式,本地测试正常,但部分测试员出现异常。

核心代码

C#后端代码(引用Microsoft.Graph 5.88.0)

private static async Task<Stream> GetEmailMessageAsync(MailboxItemModel mailboxItem) =>
    await GetGraphClient(mailboxItem).Me.Messages[mailboxItem.ItemId].Content.GetAsync();

private static GraphServiceClient GetGraphClient(MailboxItemModel mailboxItem) =>
    new GraphServiceClient(new ExistingTokenProvider(mailboxItem.Token));

private sealed class ExistingTokenProvider : IAuthenticationProvider {

    private readonly string _token;

    public ExistingTokenProvider(string token) => _token = token;

    public Task AuthenticateRequestAsync(
        RequestInformation request,
        Dictionary<string, object> additionalAuthenticationContext = null,
        CancellationToken cancellationToken = new CancellationToken()) {
        request.Headers["Authorization"] = new[] { "Bearer " + _token };
        return Task.CompletedTask;
    }
}

JavaScript前端代码(获取ItemId和Token)

/** Public Client Application for getting tokens.
 * @type {import('@azure/msal-browser').IPublicClientApplication}
 * @readonly
 */
var _pca = undefined;

var initialiseNAA = function() {
    var clientId = ViewState.GetMsalClientId();
    console.log("Creating NPCA for client " + clientId + "...");
    msal.createNestablePublicClientApplication({ auth: { clientId: clientId } }).then(
        function(pca) {
            _pca = pca;
            console.log("Created NPCA for client " + clientId + ".");
        },
        function(error) {
            console.log("Failed to create NPCA for client " + clientId + ": " + JSON.stringify(error));
        });
};

/** Get Exchange data for the selected mailbox item.
 * @param {getMailboxItemOnSuccess} onSuccess Continuation to run when the data has been read.
 */
var getMailboxItem = function(onSuccess) {
    console.log("Getting Exchange data...");
    var itemId = Office.context.mailbox.item.itemId;
    console.log("itemId: " + itemId);
    var afterSave = function() {
        var request = { scopes: ViewState.GetMsalScope().split(" ") };
        console.log("Acquiring PCA token silently...");
        _pca.acquireTokenSilent(request).then(
            function(result) {
                console.log("Acquired PCA token silently.");
                //console.log("graphToken: " + result.accessToken);
                onSuccess({ url: _graphUrl, token: result.accessToken, itemId: itemId });
            },
            function(error1) {
                console.log("Failed to acquire PCA token silently: " + JSON.stringify(error1));
                if(error1 instanceof msal.InteractionRequiredAuthError) {
                    console.log("Acquiring PCA token interactively...");
                    _pca.acquireTokenPopup(request).then(
                        function(result) {
                            console.log("Acquired PCA token interactively.");
                            //console.log("graphToken: " + result.accessToken);
                            onSuccess({ url: _graphUrl, token: result.accessToken, itemId: itemId });
                        },
                        function(error2) {
                            console.log("Failed to acquire PCA token interactively: " + JSON.stringify(error2));
                            _handleOfficeError(error2, "Cannot get a PCA token to read the mailbox item.");
                        }
                    );
                } else {
                    _handleOfficeError(error1, "Cannot get a PCA token to read the mailbox item.");
                }
            }
        );
    };
    if(itemId) {
        // We have the item ID already, it's safe to continue.
        afterSave();
    } else {
        // We must save the item first before we can read data.
        console.log("Saving the item first...");
        Office.context.mailbox.item.saveAsync(function(saveAsyncResult) {
            if(saveAsyncResult.status !== Office.AsyncResultStatus.Succeeded) {
                _handleOfficeError(saveAsyncResult, "Cannot save a draft of the mailbox item.");
                return;
            }
            itemId = saveAsyncResult.value;
            console.log("itemId: " + itemId);
            afterSave();
        });
    }
};

加载项清单XML(NAA配置)

<WebApplicationInfo xmlns="http://schemas.microsoft.com/office/mailappversionoverrides/1.1">
    <Id>MY_CLIENT_ID</Id>
    <Resource>api://MY_SITE/MY_CLIENT_ID</Resource>
    <Scopes>
        <Scope>Mail.Read</Scope>
        <Scope>Mail.Read.Shared</Scope>
    </Scopes>
</WebApplicationInfo>

注:MY_CLIENT_ID对应多租户Entra应用,已按官方文档配置SPA重定向URL,仅用于NAA认证。

错误信息

测试员反馈的异常格式如下,错误中的段名称为随机字母数字串,每次报错都会变化:

Type: Microsoft.Graph.Models.ODataErrors.ODataError
Message: Resource not found for the segment '5NET4'.
AdditionalData:
Error: {"AdditionalData":{},"BackingStore":{"ReturnOnlyChangedValues":false,"InitializationCompleted":true},"Code":"RequestBroker--ParseUri","Details":null,"InnerError":null,"Message":"Resource not found for the segment '5NET4'.","Target":null}
ResponseStatusCode: 400
ResponseHeaders:
    Cache-Control: private
    Date: Mon, 11 Aug 2025 07:29:44 GMT
    strict-transport-security: max-age=31536000
    request-id: 6a6dda61-78ce-4ce9-a3c1-8c668953f9b3
    client-request-id: 14f88e88-c493-4095-b5f6-56159ab0de6e
    x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"North Europe","Slice":"E","Ring":"4","ScaleUnit":"005","RoleInstance":"DU6PEPF00021B6F"}}
HResult: 0x80131500
Source: Microsoft.Kiota.Http.HttpClientLibrary
TargetSite: Void MoveNext()
StackTrace:
   at Microsoft.Kiota.Http.HttpClientLibrary.HttpClientRequestAdapter.<ThrowIfFailedResponseAsync>d__28.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Kiota.Http.HttpClientLibrary.HttpClientRequestAdapter.<SendPrimitiveAsync>d__21`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.Kiota.Http.HttpClientLibrary.HttpClientRequestAdapter.<SendPrimitiveAsync>d__21`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Graph.Me.Messages.Item.Value.ContentRequestBuilder.<GetAsync>d__3.MoveNext()

异常现象

  • 一位测试员修改Office许可地区后错误消失;
  • 另一位测试员即使许可地区正确仍报错;
  • 更新:测试员A上午持续报错,未做任何更改自行恢复正常;测试员B仍无法使用。

排查方向

  1. ItemId格式问题:

    • Outlook Web中的ItemId可能存在编码差异,部分环境下获取的ItemId需要经过转换才能用于Graph API。尝试使用Office.context.mailbox.convertToRestId(itemId, Office.MailboxEnums.RestVersion.v2_0)转换ItemId后再传入后端,避免直接使用原始ID导致Graph API解析错误。
  2. NAA认证的令牌范围/租户问题:

    • 检查测试员的租户是否在Entra应用的多租户允许范围内;
    • 确认令牌的aud(受众)和scopes是否正确,确保令牌包含Mail.Read或Mail.Read.Shared权限,且受众指向Graph API而非自定义资源URI。
  3. Graph API端点环境差异:

    • 不同地区的Office 365环境可能对应不同的Graph API端点,检查测试员所在地区是否需要切换端点,后端创建GraphServiceClient时需根据环境配置正确的BaseUrl。
  4. 缓存或会话问题:

    • 测试员A自行恢复可能是缓存过期,建议让测试员B清除浏览器缓存、重启Outlook Web会话,或重新授权加载项,排查是否是旧令牌/会话数据导致的异常。
  5. ItemId有效性问题:

    • 确认报错时的ItemId是否有效,是否存在邮件已被删除、移动,或权限不足的情况;对于草稿邮件,确保saveAsync返回的ItemId确实是持久化的有效ID。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 13:27:03