Subject: caching and mailbox synchronisation with c-client

From: Mike Schmidt <[email-masked]>
Date: Thu, 14 Apr 2005 15:00:03 -0400

Hi,

I'm writing a headless imap client using c-client on WindowsXP. I have 
interfaced to all the mail functions and can successfully  read mail 
messages from my uw-imap server (linux). Since the mail storage is 
handled by another application, with which my client communicates. The 
c-client code currently has no way of knowing what has already been 
downloaded. In such a case, what do I need to do to keep track and do 
proper synchronisation with the imap server?  The imap server is also 
accessed by other applications (webmail, existing email clients like 
Outlook, Thunderbird,etc). I have never wirtten an imap client before, 
so I don't know whether I should be downloading all the headers every 
time, and ask the mailstore to compare, or do I need to write a 
cachemanager, etc. How do I determine that some messages have been 
deleted and expunged between two sessions, for example? If it makes any 
difference, the imap server is runnng with mbx format mailboxes. These 
mailboxes can be quite large, sometimes into the 100Mb+ range, with 
messages numbering in the thousands.

I appreciate any ideas that might help. Hopefully some of you have 
encountered this situation before, and have asome good ides to suggest.

Thank you for any help you might be able to provide.

Mike

-- 
------------------------------------------------------------------
 For information about this mailing list, and its archives, see: 
 http://www.washington.edu/imap/c-client-list.html
------------------------------------------------------------------

---

From: Mark Crispin <[email-masked]>
Date: Thu, 14 Apr 2005 12:19:15 -0700

As a first order approximation:

You should have on record the UIDVALIDITY of the mailbox, highest assigned 
UID in the mailbox ever seen by the client, and UIDs of all messages.  If 
the IMAP server reports a different UIDVALIDITY then what you have, dump 
your entire cache; it has been invalidated so you have to reload 
everything.

Otherwise, if the UIDVALIDITY is the same, then identify new messages by 
doing "tag UID FETCH <n+1>:* FAST" (instead of "FAST", you may want "ALL" 
or "FULL" or whatever else you would like to know about new messages at 
synchronization time).  For <n+1>, substitute the highest assigned UID 
plus 1.

For example, if the highest assigned UID is 4392, then do something like:
 	tag UID FETCH 4393:* FULL
and load your cache with the returned data.

If you only get back one message, then that message is the 
highest-numbered UID message in the mailbox (not necessarily the highest 
UID ever assigned, since subsequent messages could have been deleted and 
expunged).

Next, compare the number of messages you have cached with the number of 
messages reported by EXISTS in the response to SELECT.  If this is 
different, the EXISTS value is probably smaller than what you have, 
meaning that many messages had been deleted and expunged (if EXISTS is 
larger, then you have a bug in your application since you failed to cache 
some old message).

An easy way to determine what messages were deleted is to fetch the UID 
map of the old messages with "tag UID FETCH 1:<n> UID" (where <n> is the 
highest assigned UID as above).  A slightly less chatty way to do this is 
"tag UID SEARCH UID 1:<n> ALL".  The UIDs that aren't returned are the 
ones that you need to remove from your cache.

This is a pretty simpleminded mechanism.  It's possible to do a lot 
better, particularly by observing that sequence numbers have no holes and 
that UIDs are strictly ascending; these are very useful properties.  But 
"learn to walk before you run" is a good point here; start with something 
simple like this, and then try to make it fancier.

-- Mark --

http://staff.washington.edu/mrc
Science does not emerge from voting, party politics, or public debate.
Si vis pacem, para bellum.