MailKit IMAP仅获取新的,而不是下载的消息

问题描述 投票:1回答:1

我正在使用MailKit来实现IMAP电子邮件客户端。在各种示例中,我看到获取邮件头的代码是这样的:

var messages = client.Inbox.Fetch (0, -1, MessageSummaryItems.Full | MessageSummaryItems.UniqueId).ToList();

如果我已经正确理解,这将始终提取所有消息。

我的想法是保存已经提取的本地数据库消息,然后,对于后续提取,只获得差异。有没有办法实现这个目标?谢谢

c# imap mailkit mimekit
1个回答
1
投票

有没有办法实现这个目标?

当然是。 API允许您为所需的任何消息集请求信息,无论您是要通过索引还是通过UID引用它们。

真正的问题是“如何?”这一切都取决于两件事:

  1. IMAP服务器支持的IMAP扩展
  2. 电子邮件客户端的设计以及您如何选择填充消息摘要信息的缓存(需要在UI中填充ListView或TreeView消息)。

如果您的IMAP服务器支持QRESYNC扩展,那么您将需要阅读该规范,以便了解如何最好地使用它以及查看ImapFolder.Open (FolderAccess access, uint uidValidity, ulong highestModSeq, IList uids, CancellationToken cancellationToken)方法。

如果IMAP服务器不支持QRESYNC,您可能需要考虑利用CONDSTORE扩展。您可以使用任何采用modseq值的Fetch()或FetchAsync()方法来利用此扩展。

最后,您的代码最终会看起来像这样(未经测试):

var uidValidity = cache.GetUidValidity ();
var known = cache.GetKnownUids ();
UniqueIdSet missing;

folder.MessageFlagsChanged += OnMessageFlagsChanged;

if (client.Capabilities.HasFlag (ImapCapabilities.QuickResync)) {
    var highestModSeq = cache.GetHighestKnownModSeq ();

    folder.MessagesVanished += OnMessagesVanished;

    // This version of the Open() method will emit MessagesVanished and MessageFlagsChanged
    // for all messages that have been expunged or have changed since the last session.
    folder.Open (FolderAccess.ReadWrite, uidValidity, highestModSeq, known);

    if (folder.UidValidity != uidValidity) {
        // our cache is no longer valid, we'll need to start over from scratch
        cache.Clear ();
        cache.SetUidValidity (folder.UidValidity);

        missing = folder.Search (SearchQuery.All);
    } else {
        // figure out which messages we are missing in our cache
        missing = new UniqueIdSet (SortOrder.Ascending);
        var all = folder.Search (SearchQuery.All);
        foreach (var uid in all) {
            if (!known.Contains (uid))
                missing.Add (uid);
        }
    }
} else {
    folder.MessageExpunged += OnMessageExpunged;
    folder.Open (ImapFolder.ReadWrite);

    if (folder.UidValidity != uidValidity) {
        // our cache is no longer valid, we'll need to start over from scratch
        cache.Clear ();
        cache.SetUidValidity (folder.UidValidity);

        missing = folder.Search (SearchQuery.All);
    } else {
        var all = folder.Search (SearchQuery.All);

        // purge messages from our cache that have been purged on the remote IMAP server
        foreach (var uid in known) {
            if (!all.Contains (uid))
                cache.Remove (uid);
        }

        // sync flag changes since our last session
        known = cache.GetKnownUids ();
        if (known.Count > 0) {
            IList<IMessageSummary> changed;
            if (client.Capabilities.HasFlag (ImapCapabilities.CondStore)) {
                var highestModSeq = cache.GetHighestKnownModSeq ();
                changed = folder.Fetch (known, highestModSeq, MessageSummaryItems.Flags | MessageSummaryItems.ModSeq | MessageSummaryItems.UniqueId);
            } else {
                changed = folder.Fetch (known, MessageSummaryItems.Flags | MessageSummaryItems.UniqueId);
            }

            foreach (var item in changed) {
                // update the cache for this message
                cache.Update (item);
            }
        }

        // figure out which messages we are missing in our cache
        missing = new UniqueIdSet (SortOrder.Ascending);
        foreach (var uid in all) {
            if (!known.Contains (uid))
                missing.Add (uid);
        }
    }
}

// fetch the summary information for the messages we are missing
var fields = MessageSummaryItems.Full | MessageSummaryItems.UniqueId;

if (client.Capabilities.HasFlag (ImapCapabilities.CondStore))
    fields |= MessageSummaryItems.ModSeq;

var newMessages = folder.Fetch (missing, fields);
foreach (var message in newMessages)
    cache.Add (message);

cache.SetHighestModSeq (folder.HighestModSeq);

然后你需要至少有以下事件处理程序:

void OnMessageFlagsChanged (object sender, MessageFlagsChangedEventArgs e)
{
    cache.Update (e.Index, e.Flags, e.ModSeq);
}

void OnMessageExpunged (object sender, MessageExpungedEventArgs e)
{
    cache.Remove (e.Index);
}

void OnMessagesVanished (object sender, MessagesVanishedEventArgs e)
{
    cache.RemoveRange (e.UniqueIds);
}
© www.soinside.com 2019 - 2024. All rights reserved.