【问题标题】:Ruby IMAP "changes" since last check自上次检查以来 Ruby IMAP “更改”
【发布时间】:2012-04-22 00:45:27
【问题描述】:

我正在使用 Ruby 和 Rails 开发 IMAP 客户端。我可以成功导入邮件、邮箱等...但是,在初始导入之后,如何检测自上次同步以来发生的任何更改?

目前我将 UID 和 UID 有效性值存储在数据库中,比较它们,并进行适当的搜索。这可行,但它不会检测到已删除的消息或对消息标志的更改等。

是否必须每次都提取所有消息才能检测到这些更改?其他 IMAP 客户端如何如此快速地做到这一点(即 Apple Mail 和 Postbox)。我的脚本已经为每个帐户花费了 10 多秒,而电子邮件地址非常少:

# select ourself as the current mailbox
@imap_connection.examine(self.location)

# grab all new messages and update them in the database
# if the uid's are still valid, we will just fetch the newest UIDs
# otherwise, we need to search when we last synced, which is slower :(
if self.uid_validity.nil? || uid_validity == self.uid_validity
  # for some IMAP servers, if a mailbox is empty, a uid_fetch will fail, so then
  begin
    messages = @imap_connection.uid_fetch(uid_range, ['UID', 'RFC822', 'FLAGS'])
  rescue
    # gmail cries if the folder is empty
    uids = @imap_connection.uid_search(['ALL'])
    messages = @imap_connection.uid_fetch(uids, ['UID', 'RFC822', 'FLAGS']) unless uids.empty?
  end

  messages.each do |imap_message|
    Message.create_from_imap!(imap_message, self.id)
  end unless messages.nil?
else
  query = self.last_synced.nil? ? ['All'] : ['SINCE', Net::IMAP.format_datetime(self.last_synced)]
  @imap_connection.search(query).each do |message_id|
    imap_message = @imap_connection.fetch(message_id, ['RFC822', 'FLAGS', 'UID'])[0]

    # don't mark the messages as read
    #@imap_connection.store(message_id, '-FLAGS', [:Seen])

    Message.create_from_imap!(imap_message, self.id)
  end
end

# now assume all UIDs are valid
self.uid_validity = uid_validity

# now remember that we just fetched all those messages
self.last_synced = Time.now
self.save!

【问题讨论】:

  • 相关,但不是骗子。我已经知道如何获取新消息。我需要一种方法来获取已删除或“更改”的消息...
  • 从“垃圾箱”文件夹中删除邮件时(即手动删除或 30 天后删除)。关于其他客户,我猜他们正在做相当快的 FETCH 1:* [UID],然后比较集合。
  • 所以他们只是在完全比较和/或替换他们服务器上的集合?

标签: ruby ruby-on-rails-3 imap uid


【解决方案1】:

快速标志更改重新同步有一个 IMAP 扩展 (RFC-4551)。使用此扩展,可以搜索自上次同步以来已更改的所有消息(基于某种时间戳)。但是,据我所知,此扩展并未得到广泛支持。

有一个信息 RFC 描述了 IMAP 客户端应如何进行同步(RFC-4549,第 4.3 节)。文中建议发出以下两条命令:

tag1 UID FETCH <lastseenuid+1>:* <descriptors>
tag2 UID FETCH 1:<lastseenuid> FLAGS

第一个命令用于获取所有未知邮件的所需信息(不知道有多少邮件)。第二个命令用于同步已看到邮件的标志。

AFAIK 这种方法被广泛使用。因此,许多 IMAP 服务器包含优化以快速提供此信息。通常,网络带宽是限制因素。

【讨论】:

  • 您可能希望使用 RFC-7162 更新答案,这也是“标准跟踪”
【解决方案2】:

不幸的是,IMAP 协议以这种方式已经死了。例如,IDLE 确实应该能够在连接时返回这种东西。上面的 FETCH FLAGS 建议是唯一的方法。

但是,需要注意的一点是,根据规范,UID 仅对给定会话有效。即使某些服务器持久保存它们,也不应存储它们。

【讨论】:

  • 不过,这是一项非常昂贵的操作——尤其是对于收件箱中有 10000 封电子邮件的用户而言。必须有一种缓存现有消息的方法。
  • @Aaron Zinman UID 不是特定于会话的。 IMAP4 的同步规范强烈建议使用 UID,因为它对于文件夹中的消息保持不变。在 RFC4549 tools.ietf.org/html/rfc4549 中,它说“由于断开连接的客户端无法知道在断开连接时邮箱可能发生了什么变化,因此消息编号对断开连接的客户端没有用。所有断开连接的客户端操作都应使用 UID 执行,以便客户端可以确定它和服务器在同步过程中正在谈论相同的消息。”
  • @sethvargo 目前正在做一个类似的项目,并考虑到可能有大量电子邮件的人,分页将是你最好的选择。您不会在一页上显示 10,000 封电子邮件,因此一次只处理一页。在处理新消息时,您可以使用预设的最大范围简单地拉取它们。这在 RFC 4549 中进行了解释。标志也是如此,您可以限制一次请求的标志数量。
猜你喜欢
  • 2011-10-03
  • 1970-01-01
  • 2018-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-18
  • 2017-08-16
  • 1970-01-01
相关资源
最近更新 更多