MailKit IMAP仅获取新的而不是下载的消息 [英] MailKit IMAP fetch only new, not downloaded messages

查看:303
本文介绍了MailKit IMAP仅获取新的而不是下载的消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用MailKit实施IMAP电子邮件客户端.在各种示例中,我已经看到获取消息头的代码是这样的:

i'm using MailKit to implement an IMAP email client. In the various examples i've seen that the code to fetch message headers is this one:

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

如果我正确理解,它将始终获取所有消息.

If i have correctly understood, this fetches always ALL messages.

我的想法是将已经获取的消息保存在本地db中,然后,对于后续的获取,仅获取差异. 有没有办法做到这一点? 谢谢

My idea is to save in a local db messages already fetched, and then, for subsequent fetches, getting only differences. Is there a way to accomplish this? Thanks

推荐答案

有没有办法做到这一点?

Is there a way to accomplish this?

是的,当然.该API使您可以请求所需的任何消息集的信息,无论您是要通过索引还是通过UID引用它们.

Yes, of course. The API allows you to request the information for any set of messages you want, whether you want to reference them by index or by UID.

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

The real question is "how?" and that all depends on two things:

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

如果您的IMAP服务器支持 QRESYNC 扩展名,则需要阅读该规范这样一来,您不仅可以更好地使用它,还可以查看 ImapFolder.Open (FolderAccess访问,uint uidValidity,ulong maximumModSeq,IList uid和CancellationToken cancelleToken)方法.

If your IMAP server supports the QRESYNC extension, you'll want to read that specification so that you understand how best to use it as well as taking a look at the ImapFolder.Open (FolderAccess access, uint uidValidity, ulong highestModSeq, IList uids, CancellationToken cancellationToken) method.

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

If the IMAP server doesn't support QRESYNC, you might want to look into taking advantage of the CONDSTORE extension. You can take advantage of this extension by using any of the Fetch() or FetchAsync() methods that take a modseq value.

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

In the end, your code will end up looking something like this (untested):

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);

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

And then you'd need to have at least the following event handlers:

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);
}

这篇关于MailKit IMAP仅获取新的而不是下载的消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆