Mimekit/Mailkit如何下载邮件正文?

5

我最近在制作自己的邮件客户端,并添加了接收选项,我使用mimekit和mailkit作为插件,并使用阅读器下载了大部分邮件,阅读器显示内容(目前仅显示主题、收件人、发件人和日期)。

我用msg.envelope.subject, msg.envelope.to下载了主题、收件人等信息,但是我无法像这样下载正文:( 无论使用msg.body、msg.textbody、msg.bodyparts等方法,都会返回空值,应该存在的位置却是空白的,我无法下载它:(

有谁可以帮帮我吗?

1个回答

8

获取消息正文有两种方法:

1. 下载整个消息

这可能是最简单的方法。

要做到这一点,您只需要调用:

var message = folder.GetMessage (uid);

或者

var message = folder.GetMessage (index);

我建议始终使用消息的 UniqueId。既然你已经在使用 Fetch 方法,那么只需要在 fetch 请求中包含 MessageSummaryItems.UniqueId 来确保你拥有消息的 UniqueId

var messages = folder.Fetch (0, -1, MessageSummaryItems.UniqueId |
    MessageSummaryItems.Envelope | ...);

一旦您获得了消息,您可以随心所欲地处理它。

要呈现消息,我建议查看MimeKit GitHub存储库中包含的MessageReader示例。

它将向您展示如何正确呈现MimeMessage

2. 仅下载所需内容

这种方法有点困难,但在网络带宽使用方面可能更有效率。

首先,您需要确保在Fetch方法中包含MessageSummaryItems.BodyStructure位标志。例如:

var messages = folder.Fetch (0, -1, MessageSummaryItems.Envelope | 
    MessageSummaryItems.BodyStructure);

您可能需要其他字段,但这只是一个示例,向您展示如何按位或标志以请求多个消息摘要项。

通过请求消息的BodyStructure,您将能够利用msg.Body属性。

每个msg.Body都是一个抽象类BodyPart对象。两个主要子类是BodyPartMultipartBodyPartBasic。您可以使用as转换或is关键字来确定它是哪一个:

var multipart = msg.Body as BodyPartMultipart;

if (multipart != null) {
    // the top-level body part is a multi-part
} else {
    // the body is a basic singleton part
}

这是如何迭代一个BodyPartMultipart的子部分:

foreach (var part in multipart.BodyParts) {
    // each part will either be a BodyPartMultipart
    // or a BodyPartBasic, just like before...
}

还有两个BodyPartBasic的子类,分别是:BodyPartTextBodyPartMessageBodyPartText是基于文本的MIME部件(表示它具有text/* MIME类型),而BodyPartMessage是一个嵌入式消息(将具有message/rfc822 MIME类型)。

由于MIME是递归的,您需要实现一个递归函数来遍历MIME树结构,以查找您正在查找的任何MIME部件。

为了方便起见,IMessageSummary接口上的TextBodyHtmlBody属性将分别定位并返回text/plaintext/html正文部分。

然而,需要注意的是,这些属性仅在消息结构遵循标准惯例的情况下才有效(请注意我说的是惯例,没有正式标准规定消息文本在MIME层次结构中的位置)。

需要注意的是,如果您的邮件客户端将呈现HTML正文,则HTML正文部分可能是一组相关MIME部分的一部分(即multipart/related的子级),但HtmlBody属性将无法返回它,因此实现自己的递归逻辑将是更好的选择。
关于如何实现,请查看MailKit GitHub存储库中的ImapClientDemo示例。目前逻辑位于MainWindow.cs代码中。

谢谢,但我有一个问题,在mimekit文档中它一直在引用“stream”(例如,var message = MimeMessage.Load(STREAM);),我不知道这是从哪里来的,我尝试创建一个内存流,但它抛出了一个异常:值不能为空。 - user265889
好的,Load()方法解析一个流...所以如果你传入一个空流,它就不能解析它了,对吧?如果你在将其传递给Load()方法之前实际上向流中写入内容,请确保将其定位回流的开头。 - jstedfast
顺便提一下,流可以来自File.OpenRead()new FileStream(),通常就是这样。 - jstedfast
有没有一个简单的示例代码可以重用,以便下载和提取HTML和文本正文部分,而不必下载附件?MailKit GitHub示例代码并不是很直观。 - rboy
请阅读我上面的回答,它回答了你的问题:为了方便起见,IMessageSummary接口上的TextBody和HtmlBody属性将分别定位并返回text/plain和text/html正文部分。 - jstedfast
一旦您拥有了 BodyPart,您只需要调用其中一个 GetBodyPart() 重载即可:http://www.mimekit.net/docs/html/Overload_MailKit_Net_Imap_ImapFolder_GetBodyPart.htm - jstedfast

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接