如何通过MS Graph API从共享邮箱发送带.eml附件的邮件
解决MS Graph API发送带ItemAttachment(.eml)邮件时的'item'缺失错误
我们的项目需求是从共享邮箱读取邮件并获取附件,再转发至其他邮箱。目前已通过MS Graph API实现仅带FileAttachment的邮件发送功能,但无法发送带ItemAttachment(.eml格式)的邮件,运行代码时出现**'item'缺失**的错误。
错误原因
- 获取邮件时,默认的
Expand("attachments")仅展开附件基础信息,不会加载ItemAttachment对应的Item内容(即.eml邮件本身),导致发送时Graph API找不到必要的item数据。 - 代码中使用
Task.Run().Result和.Wait()同步等待异步方法,可能引发死锁,同时不符合异步编程规范。
修复方案
- 修改邮件查询语句,确保展开
attachments.item以加载ItemAttachment的完整内容。 - 发送邮件时重新构造
ItemAttachment对象,确保Item属性正确赋值。 - 替换同步等待写法,改用
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); } }
关键修改点说明
- 查询扩展:通过
attachments($expand=item)强制加载ItemAttachment对应的.eml内容,解决'item'缺失问题。 - 异步规范:移除所有同步等待写法,改用
await处理异步操作,避免死锁风险。 - 附件重构:发送时重新构造附件集合,确保
ItemAttachment的Item属性正确传递,避免原集合的引用异常。 - 逻辑优化:将转发逻辑移至附件循环外,避免同一邮件因多个符合条件的附件重复转发。
内容的提问来源于stack exchange,提问作者Madhu Chepuroju
相关产品推荐
相关产品推荐

