我正在使用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!
答案 0 :(得分:11)
快速标记更改重新同步(RFC-4551)有一个IMAP扩展。使用此扩展,可以搜索自上次同步以来已更改的所有消息(基于某种时间戳)。但是,据我所知,这种扩展并未得到广泛支持。
有一个信息RFC描述了IMAP客户端应如何进行同步(RFC-4549,第4.3节)。该文本建议发出以下两个命令:
tag1 UID FETCH <lastseenuid+1>:* <descriptors>
tag2 UID FETCH 1:<lastseenuid> FLAGS
第一个命令用于获取所有未知邮件所需的信息(不知道有多少邮件)。第二个命令用于同步已经看过的邮件的标志。
AFAIK这种方法被广泛使用。因此,许多IMAP服务器都包含优化,以便快速提供此信息。通常,网络带宽是限制因素。
答案 1 :(得分:1)
不幸的是,IMAP协议以这种方式死亡。例如,IDLE确实应该能够在连接时返回这种东西。上面的FETCH FLAGS建议是唯一的方法。
但是,要注意的一件事是,UID仅对规范中的给定会话有效。您不应该存储它们,即使某些服务器仍然存在它们。