Switching from procmail to maildrop

November 5, 2019

Today I finally made the switch from procmail to maildrop.

And it was about time! procmail hasn’t seen a new version since 2001 (although Debian has been patching security issues for some years)!

I know maildrop isn’t really updated every week, but it is a hell of a lot fresher than procmail. Also, I found that the config-file is a bit nicer.

There has been many articles written on this subject, so I won’t bother with explaining too much here. I’ll show a few examples of how things are done in procmail and maildrop, and then I’ll post a sample of my new config.

.procmailrc vs .mailfilter - comparing configs

Both configs are pretty similar. .mailfilter uses perlre - Perl Regular Expressions (see perldoc perlre) - and .procmailrc uses regular expressions that are compatible with egrep. This means that the regexes in the configs are mostly compatible, and you can just copy&paste them in.

Simple example

This will move all mail from kernel.org into the folder kernel. .procmailrc:

:0
* ^From:.*kernel.org
kernel

.mailfilter:

if ( /^From:.*kernel.org/ )
    to $DEFAULT/.kernel

Filtering out duplicates

This will putt duplicats in the trash.

.procmailrc:

:0 Whc: msgid.lock
| /usr/bin/formail -D 8192 .msgid.cache
:0 a:
.Trash/

.mailfilter:

`${REFORMAIL} -D 8192 $HOME/.duplicate.cache`
{
    log "File: (duplicate)     ($SIZE)\n"
    to ${DEFAULT}/.Trash
}

Mark as Read

And this will mark an email from yourself as read.

.procmailrc:

:0
* ^From:.*pink.duck@example.com
{
    # First deliver to maildir so LASTFOLDER gets set
    :0 c
    ./

    # Manipulate the filename
    :0 ai
    * LASTFOLDER ?? ()\/[^/]+^^
    | mv "$LASTFOLDER" "./cur/$MATCH:2,S"
}

.mailfilter:

if ( /^From:.*pink.duck@example.com/ )
    FLAGS=S

I BCC myself on all emails, just to have complete threads in my folders, and this is bit saves me from having to mark the emails as read manually.

My new config

Here’s a sample from my new config-file

# regex flags, used after the regex: /something/:b
# :h - header
# :b - body
# :D - distinguish between upper and lower case (default is to ignore case)

DATE=`date +%Y-%m`
logfile "$HOME/.maildrop/mailfilter-$DATE.log"

MAIL="/usr/bin/mail"
MAILDIRMAKE="/bin/maildirmake"
REFORMAIL="/bin/reformail"

DEFAULT="$HOME/Mail"

# Root ################################
if ( /^To:.*root@(.*)?example.com/ \
	|| /^To:.postmaster@(.*)?example.com/ \
	|| /^To:.*dmarc@example.com/ \
	|| /^To:.*dmarcreport@example.com/ \
	to ${DEFAULT}/.root


# My self ################################
if ( /^From:.*pink.duck@example.com/ )
{
	# Mark as Read
	FLAGS=S

	# filter out duplicate messages
	`${REFORMAIL} -D 8192 $HOME/.duplicate.cache`
	if ( $RETURNCODE == 0 )
	{
	    log "File: (duplicate)     ($SIZE)\n"
		to ${DEFAULT}/.Trash
	}
}


# Spam ################################
if ( /^X-Spam-Flag: YES/ )
    to ${DEFAULT}/.Spam


# Other ################################
# paypal
if ( /^From:.*@(paypal.com|e.paypal.no|mail.paypal.no)/ )
	to ${DEFAULT}/.shops.paypal


# Lists ################################
if ( /^(To|Cc|Delivered-To): dennis(\+|-)debian@example.com/ )
	to ${DEFAULT}/.lists.debian

# iers.org - date/time stuff.
if ( /^(To|Cc|Delivered-To): dennis(\+|-)iers@example.com/ )
	to ${DEFAULT}/.lists

# launchpad bugs
if ( /^Reply-To:.*bugs.launchpad.net/ && /^Sender: bounces@canonical.com/ )
	to ${DEFAULT}/.lists

# zx2c4
if ( /^Delivered-To:.*dennis-lists.zx2c4.com@example.com/ )
	to ${DEFAULT}/.lists

# cisco security advisories
if ( /^Delivered-To:.*dennis-cisco-security-announce@example.com/ )
	to ${DEFAULT}/.lists


# Newsletters ################################
# Hacker News Newsletter
if ( /^Delivered-To: dennis-hackernewsletter.com@example.com/ )
	to ${DEFAULT}/.lists.newsletters

Sources