Tuesday, May 18, 2004

Migrating from procmail to maildrop.

I first used procmail over ten years ago. When I decided to make the leap to maildrop, I had over 70 procmail recipes (as counted by "grep -c '^:'") to translate.

I started by reading most of the manual. With that, I set to work. I intend to document here some of the things I learned in my few hours of tackling this task which I thought would be many hours more monumental. I was using procmail 3.22, and I went to maildrop 1.3.7. If anything I say here is inconsistent with your experience, check your versions against what I'm using before hollering too loudly.

The real impetus for the change was patterns that look like this:

:0HB:proclock
* !^Delivered-To: kyle-virus@
* ! ? /usr/bin/clamscan --quiet --mbox -
| /usr/bin/tmda-filter -I $HOME/.tmda/filters/always_hold

This was a big problem for me in procmail because I don't see a way to lock that invocation of clamscan. I'd get a flood of mail, and there'd be 15 of the damn things running at once.

In maildrop, I can lock any block that it works on. It looks like this:

if ( ! /^Delivered-To: kyle-virus@/ )
{
flock "$PROCLOCK" {
if ( `/usr/bin/clamscan --quiet --mbox -` )
to "| /usr/bin/tmda-filter -I $HOME/.tmda/filters/always_hold"
}
}

Doing it that way, I get to lock the check for viruses and the delivery at the same time. I have no more clamscan rabbits. One gotcha here is that the test for clamscan is reversed. What's a test for falsehood ("!?") in procmail is a truth test in maildrop. I had to remember to reverse every test that I did that way.

Maildrop's syntax is not really free form. I read this in the docs, and I was careful of the example given. Still, I tripped. This works:

flock "filename" {

This does not:

flock "filename"
{

The error message pointed me to the right place, but it didn't really tell me what the problem was. It didn't take me long to figure it out, but someone with more faith in the language might have been stumped longer.

In my procmailrc, I used INCLUDERC many times. My recipes were spread over a half a dozen files. It's no problem doing the same thing in maildrop, but I didn't know right away that environment variables imported in the main file do not propagate to the children. Because I use TMDA, I need to import SENDER, RECIPIENT, and EXTENSION. I gave procmail the -p option, and that was the end of it. In maildrop, I need these lines at the top of every file that wants to call TMDA:

import SENDER
import RECIPIENT
import EXTENSION
if ( ! $SENDER )
SENDER = "<>"

Moving patterns from one to the other is fairly straight forward. You have to replace '\/' with '!', and the corresponding $MATCH becomes $MATCH2. What is "* !^foo" in procmail is "! /^foo/" in maildrop. I didn't run into too many details that tripped me up, but YMMV.

Procmail's FROM_DAEMON internal pattern is really handy. I tried to just paste it into maildrop, and it didn't go so well. I wound up doing this:

FROMDAEMON=0
foreach /^((Resent-)?(From|Sender)|X-Envelope-From): .*/
{
foreach ( getaddr $MATCH =~ /.+/ )
{
ADDR=$MATCH
if ( $ADDR =~ /(Post(ma(st(er)?|n)|office)|(send)?Mail(er)?|daemon|mmdf|n?uucp|ops|r(esponse|oot)|(bbs\.)?smtp(error)?|s(erv(ices?|er)|ystem)|A(dmin(istrator)?|MMGR))/ )
{
FROMDAEMON=1
}
}
}
if ( $FROMDAEMON ) ...

It looks bad, I'll grant you, but I think it's more reliable. Also, you can do this once and use the variable over and over without having to reprocess the pattern match. I did something similar for other places where I was paying close attention to how the email was addressed. I'm happier with the results because I no longer worry that my pattern will be foiled by some oddball use of RFC 2822. Maildrop takes care of it.

While debugging, it was worthwhile to do this:

tail -f /var/log/mail.log | grep 'temporary failure'

Note that I'm using Postfix (1.1.11), and it helpfully put the maildrop error messages in the log line with its temporary failure notes.

I tested with 'maildrop -V 1 < testmessage' quite a bit. It's convenient. I didn't notice any difference between '-V 1' and '-V 2', but maybe I just never hit a feature that shows the difference.

All in all it was quite a bit less painful than I thought (y'know, before I knew anything about maildrop).

No comments: