从IMAP服务器获取仅新邮件

21

我正在编写一个客户端应用程序,用于从IMAP服务器获取电子邮件并将其存储在数据库中。问题是,一旦我检查了邮件,下一次我只想下载自那时以来到达的邮件。因此,如果我两个小时前检查过服务器上的邮件,则只想获取最近两个小时内到达的邮件。

我可以使用SINCE DATE进行搜索,但是对于时间+日期没有支持,容易被欺骗。

我还尝试了RECENT标志,但它似乎不适用于gmail(在ruby中每次显示nil)。

3个回答

42

您想要使用消息的唯一标识符(UID)。这就是为什么它被创建的特定原因。

您将想要跟踪最后一个请求的 UID,然后要请求所有新消息,您可以使用消息集"[UID]: *", 其中[UID]是实际的 UID 值。

例如,假设上次检索到的最后一条消息具有唯一标识符"123456"。你将获取

123456:*

然后丢弃第一个返回的消息。

UID 应该在会话间是稳定且不变的,并且值始终递增。要验证此值,请检查选择文件夹时的 UIDValidity。如果 UIDValidity 数字未更改,则 UID 在会话间应仍然有效。

以下是 RFC 中的相关部分:

2.3.1.1.唯一标识符(UID)消息属性

分配给每个消息的 32 位值,在与唯一标识符有效值(见下文)一起使用时,形成一个 64 位值,该值永远不得引用邮箱中的任何其他消息或同名后续邮箱。唯一标识符在邮箱中严格按升序分配;在每个消息添加到邮箱时,它会被分配比先前添加的消息(们)更高的 UID。与消息序列号不同,唯一标识符不一定是连续的。

消息的唯一标识符在会话期间不得更改,并且在会话之间不应更改。在会话之间更改唯一标识符的任何更改都必须使用下面讨论的 UIDVALIDITY 机制进行检测。客户端需要持久的唯一标识符来从以前的会话中与服务器重新同步其状态(例如,断开连接或离线访问客户端),这在 [IMAP-DISC] 中进一步讨论。

注意:下一个唯一标识符值旨在提供一种方法,使客户端能够确定是否自上次检查此值以来传递了任何消息。

这里是更多信息的链接:

我会做的是,同时跟踪所下载邮件的 InternalDate。这样,如果您不小心失去 UID 同步,至少可以遍历这些邮件,并根据邮件的 InternalDate 找到您最后下载的那个邮件。请点击这里查看更多信息。

是的,这很完美!请确保运行命令“UID 123:*”,而不是只运行“123:”,否则会返回意外结果 - 例如,client.Folders.Inbox.Search("UID 123:")。 - Simon_Weaver
注意,如果同时被删除的是最后一个获取到的消息,则丢弃第一个返回的消息将导致丢失一条uid高于已获取到的最后一条消息的消息。此外,我在RFC中找不到关于获取响应中消息顺序的任何信息。 - p0ny

4

存在一个名为“seen”的imap标志。大多数客户端在查看邮件时会将其标记为已读(seen),因此您需要枚举未设置该标志的服务器上的邮件。

以下是一段代码片段,它应该会给您正确的想法。当然,关键部分是:

imap.search(["NOT", "SEEN"]).each do bla.bla.bla

谢谢,但我的应用程序不是唯一可以访问该电子邮件帐户的。例如,某个消息可能已在Outlook中阅读,因此标记为“已读”。使用“已读”会使我的应用程序错过它。 - Abhishiv Saxena
在这种情况下,您可能只想在服务器上遍历邮件中的Message-Id标头,并与数据库中的内容进行比较。http://www.freesoft.org/CIE/RFC/850/10.htm - JosefAssad

0
如果您能够在服务器端将传入的邮件过滤到特定的IMAP文件夹中,那么您的应用程序就可以在该文件夹中读取新消息,然后在完成后将它们移动到标准的收件箱文件夹中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接