procmail, maildir, and marking as read
June 9th, 2008
Googling for “procmail maildir mark as read” yields a number of solutions, the most compact of which seems to be using INCLUDERC or SWITCHRC as explained here: http://blog.raamdev.com/2007/11/14/using-procmail-to-mark-as-read/
However, in my experience, this solution is noticeably racey. When using IMAP with the IDLE command set, some mail clients (thunderbird, probably others) will under certain circumstances immediately tell the mail server to mark the message as unread and not new. In maildir, this moves the message for new/ to cur/. Thus, if this happens before the server gets around to executing the mv command, the move fails and the message is not marked as read.
Truthfully, procmail should be enhanced to allow you to process a message marked as read in an atomic fashion. But that doesn’t seem likely, so the hack is to tell the mv command to look in both the cur/ and new/ directory. Doing so is straightforward:
Put this in ~/.procmailrc_mark_as_read_maildir:
:0
{
:0c # store as new
$folder/
:0 # move to cur/ and append a ,S to mark as read
* LASTFOLDER ?? /\/[^/]+$
{ tail=$MATCH }
TRAP=”mv -v $LASTFOLDER $folder/cur/$tail 2> /dev/null ; mv -v $folder/cur/${tail}* $folder/cur/$tail:2,S”
HOST
}
Then in your normal procmailrc, the usage is this:
:0
* someregexhere
{
folder=Maildir/.myfolder
SWITCHRC=$HOME/.procmailrc_mark_as_read_maildir
}
Now it will mark the message read whether or not your client is IDLEing in that folder. It will also log that it has done so, if you have logging enabled.
The solution isn’t perfect, as if you mark the message read inbetween the moves, it will log bogus errors; at least it will now mark the mail correctly.
UPDATE:
I’ve been asked by a few people how a remote host running IMAP can possibly win the race with procmail executing mv sequentially after initially creating the file. My IMAP server, dovecot, uses inotify to watch for new messages in maildirs. So when the kernel writes out the file, it notifies dovecot who immediately notifies its clients who mark the message as unread but not new (assuming they’re IDLEing that folder). Now, true, there is some network latency, but since dovecot notices the new mail immediately it is plausible that the network latency will be less than the system latency in exec()ing a new command, especially if load is moderate or high.