使用C#结合Microsoft Graph API读取带附件邮件并转.eml等问题
使用C# + Microsoft Graph API 处理邮件的完整解决方案
1. 版本兼容性确认
Microsoft Graph SDK 5.49.0与.NET 5.0完全兼容。SDK 5.x系列官方支持.NET 5.0及以上版本(包括.NET 6.0、.NET 7.0等),无需担心版本适配问题。
2. 解决HasAttachments为true但Attachments为空的问题
默认查询邮件时,Graph API不会自动加载附件数据,因此即使HasAttachments为true,message.Attachments也会为空。解决方式有两种:
- 方式一:查询邮件时主动展开附件
在调用GetAsync()前添加.Expand("attachments"),一次性获取邮件及附件数据。 - 方式二:单独获取单封邮件的附件
针对单封邮件,调用附件接口单独拉取:_graphServiceClient.Users[userId].Messages[message.Id].Attachments.GetAsync()
3. 完整功能示例代码
以下代码包含读取带附件邮件、保存为.eml文件、移动邮件至指定文件夹的完整实现:
using Azure.Identity; using Microsoft.Graph; using Microsoft.Graph.Models; using System.IO; // 初始化GraphServiceClient(以ClientSecret认证为例,根据实际场景替换认证方式) var tenantId = "你的租户ID"; var clientId = "你的客户端ID"; var clientSecret = "你的客户端密钥"; var userId = "目标用户邮箱或ID"; var targetFolderId = "目标文件夹ID(可通过Graph API获取文件夹列表得到)"; var credential = new ClientSecretCredential(tenantId, clientId, clientSecret); var _graphServiceClient = new GraphServiceClient(credential); try { // 读取收件箱邮件,同时展开附件数据 var messages = await _graphServiceClient.Users[userId].MailFolders["inbox"].Messages .GetAsync(requestConfiguration => { requestConfiguration.QueryParameters.Expand = new string[] { "attachments" }; // 可按需添加筛选条件,比如只获取带附件的邮件 requestConfiguration.QueryParameters.Filter = "HasAttachments eq true"; }); foreach (var message in messages.Value) { Console.WriteLine($"处理邮件:{message.Subject}"); // 1. 将邮件保存为.eml文件 var mimeContent = await _graphServiceClient.Users[userId].Messages[message.Id].Content.GetAsync(); using var fileStream = new FileStream($"{message.Subject}.eml", FileMode.Create); await mimeContent.CopyToAsync(fileStream); Console.WriteLine($"已保存为EML文件:{message.Subject}.eml"); // 2. 打印附件信息(如果需要处理附件内容,可在此处扩展) if (message.Attachments != null && message.Attachments.Any()) { Console.WriteLine("附件列表:"); foreach (var attachment in message.Attachments) { if (attachment is FileAttachment fileAttachment) { Console.WriteLine($"- {fileAttachment.Name}(大小:{fileAttachment.Size}字节)"); // 如需保存附件,可使用fileAttachment.ContentBytes转换为文件 } } } // 3. 将邮件从收件箱移动至目标文件夹 await _graphServiceClient.Users[userId].Messages[message.Id].Move.PostAsync( new MovePostRequestBody { DestinationId = targetFolderId }); Console.WriteLine($"已移动邮件至目标文件夹"); } } catch (Exception ex) { Console.WriteLine($"处理出错:{ex.Message}"); }
关键代码说明
- 附件加载:通过
Expand("attachments")在查询邮件时关联加载附件,避免二次请求;若邮件数量大,也可单独获取单封邮件的附件以减少单次请求数据量。 - EML转换:调用
Messages[message.Id].Content.GetAsync()直接获取邮件的MIME格式流,写入文件即为标准.eml文件,无需额外转换逻辑。 - 邮件移动:使用
Move.PostAsync()方法,传入目标文件夹ID即可完成移动,目标文件夹ID可通过_graphServiceClient.Users[userId].MailFolders.GetAsync()获取所有邮箱文件夹的ID。
内容的提问来源于stack exchange,提问作者Akila
相关产品推荐
相关产品推荐

