I've seen a couple of blog posts explaining how to mark Maildir messages as read with procmail. All of them point to a thread on the procmail mailing list as the source of this solution. However, all of them fail to make any kind of attempt at explaining whats going on. After some trial and error, I was able to learn what was happening. First the snippet of procmail code:
[sourcecode language="bash"]
:0
* conditions
{
foldername=whatever
:0c
.$foldername/ # stores in .$foldername/new/
:0
* LASTFOLDER ?? //[^/]+$
{ tail=$MATCH }
TRAP="mv $LASTFOLDER .$foldername/cur/$tail:2,S"
HOST
}
[/sourcecode]
OK, I'm some-what familiar with procmail, however this code was not very intuitive. Why does a copy of the message (:0c
) get moved into $foldername
? What is HOST
and what does it do? I will attempt to explain:
* conditions
This can be whatever you want. In my case, my Blackberry forwards a copy of all sent email to my inbox so that I can store it in the sent folder for future reference. However, I don't want to see "new" messages in my sent folder. I want them to be moved there and marked as read. All messages coming from my Blackberry have a From address of [email protected], so my condition is ^From.*[email protected]
. I make the assumption that I won't be emailing myself (I have a separate email account for that).
foldername=whatever
This is just storing the path to the folder we're going to work with. In my case, I'm using my sent folder: foldername=/home/raam/mail/sent
:0c
.$foldername/
This places a copy of the message in the /new
directory. This confused me, since the point of this code was to mark messages as read. But I discovered this step was necessary for the next few lines to work.
:0
* LASTFOLDER ?? //[^/]+$
{ tail=$MATCH }
First, let's read what LASTFOLDER
is according to the procmail documentation:
This variable is assigned to by procmail whenever it is delivering to a folder or program. It always contains the name of the last file (or program) procmail delivered to. If the last delivery was to several directory folders together then $LASTFOLDER will contain the hardlinked filenames as a space separated list.
OK, so in this case, LASTFOLDER
would contain the full path to the email that was copied to $foldername
in the previous step. I'm not entirely sure what the rest of the commands do, but they're necessary.
TRAP="mv $LASTFOLDER .$foldername/cur/$tail:2,S"
Deciphering the mv
command is pretty simple. It moves the email that we copied to $foldername
to the /cur/
directory and renames it to end with :2,S
. Cool, that makes the email client see the message as read. But what is TRAP
? Again, let's RTFM and find out what TRAP
is used for:
When procmail terminates of its own accord and not because it received a signal, it will execute the contents of this variable. A copy of the mail can be read from stdin. Any output produced by this command will be appended to $LOGFILE. Possible uses for TRAP are: removal of temporary files, logging customised abstracts, etc.
Interesting. But the next line is even more interesting!
HOST
What on Earth could this do? Well to my surprise it is directly linked to TRAP
. Since the contents of TRAP
will be executed when procmail terminates, we need a way of terminating procmail (for this block anyway). We do this with HOST
. Here is a good explanation from another mailing list thread:
Lacking an explicit "exit" command in procmailrc, "HOST" in procmail is
what "exit $EXITCODE" would be in a shell.
So there you have it. I had no idea there would be so much happening behind these few lines of procmail code, but I'm glad I took the time to learn!