Mailkit:获取邮件并将它们复制到 MySQL,附件到驱动器

Mailkit: fetch messages and copying them to MySQL, attachments to drive

到目前为止,我一直在使用 MailSystem.Net 的 this code 从 Imap 收件箱获取电子邮件,并添加了使用 $"SENTSINCE {Date}" 检索邮件的选项。

string mailBox = "INBOX";
public IEnumerable<Message> GetMailsSince(string mailBox) {
  return GetMails(mailBox, $"SENTSINCE {DateTime.Now.AddDays(-3).ToString("dd-MMM-yyyy")}").Cast<Message>();
}

private MessageCollection GetMails(string mailBox, string searchPhrase) {
  Mailbox mails = Client.SelectMailbox(mailBox);
  MessageCollection messages = mails.SearchParse(searchPhrase);
  return messages;
}

但即使在研究了几个小时的 mailkit 之后,我似乎也无法提炼出如何做同样的事情。我的目标是获取一个消息对象列表,然后我可以将其属性映射到我创建的另一个 class 并将其写入 mysql 数据库。我还想将附件保存到磁盘。到目前为止,所有这些工作正常,但性能是一个问题。我希望 mailkit 能大大改善这一点。

我的主要来源是the sample here,但因为我还不熟悉异步编程和树视图,所以很难看透它。

如何将我想要的 "INBOX" 硬编码为“IMailFolder”? 我可以在哪里或如何使用 Mailkit 中的 "SENTSINCE {Date}" 过滤器? 我如何获得 Mailkits 的“IEnumerable”等同于邮件系统中的 Message 对象(可能是“IMessageSummary”)?

如果您能给我指点一些代码,甚至可以将链接的 MailSystem.Net 示例转换为 Mailkit,那就太棒了。

"Inbox" 文件夹在 IMAP 邮件帐户上始终可用。对于 MailKit,它可以作为 ImapClient.Inbox 使用。对于日期过滤,您可以使用 DateSearchQuery class。 MailKit 的入门页面几乎涵盖了您所有的问题。

MimeMessage 相当于 MailSystem.NET 的 Message object,但这不是您想要的。您想要的是 MailKit 的 IMessageSummary,它将允许您下载单独的 MIME 部分(又名 "attachments")。

它还允许您获取有关邮件的摘要信息(标志、接收日期(又名 "InternalDate")pre-parsed/decoded 常见 header 值(例如主题、发件人、收件人、等)非常快,因为 IMAP 服务器将这些信息缓存在其数据库中以便快速检索。

using (var client = new ImapClient ()) {
    client.Connect ("imap.mail-server.com", 993, SecureSocketOptions.SslOnConnect);
    client.Authenticate ("username", "password");

    // if you don't care about modifying message flags or deleting
    // messages, you can open the INBOX in read-only mode...
    client.Inbox.Open (FolderAccess.ReadOnly);

    // search for messages sent since a particular date
    var uids = client.Inbox.Search (SearchQuery.SentAfter (date));

    // using the uids of the matching messages, fetch the BODYSTRUCTUREs
    // of each message so that we can figure out which MIME parts to
    // download individually.
    foreach (var item in client.Inbox.Fetch (uids, MessageSummaryItems.BodyStructure MessageSummaryItems.UniqueId)) {
        foreach (var attachment in item.Attachments.OfType<BodyPartBasic> ()) {
            var part = (MimePart) client.Inbox.GetBodyPart (item.UniqueId, attachment);

            using (var stream = File.Create (part.FileName))
                part.ContentObject.DecodeTo (stream);
        }
    }
}

注意:IMessageSummary 上的每个 属性 都有一个相应的 MessageSummaryItems 枚举值,您需要使用该枚举值来填充 属性。

例如,如果您想使用 IMessageSummary.Envelope,则需要在 Fetch() 请求中包含 MessageSummaryItems.Envelope

由于 MessageSummaryItems 标有 [Flags] 属性,您可以 bitwise-or 像这样一起枚举值:

MessageSummaryItems.BodyStructure | MessageSummaryItems.Envelope 两条信息都会被抓取。

更新:

这是更接近于 MailSystem.NET 的低效方式。

using (var client = new ImapClient ()) {
    client.Connect ("imap.mail-server.com", 993, SecureSocketOptions.SslOnConnect);
    client.Authenticate ("username", "password");

    // if you don't care about modifying message flags or deleting
    // messages, you can open the INBOX in read-only mode...
    client.Inbox.Open (FolderAccess.ReadOnly);

    // search for messages sent since a particular date
    var uids = client.Inbox.Search (SearchQuery.SentAfter (date));

    // using the uids of the matching messages, fetch the BODYSTRUCTUREs
    // of each message so that we can figure out which MIME parts to
    // download individually.
    foreach (var uid in uids) {
        var message = client.Inbox.GetMessage (uid);

        foreach (var attachment in message.Attachments.OfType<MimePart> ()) {
            using (var stream = File.Create (attachment.FileName))
                attachment.ContentObject.DecodeTo (stream);
        }
    }
}

注意:如果您关心保存 message/rfc822 个附件,请查看这个 Whosebug 答案:MailKit save Attachments