[英]How to download the attachments of a email using Mailkit
I'm using the code from here to download attachments from mail using MailKit. 我正在使用此处的代码使用MailKit从邮件中下载附件。 In the foreach loop where attachments are retrieved, it is always returning empty.
在检索附件的foreach循环中,它总是返回空。 As it is empty it is not entering the foreach loop.
由于它为空,因此不会进入foreach循环。 Please correct me if i'm doing anything wrong.
如果我做错了什么,请纠正我。
var messages = client.Inbox.Fetch(0, -1, MessageSummaryItems.Full | MessageSummaryItems.UniqueId);
int unnamed = 0;
foreach (var message in messages)
{
var multipart = message.Body as BodyPartMultipart;
var basic = message.Body as BodyPartBasic;
if (multipart != null)
{
//Here the attachments is always empty even though my mail has email with attachements
var attachments = multipart.BodyParts.OfType<BodyPartBasic>().Where(x => x.IsAttachment);
foreach (var attachment in attachments)
{
var mime = (MimePart)client.Inbox.GetBodyPart(message.UniqueId.Value, attachment);
var fileName = mime.FileName;
if (string.IsNullOrEmpty(fileName))
fileName = string.Format("unnamed-{0}", ++unnamed);
using (var stream = File.Create(fileName))
mime.ContentObject.DecodeTo(stream);
}
}
else if (basic != null && basic.IsAttachment)
{
var mime = (MimePart)client.Inbox.GetBodyPart(message.UniqueId.Value, basic);
var fileName = mime.FileName;
if (string.IsNullOrEmpty(fileName))
fileName = string.Format("unnamed-{0}", ++unnamed);
using (var stream = File.Create(fileName))
mime.ContentObject.DecodeTo(stream);
}
}
Here's what I'm using to traverse the MIME tree structure to get all possible attachments out. 这就是我用来遍历MIME树结构以获取所有可能的附件的内容。 Note that at least in the case of the emails I was testing, the
IsAttachment
flag was never set to true
. 请注意,至少在我正在测试的电子邮件中,
IsAttachment
标志从未设置为true
。
First, make a recursive function that retrieves all basic body parts (which are the parts of the MIME message that contains the actual content of the message) as an IEnumerable<BodyPartBasic>
: 首先,创建一个递归函数,以
IEnumerable<BodyPartBasic>
检索所有基本主体部分(包含消息的实际内容的MIME消息部分):
private static IEnumerable<BodyPartBasic> GetBasicBodyParts(this BodyPart part)
{
var multipart = part as BodyPartMultipart;
var basic = part as BodyPartBasic;
if (multipart != null)
{
foreach (var subPart in multipart.BodyParts)
{
if (subPart is BodyPartBasic)
{
yield return subPart as BodyPartBasic;
}
else
{
foreach (var subSubPart in subPart.GetBasicBodyParts())
{
yield return subSubPart;
}
}
}
} else if (basic != null)
{
yield return basic;
}
else
{
yield break;
}
}
And then put that function to use within a "download" function that is very similar to what @jstedfast has provided in other posts: 然后将该函数在“下载”函数中使用,该函数与@jstedfast在其他文章中提供的非常相似:
public static IEnumerable<FileInfo> DownloadAttachments(this EmailClient client, IMessageSummary message,
string destination)
{
fileNameFilter = fileNameFilter ?? AlwaysTrue;
if (!Directory.Exists(destination))
Directory.CreateDirectory(destination);
var folder = client.Inbox;
folder.Open(FolderAccess.ReadOnly);
foreach (var part in message.Body.GetBasicBodyParts())
{
var mimeHeader = (MimePart) folder.GetBodyPart(message.UniqueId.Value, part, headersOnly: true);
var headerFileName = mimeHeader.FileName;
if (string.IsNullOrWhiteSpace(headerFileName))
continue;
var mime = (MimePart) folder.GetBodyPart(message.UniqueId.Value, part);
var fileName = mime.FileName;
var filePath = Path.Combine(destination, fileName);
using (var stream = File.Create(filePath))
mime.ContentObject.DecodeTo(stream);
yield return new FileInfo(filePath);
}
}
Note that this function: 请注意此功能:
unnamed
counter from @jstedfast's other examples. unnamed
计数器。 You could also add in other logic to filter out files based on filename or other information you'd get in the MIME header. client.DownloadAttachments(someMessage, @"C:\\tmp\\attachments")
client.DownloadAttachments(someMessage, @"C:\\tmp\\attachments")
System.IO.FileInfo
objects for each attachment saved. System.IO.FileInfo
对象。 This was useful for me but may not be relevant to others. I hope this helps other folks. 我希望这对其他人有帮助。
The first thing to note is that MIME is a tree structure and not a flat list. 首先要注意的是MIME是树结构而不是平面列表。 A BodyPartMultipart can contain other BodyPartMultipart children as well as BodyPartBasic children, so when you come across another BodyPartMultipart, you need to descend into that as well.
BodyPartMultipart可以包含其他BodyPartMultipart子代以及BodyPartBasic子代,因此当您遇到另一个BodyPartMultipart时,您也需要进入该子代。
My guess is that the messages you are examining have nested multiparts and that is why you are having trouble. 我的猜测是您正在检查的消息具有嵌套的多个部分,这就是您遇到麻烦的原因。
Either that or the "attachments" do not have a Content-Disposition header with a value of "attachment". 那个或“附件”都没有一个值为“ attachment”的Content-Disposition标头。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.