使用Microsoft Graph获取Office365邮件附件遇空引用错误求助
问题原因及解决方案
问题根源
你遇到的空引用错误,是因为Microsoft Graph API默认获取邮件(Message)资源时,不会自动返回附件(Attachments)数据。即使HasAttachments为true,item.Attachments属性依然是null,直接访问CurrentPage自然会抛出空引用异常。
解决方法
结合你的需求(读取未读邮件、下载附件、标记已读),提供两种可行处理方式:
方法1:获取邮件时预加载附件(高效推荐)
在请求邮件时通过$expand参数内嵌返回附件数据,避免后续单独请求,同时可一次性完成标记已读操作:
// Auth code omitted for brevity... var graphClient = new GraphServiceClient(clientSecretCredential, scopes); var messages = await graphClient.Users["ipaqpc@mymail.com"].Messages .Request() .Filter("isRead eq false") .Expand("attachments") // 关键:预加载附件数据 .Select("id,subject,sender,hasAttachments,isRead") // 按需选择字段,提升请求性能 .GetAsync(); Console.WriteLine(messages.Count); // Returns "10". foreach (var item in messages.CurrentPage) { Console.WriteLine($"发件人:{item.Sender.EmailAddress.Address}"); // 标记邮件为已读 await graphClient.Users["ipaqpc@mymail.com"].Messages[item.Id] .Request() .UpdateAsync(new Message { IsRead = true }); if (item.HasAttachments == true) { Console.WriteLine("包含附件"); // 此时Attachments已被预加载,可直接遍历 foreach (var attachment in item.Attachments) { Console.WriteLine($"附件名称:{attachment.Name}"); // 下载文件类型附件(忽略内嵌附件等其他类型) if (attachment is FileAttachment fileAttachment) { // 将附件内容保存到本地路径 File.WriteAllBytes($"本地保存路径\\{fileAttachment.Name}", fileAttachment.ContentBytes); Console.WriteLine($"已下载附件:{fileAttachment.Name}"); } } } }
方法2:单独请求单封邮件的附件
如果邮件数量多、附件体积大,不想一次性加载所有附件,可在判断HasAttachments为true后,单独请求该邮件的附件资源:
// Auth code omitted for brevity... var graphClient = new GraphServiceClient(clientSecretCredential, scopes); var messages = await graphClient.Users["ipaqpc@mymail.com"].Messages .Request() .Filter("isRead eq false") .Select("id,subject,sender,hasAttachments,isRead") .GetAsync(); Console.WriteLine(messages.Count); // Returns "10". foreach (var item in messages.CurrentPage) { Console.WriteLine($"发件人:{item.Sender.EmailAddress.Address}"); // 标记邮件为已读 await graphClient.Users["ipaqpc@mymail.com"].Messages[item.Id] .Request() .UpdateAsync(new Message { IsRead = true }); if (item.HasAttachments == true) { Console.WriteLine("包含附件"); // 单独请求当前邮件的附件列表 var attachments = await graphClient.Users["ipaqpc@mymail.com"].Messages[item.Id].Attachments .Request() .GetAsync(); foreach (var attachment in attachments.CurrentPage) { Console.WriteLine($"附件名称:{attachment.Name}"); // 下载文件类型附件 if (attachment is FileAttachment fileAttachment) { File.WriteAllBytes($"本地保存路径\\{fileAttachment.Name}", fileAttachment.ContentBytes); Console.WriteLine($"已下载附件:{fileAttachment.Name}"); } } } }
额外注意事项
- 权限验证:确保应用已申请
Mail.ReadWrite权限(委托或应用权限),否则无法完成读取邮件、下载附件、标记已读操作。 - 附件类型处理:邮件附件包含
FileAttachment、ItemAttachment等多种类型,需根据业务需求针对性处理,示例仅覆盖常见的文件附件场景。 - 分页处理:如果未读邮件或附件数量超过默认分页限制(通常为100条),需调用
messages.NextPageRequest.GetAsync()获取后续数据。
内容的提问来源于stack exchange,提问作者Stephen McCarten
相关产品推荐
相关产品推荐

