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

使用Microsoft Graph API发送带附件邮件报错及批量发送异常排查

问题分析与解决方案

报错Cannot process input of abstract type 'microsoft.graph.attachment'以及批量发送时仅第一个收件人成功的核心原因是:重复复用同一个SendMailPostRequestBody及内部的Message对象。Graph SDK在第一次请求序列化后,会修改对象的内部元数据状态,导致后续请求时无法正确识别具体的FileAttachment类型,转而尝试序列化抽象的Attachment基类,触发API报错。

解决步骤

  • 每次循环生成全新的请求体对象,包括Message和附件集合,避免状态残留
  • 把GraphServiceClient的创建移到循环外,减少重复初始化开销
  • 简化MemoryStream的使用,利用using自动释放资源

修改后的代码示例

private async Task ExecuteSendEmailAsync()
{
    try
    {
        // 获取收件人列表
        List<Model.User> receivers = new();
        receivers.Add(new Model.User { EMAIL = "email@email.com" });
        List<Reservation> reservation = new();

        // 生成PDF附件字节(只做一次,复用字节数组)
        string contenuto = "<h1 style='text-align:center; font-family: Arial, Helvetica, sans-serif; font-size: 24px;' >Daily report</h1><br>";
        contenuto += "<br>";
        // 此处添加其他内容...

        byte[] pdfBytes;
        using (MemoryStream memoryStream = new MemoryStream())
        {
            Document document = new(PageSize.A4, 10f, 10f, 10f, 0f);
            HtmlWorker htmlparser = new(document);
            PdfWriter writer = PdfWriter.GetInstance(document, memoryStream);
            
            document.Open();
            htmlparser.Parse(new StringReader(contenuto));
            document.Close();
            
            pdfBytes = memoryStream.ToArray();
            // using块会自动关闭memoryStream,无需手动调用Close
        }

        // 只创建一次GraphClient,避免重复初始化
        GraphServiceClient graphClient = GraphHelper.GetAuthenticatedGraphClient("*tenant*");
        string fromEmail = "from@email.com";

        // 循环发送邮件,每次创建全新的请求体
        foreach (Model.User rec in receivers)
        {
            var requestBody = new Microsoft.Graph.Users.Item.SendMail.SendMailPostRequestBody
            {
                Message = new Message
                {
                    Subject = "test",
                    Body = new ItemBody
                    {
                        ContentType = BodyType.Text,
                        Content = "Hello, look at the attachment"
                    },
                    ToRecipients = new List<Recipient>
                    {
                        new Recipient { EmailAddress = new EmailAddress { Address = rec.EMAIL } }
                    },
                    Attachments = new List<Microsoft.Graph.Models.Attachment>
                    {
                        new FileAttachment
                        {
                            OdataType = "#microsoft.graph.fileAttachment",
                            Name = "Daily_report.pdf",
                            ContentType = "application/pdf",
                            ContentBytes = pdfBytes,
                        },
                    }
                }
            };

            await graphClient.Users[fromEmail].SendMail.PostAsync(requestBody);
        }
    }
    catch (Exception e)
    {
        string msg = "Errore durante l'invio di una mail";
        ManageExceptions.ManageLog(e, msg, "ExecuteSendEmail - ReportMensaEmailJob", "Error");
        throw;
    }
}

关键修改点

  1. PDF字节复用:把PDF生成逻辑移到循环外,只生成一次字节数组,提升性能
  2. 请求体循环内创建:每次循环都新建SendMailPostRequestBody和Message,确保对象状态干净
  3. GraphClient复用:避免在循环内重复创建认证客户端,减少资源消耗
  4. 简化流操作:移除手动的memoryStream.Close(),依赖using自动释放

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 01:57:38