使用 imap_tools或 imaplib,如何通过重复获取整个 imap 数据库来同步 imap 更改而不是轮询?

问题描述

因为有几个类似的问题,我想说得非常准确。

编辑:让我们专注于对从一个文件夹移动到另一个文件夹的任何电子邮件进行动态反应。

典型的 imap 客户端应用程序仅获取自上次同步以来 imap 数据库中的更改。如果您的电子邮件客户端每次运行时都必须获取每封电子邮件,那将需要很长时间。

不幸的是,我的 imap_tools 应用程序每次运行时都必须获取(仅限标题)整个 imap 数据库。为了动态检测变化,我必须反复轮询整个消息集。显然,这不是一个合理的设计。

imap_tools(或底层的 imaplib)是否提供同步机制?

不是使用“seen”标志。那是为了指示人是否已经阅读了消息,也不是针对特定客户端的。

依赖 uid 不完全是因为我想检测用户是否已将邮件从一个文件夹删除或移动到另一个文件夹。

解决方法

您可以:

  • 对限制数据集使用搜索参数:date_gte、date_lt、new ...
  • 如果您存储某些内容,则依赖于标头中的 message-id
  • 使用mailbox.move 来代替标记可靠的“标记”味精
  • 计算 msg 哈希

一切都取决于你的任务。

据我所知,IMAP 中没有“同步”,有 IDLE,但是 imap_tools 做不到。

,

从本质上讲,IMAP 是一种陈旧且效率不高的协议,因为其设计并未专注于同步。 Kundrát 称之为 Cache Filing Protocol:服务器是唯一的真实来源,客户端的工作是向用户显示它,并且通常缓存尽可能多的信息。

在 Baseline IMAP 中,这通常意味着连接到服务器,并询问和缓存客户端想要显示的尽可能多的信息。消息、标题、标志、可能是正文、可能是附件的数量。

它还假设客户端在使用时拥有最稳定的网络连接,这适用于大多数桌面模式客户端。同步完所有数据后,服务器可以在收到新消息时向您发送 unsolicited responsesEXISTSSTORE 标记更新时,EXPUNGE 消息删除时。除非响应允许的用户命令,否则服务器通常不会发送这些。老客户通常为此使用 NOOP,或者可能使用 CHECK

如果您失去连接,客户端将重新连接并刷新其缓存。由于消息唯一可变的东西是它们的存在和标志,这通常相当快:客户端通常会请求所有消息的所有标志。从那里它可以快速更新其缓存。应用标志。获取它发现的新 UID 的标头,删除它没有收到的 UID 的缓存版本。

当一个文件夹有数以万计的邮件时,这确实开始崩溃,您会发现此时客户端在某些服务器上的启动/同步速度非常慢,并且开始使用大量数据.

作为协议的 IMAP 无法跨文件夹跟踪邮件。每个文件夹的状态是完全独立的。如果它被移动,它相当于从一个文件夹中删除并添加到另一个文件夹。桌面客户端通常会维护一个连接池,以便一次查看多个文件夹。您可以对缓存的邮件应用启发式方法来尝试检测文件夹移动(例如,选择的标题和元数据),但它不可能完美。


如您所见,一旦您的邮箱增长到超过几百封邮件,其中的很多内容就会变得非常低效,因此有很多的扩展程序可以提高缓存效率。

UIDPLUS (RFC4315) 几乎无处不在。这需要服务器在更多命令中支持 UID,并且几乎所有缓存模式客户端都需要,因为在涉及删除时消息序列号不可靠。

IDLE (RFC 2177) 相当普遍,但并非无处不在。客户端可以发出 IDLE 命令,这会告诉服务器它已准备好随时进行这些未经请求的更新。这意味着客户端不必每隔几分钟就使用 NOOP 命令进行轮询。

CONDSTORE (RFC 4551) 在大多数 unix 类型服务器和一些商业服务器上。除其他外,它还将序列号与标志更改相关联。这允许标志重新同步步骤仅从它知道的最新序列号中获取更改。然而,它无助于检测已删除的邮件,并且在断开连接后仍然需要 UID SEARCH ALL 才能找到这些邮件。

QRESYNC (RFC5162) 提供已删除邮件的重新同步数据。不幸的是,这是一个非常罕见的扩展,在大型商业服务器上几乎不存在。

NOTIFY (RFC5465) 几乎无处可去。应该是可以同时监控多个邮箱的super-IDLE。

Gmail Extensions 当然是 Gmail 特有的。它,除其他外,将永久标识符与每条消息 (X-GM-MSGID) 相关联,这确实允许跨文件夹可靠地跟踪它。它还提供“ALL MAIL”文件夹和标签,这意味着您可以通过同步“所有邮件”文件夹来同步整个帐户。与其他服务器一样,在处理数万条消息时,这确实会导致带宽效率低下。


根据我参与开发多个移动电子邮件客户端的经验,这些客户端强调带宽效率和响应能力,即使在处理 IMAP 的所有问题时,客户端也可以表现得非常响应。 IDLE 可用于尝试保持收件箱同步。如果你不能这样做,你可以通过只保持最近一周的消息完全同步来隐藏很多卡顿,并且不那么频繁地同步其余的(UID SEARCH SINCE 在这里很有帮助)。用户通常只看收件箱的末尾,一般只关心收到的新邮件。

一般来说,镜像消息的移动实际上只是被检测为删除和添加,这只是互联网连接和服务器超快,对用户来说可能需要几百毫秒的时间。如果发生任何优化,则是启发式的。我认为 Thunderbird 可以有一个可以打开的协议日志。如果你真的很好奇它在做什么,打开它并移动一条消息,看看它做了什么。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...