我正在使用here中的代码使用MailKit从邮件下载附件。在检索附件的foreach循环中,它始终返回空。因为它是空的,所以它不会进入foreach循环。如果我做错了,请纠正我。
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);
}
}
答案 0 :(得分:2)
这是我用来遍历MIME树结构以获取所有可能的附件的内容。请注意,至少在我测试的电子邮件的情况下,IsAttachment
标记从未设置为true
。
首先,创建一个递归函数,以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;
}
}
然后将该功能用于“下载”功能,该功能与@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);
}
}
请注意此功能:
unnamed
计数器。您还可以添加其他逻辑,以根据您在MIME标头中获得的文件名或其他信息过滤掉文件。client.DownloadAttachments(someMessage, @"C:\tmp\attachments")
System.IO.FileInfo
个对象。这对我有用,但可能与其他人无关。这不是绝对必要的。我希望这有助于其他人。
答案 1 :(得分:0)
首先要注意的是MIME是树结构,而不是平面列表。 BodyPartMultipart可以包含其他BodyPartMultipart子节点以及BodyPartBasic子节点,因此当您遇到另一个BodyPartMultipart时,您也需要进入其中。
我的猜测是你正在检查的邮件有嵌套的多部分,这就是你遇到麻烦的原因。
要么是&#34;附件&#34;没有Content-Disposition标头,其值为&#34;附件&#34;。