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

如何通过MS Graph API从共享邮箱发送带.eml附件的邮件

解决MS Graph API发送带ItemAttachment(.eml)邮件时的'item'缺失错误

我们的项目需求是从共享邮箱读取邮件并获取附件,再转发至其他邮箱。目前已通过MS Graph API实现仅带FileAttachment的邮件发送功能,但无法发送带ItemAttachment(.eml格式)的邮件,运行代码时出现**'item'缺失**的错误。

错误原因

  1. 获取邮件时,默认的Expand("attachments")仅展开附件基础信息,不会加载ItemAttachment对应的Item内容(即.eml邮件本身),导致发送时Graph API找不到必要的item数据。
  2. 代码中使用Task.Run().Result和.Wait()同步等待异步方法,可能引发死锁,同时不符合异步编程规范。

修复方案

  1. 修改邮件查询语句,确保展开attachments.item以加载ItemAttachment的完整内容。
  2. 发送邮件时重新构造ItemAttachment对象,确保Item属性正确赋值。
  3. 替换同步等待写法,改用await处理异步操作。

修改后的完整代码

internal static async Task<IEnumerable> ProcessMessages(string Withattachments, string Withoutattachments, MM_Mailbox MailboxAddress)
{
    string checkMails = ConfigurationManager.AppSettings["mailsNotToKofax"];
    // 关键修改:展开attachments的item属性,加载.eml附件内容
    var topTenMessagesQuery = graphClient.Users[MailboxAddress.MailBoxSMTPAddress]
        .MailFolders["Inbox"]
        .Messages
        .Request()
        .Filter("isRead ne true")
        .Top(10)
        .Expand("attachments($expand=item)");

    var topTenMessages = await topTenMessagesQuery.GetAsync();

    foreach (var message in topTenMessages)
    {
        int data = 0;
        if (message.HasAttachments == true)
        {
            try
            {
                foreach (Attachment attachment in message.Attachments)
                {
                    if (attachment is FileAttachment fileAttachment)
                    {
                        if (fileAttachment.ContentId != null)
                        {
                            var lowerContentId = fileAttachment.ContentId.ToLower();
                            if (lowerContentId.Contains("pdf") || lowerContentId.Contains("htm") || 
                                lowerContentId.Contains("tif") || lowerContentId.Contains("doc"))
                            {
                                data = 1;
                            }
                        }
                    }
                    else if (attachment is ItemAttachment itemAttachment)
                    {
                        if (attachment.ContentType.ToLower().Contains("message"))
                        {
                            data = 1;
                        }
                    }
                }

                // 优化逻辑:避免同一邮件因多个附件重复转发
                if (data == 1)
                {
                    await fwdEmailToSaleForce(message, IlistMBForward, smptpadd, MailboxAddress, 0);
                    await graphClient.Users[MailboxAddress.MailBoxSMTPAddress]
                        .Messages[message.Id]
                        .Move(Withoutattachments)
                        .Request()
                        .PostAsync();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("处理邮件时出错:", ex);
            }
        }
    }

    return topTenMessages;
}

internal static async Task<bool> fwdEmailToSaleForce(Message message, List<MM_Mailbox_Forward> toAddress, string smptpadd, MM_Mailbox MailboxAddress, int data)
{
    var result = toAddress.FirstOrDefault(x => x.MailBoxSMTPAddress == smptpadd && x.Enabled == "1");
    try
    {
        string from1 = message.From.EmailAddress.Address;
        string to1 = result.ForwardURL;

        await SendEmail(from1, to1, message.Subject, message.Body, message.Attachments, smptpadd);
    }
    catch (Exception ex)
    {
        throw new Exception("转发邮件时出错:", ex);
    }
    return true;
}

internal static async Task<string> SendEmail(string fromAddress, string toAddress, string subject, ItemBody body, IMessageAttachmentsCollectionPage attachments, string relayingMailboxAddress)
{
    try
    {
        string[] toMail = toAddress.Split(',');
        List<Recipient> toRecipients = new List<Recipient>();
        foreach (string mail in toMail)
        {
            toRecipients.Add(new Recipient
            {
                EmailAddress = new EmailAddress { Address = mail }
            });
        }

        // 重新构造附件集合,确保ItemAttachment的Item属性正确传递
        var newAttachments = new MessageAttachmentsCollectionPage();
        foreach (var attachment in attachments)
        {
            if (attachment is FileAttachment fileAttachment)
            {
                newAttachments.Add(new FileAttachment
                {
                    Name = fileAttachment.Name,
                    ContentType = fileAttachment.ContentType,
                    ContentBytes = fileAttachment.ContentBytes,
                    ContentId = fileAttachment.ContentId
                });
            }
            else if (attachment is ItemAttachment itemAttachment)
            {
                newAttachments.Add(new ItemAttachment
                {
                    Name = itemAttachment.Name,
                    ContentType = itemAttachment.ContentType,
                    Item = itemAttachment.Item
                });
            }
        }

        var mailMessage = new Message
        {
            Subject = $"|{fromAddress}| {subject}",
            Body = body,
            ToRecipients = toRecipients,
            Attachments = newAttachments
        };

        await graphClient
            .Users[relayingMailboxAddress]
            .SendMail(mailMessage, false)
            .Request()
            .PostAsync();

        return "邮件发送成功。";
    }
    catch (Exception ex)
    {
        throw new Exception("发送邮件时出错:", ex);
    }
}

关键修改点说明

  1. 查询扩展:通过attachments($expand=item)强制加载ItemAttachment对应的.eml内容,解决'item'缺失问题。
  2. 异步规范:移除所有同步等待写法,改用await处理异步操作,避免死锁风险。
  3. 附件重构:发送时重新构造附件集合,确保ItemAttachment的Item属性正确传递,避免原集合的引用异常。
  4. 逻辑优化:将转发逻辑移至附件循环外,避免同一邮件因多个符合条件的附件重复转发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 01:25:05