To my understanding, there is no way to query an entire IMAP account for a total unread count, or the UIDs of all recent messages, regardless of mailbox. That to get a total unread count for the account, you need to iterate over all mboxes and check their status. I've done that, but it's very slow (45 seconds on one of my accounts with many mailboxes).
Mail.app can find new messages, even in deeply nested mailboxes, in just a couple seconds.
Is the speed here just a limitation of using Net::IMAP? Or am I missing some functionality that will return a more limited set of mailboxes, like only ones that have RECENT mes开发者_运维技巧sages?
The only other option I can think of to use response handlers, and also keep a cache of which mboxes have a counter > 1, and then only check the combination of the two each cycle. But since I'm looking to do this in a script, eliminating the need to carry over a cache would be ideal, if not required.
The canonical way to detect new messages in IMAP is via UIDNEXT
. Issuing
A001 STATUS "foldername" (UIDVALIDITY UIDNEXT)
on each folder that you care about will give you the expected next UID for that folder. Here's what the RFC has to say:
Unique identifiers are assigned in a strictly ascending fashion in the mailbox; as each message is added to the mailbox it is assigned a higher UID than the message(s) which were added previously. Unlike message sequence numbers, unique identifiers are not necessarily contiguous.
The next unique identifier value is the predicted value that will be assigned to a new message in the mailbox. Unless the unique identifier validity also changes (see below), the next unique identifier value MUST have the following two characteristics. First, the next unique identifier value MUST NOT change unless new messages are added to the mailbox; and second, the next unique identifier value MUST change whenever new messages are added to the mailbox, even if those new messages are subsequently expunged.
So just keep track of the each folder's expected next UID and UID validity value. If a STATUS
command results in either UIDNEXT
or UIDVALIDITY
changing from your cached value, you know you need to check for new mail (if the former) or resync (if the latter).
Something like this:
imap.status("foldername", ["UIDNEXT", "UIDVALIDITY"])
精彩评论