【问题标题】:Unable to send large attachment using graph api无法使用图形 api 发送大附件
【发布时间】:2026-02-04 00:50:02
【问题描述】:

我正在尝试使用 Microsoft Graph 向电子邮件添加大附件。

步骤:

获取令牌:

public static async Task<GraphServiceClient> GetAuthenticatedClientForApp(IConfidentialClientApplication app)
{
    GraphServiceClient graphClient = null;
    // Create Microsoft Graph client.
    try
    {
        var token = await GetTokenForAppAsync(app);
        graphClient = new GraphServiceClient(
            "https://graph.microsoft.com/beta",
            new DelegateAuthenticationProvider(async(requestMessage) =>
            {
                requestMessage.Headers.Authorization =
                    new AuthenticationHeaderValue("bearer", token);

            }));
        return graphClient;
    }

    catch (Exception ex)
    {
        Logger.Error("Could not create a graph client: " + ex.Message);
    }

    return graphClient;
}
/// <summary>
/// Get Token for App.
/// </summary>
/// <returns>Token for app.</returns>
public static async Task<string> GetTokenForAppAsync(IConfidentialClientApplication app)
{
    AuthenticationResult authResult;
    authResult = await app
        .AcquireTokenForClient(new string[] { "https://graph.microsoft.com/.default" })
        .ExecuteAsync(System.Threading.CancellationToken.None);
    return authResult.AccessToken;
}

创建草稿:

Message draft = await client
    .Users[emailDTO.FromEmail]
    .Messages
    .Request()
    .AddAsync(msg);

附加文件:

if (emailDTO.FileAttachments != null && emailDTO.FileAttachments.Count() > 0)
{
    foreach (EmailAttachment emailAttachment in emailDTO.FileAttachments)
    {
        if (emailAttachment.UploadFile != null && emailAttachment.UploadFile.Length > 0)
        {
            var attachmentItem = new AttachmentItem
            {
                AttachmentType = AttachmentType.File,
                Name = emailAttachment.FileName,
                Size = emailAttachment.UploadFile.Length
            };
            var session = await client
                .Users[emailDTO.FromEmail]
                .MailFolders
                .Drafts
                .Messages[draft.Id]
                .Attachments
                .CreateUploadSession(attachmentItem)
                .Request()
                .PostAsync();

            var stream = new MemoryStream(emailAttachment.UploadFile);
            var maxChunkSize = 320 * 1024 * 1024;
            var provider = new ChunkedUploadProvider(session, client, stream, maxChunkSize);
            var readBuffer = new byte[maxChunkSize];
            var chunkRequests = provider.GetUploadChunkRequests();

            //var uploadedItem = await provider.UploadAsync();
            var trackedExceptions = new List<Exception>();
            foreach (var rq in chunkRequests)
            {
                var result = await provider.GetChunkRequestResponseAsync(rq, readBuffer, trackedExceptions);
            }
        }
    }
}

错误:

{
  Code: InvalidAudienceForResource
  Message: The audience claim value is invalid for current resource. 
            Audience claim is 'https://graph.microsoft.com', request url is
            'https://outlook.office.com/api/beta/User

【问题讨论】:

  • 您注册了范围吗?查看整个错误和您收到的实际令牌也会很有帮助。
  • Marc,图形应用程序是否需要此 Exchange 权限 Mail.ReadWrite Application 在所有邮箱中读写邮件。它确实有图表 > Mail.ReadWrite 权限。
  • 这是我的解决方案docs.microsoft.com/en-us/graph/sdks/…

标签: c# microsoft-graph-api microsoft-graph-sdks microsoft-graph-mail


【解决方案1】:

我认为这里的问题是创建的会话 URL 指向不在 Microsoft Graph 上的资源。但是,当您使用同一个客户端调用该端点时,它会传递属于 Graph 的不记名令牌。我相信会话 URL 在 URL 中有足够的访问令牌。

您可以更新您的 DelegateAuthenticationProvider 函数,只为 graph.microsoft.com 的主机添加授权标头。或者您可以使用我们的LargeFileUploadTask 而不是 ChunkedUploadProvider,它会为您完成大部分工作。可悲的是,我还没有完成它的文档。我很快就会回来并使用文档链接更新这篇文章。

【讨论】:

    【解决方案2】:
    var task = new Task(() =>
    {
        foreach(var attachment in attachments) {
            using(MemoryStream stream = new MemoryStream()) {
    
                var mimePart = (MimePart)attachment;
                mimePart.Content.DecodeTo(stream);
                var size = MeasureAttachmentSize(mimePart);
                var attachmentItem = MapAttachmentItem(attachment, size);
    
                // Use createUploadSession to retrieve an upload URL which contains the session identifier.
                var uploadSession = client.Users[mailbox]
                    .Messages[addedMessage.Id]
                    .Attachments
                    .CreateUploadSession(attachmentItem)
                    .Request()
                    .PostAsync()
                    .GetAwaiter()
                    .GetResult();
    
                // Max slice size must be a multiple of 320 KiB
                int maxSliceSize = 320 * 1024;
                var fileUploadTask = new LargeFileUploadTask<FileAttachment>(uploadSession
                                                                            ,stream
                                                                            ,maxSliceSize
                                                                            ,client);
    
                // Create a callback that is invoked after each slice is uploaded
                IProgress<long> progress = new Progress<long>(prog =>
                {
                    Console.WriteLine($"Uploaded {prog} bytes of {stream.Length} bytes");
                });
    
                try {
                    // Upload the file
                    var uploadResult = fileUploadTask.UploadAsync(progress, 3).Result;
    
                    if(uploadResult.UploadSucceeded) {
                        // The result includes the location URI.
                        Console.WriteLine($"Upload complete, LocationUrl: {uploadResult.Location}");
                    }
                    else {
                        Console.WriteLine("Upload failed");
                    }
                }
                catch(ServiceException ex) {
                    Console.WriteLine($"Error uploading: {ex.ToString()}");
                    throw ex;
                }
            }
        }
    });
    task.RunSynchronously();
    

    【讨论】:

    • 你应该为你的块添加一个解释。
    最近更新 更多