仅从 IMAP 服务器获取新邮件
Posted
技术标签:
【中文标题】仅从 IMAP 服务器获取新邮件【英文标题】:Getting only new mail from an IMAP server 【发布时间】:2010-11-08 06:13:06 【问题描述】:我正在编写一个客户端应用程序,它从 IMAP 服务器获取电子邮件,然后将它们存储在数据库中。问题是,一旦我检查了邮件,下次我只想下载从那以后到达的邮件。因此,如果我在两小时前检查了服务器的邮件,我只想获取最近两小时内到达的邮件。
我可以将 SEARCH 与 SINCE DATE 一起使用,但不支持时间 + 日期很容易被欺骗。
我也尝试了 RECENT 标志,但这似乎不适用于 gmail(在 ruby 中,它每次都显示 nil)。
【问题讨论】:
【参考方案1】:您希望对消息使用 UniqueId (UID)。这就是创建它的具体原因。
您需要跟踪上次请求的 UID,然后,要请求所有新消息,请使用消息集“[UID]:*”,其中 [UID] 是实际的 UID 值。
例如,假设获取的最后一条消息的唯一 ID 为“123456”。你会获取
123456:*
然后,丢弃第一条返回的消息。
UID 被“假定”在会话中是稳定的,并且永远不会改变,并且总是会增加价值。验证这一点的关键是在您选择文件夹时检查 UIDValidity。如果 UIDValidity 数字没有改变,那么 UID 应该在会话中仍然有效。
以下是 RFC 中的相关部分:
2.3.1.1。唯一标识符 (UID) 消息属性
分配给每条消息的 32 位值,当与 唯一标识符有效性值(见下文)形成一个 64 位值 不得引用邮箱中的任何其他消息或任何 后续邮箱永远同名。唯一标识符 在邮箱中以严格的升序方式分配;作为每个 邮件被添加到邮箱中,它被分配了一个比邮件更高的 UID 之前添加的消息。不同于消息序列 数字,唯一标识符不一定是连续的。
消息的唯一标识符在发送期间不得更改 会话,并且不应在会话之间更改。的任何变化 会话之间的唯一标识符必须可以使用 下面讨论 UIDVALIDITY 机制。持久的唯一标识符 客户端需要从先前的状态重新同步其状态 与服务器的会话(例如,断开连接或离线访问 客户);这将在 [IMAP-DISC] 中进一步讨论。
注意:下一个唯一标识符值旨在 为客户提供一种方法来确定是否有任何 邮件已发送到邮箱,因为 上次它检查过这个值。
这里是更多信息的链接:
http://www.faqs.org/rfcs/rfc3501.html
我会做的,也是跟踪下载消息的 InternalDate。这样,如果您丢失了 UID 同步,您至少可以遍历邮件,并根据邮件的 InternalDate 找到您下载的最后一个。
【讨论】:
是的,这太完美了!确保您运行命令“UID 123:*”而不是仅返回意外结果的“123:*” - 例如。 client.Folders.Inbox.Search("UID 123:*") 请注意,如果在此期间删除了最后获取的消息,则丢弃第一个返回的消息将导致丢弃 uid 高于最后获取的消息 uid 的消息。此外,我在 RFC 中根本找不到任何关于 fetch 响应中消息顺序的信息。【参考方案2】:有一个名为“seen”的 imap 标志。大多数客户端会在查看消息时标记一条消息,因此您需要遍历服务器上未设置该标志的消息。
这是一个代码 sn-p,它应该会给你正确的想法。操作位当然是
imap.search(["NOT", "SEEN"]).each do bla.bla.bla
【讨论】:
谢谢,但我的应用程序并不是唯一可以访问该电子邮件帐户的应用程序。例如,可能已在 Outlook 中读取了特定消息,因此将其标记为“已看到”。使用“seen”会让我的应用程序错过它。 在这种情况下,您可能只想遍历服务器上邮件中的 Message-Id 标头并与数据库中的内容进行比较。 freesoft.org/CIE/RFC/850/10.htm【参考方案3】:如果您能够将收到的邮件过滤到服务器端的特定 IMAP 文件夹中,那么您的应用 可以读取该文件夹中的新邮件,然后在完成后将它们移动到标准收件箱文件夹中。
【讨论】:
以上是关于仅从 IMAP 服务器获取新邮件的主要内容,如果未能解决你的问题,请参考以下文章