Storing all of your electronic mail on your mail server tends to take a lot of hard drive space, especially if you never delete any messages.

Fortunately, Dovecot can easily be configured to use zlib-based compression. Less fortunately, actually storing mail in a compressed format requires either compressing your mail manually (by the use of a cron job, say) or delivering it through Dovecot's custom local delivery agent (LDA). At first sight, the latter seems to preclude you from using procmail, since the mail transfer agent, which is the usual entity to call procmail, is supposed to hand all mail over to the LDA instead. However, procmail can easily be configured to deliver compressed mail. There are two approaches: having procmail run bzip2 itself (which I shall call the low-level approach), or preferably, piping procmail's output to Dovecot's LDA (the high-level approach).

The high-level approach incidentally enables you to make use of Dovecot's custom mail storage formats. The low-level approach, on the other hand, is independent of Dovecot and can be used in conjunction with any mail server that can handle gzip- or bzip2-compressed files.

High-Level Approach: Using Dovecot's LDA

First, put the following somewhere near the top of your .procmailrc:

LDA=/usr/local/libexec/dovecot/dovecot-lda

Customize the file path as appropriate.

Next, let's say you have a rule like the following:

:0
* ^Subject:.*This is spam.*
$MAILDIR/.Spam/

(If only it was that easy!)

Replace it with the following:

:0
* ^Subject:.*This is spam.*
| $LDA -m Spam

Repeat this for all the rules in the file. You're done!

Low-Level Approach: Using bzip2 from procmail

This approach assumes you're storing your mail in a Maildir.

First, we need the ability to generate Maildir file names. Put the following somewhere near the top of your .procmailrc:

GENID='echo -n `date +%s`; echo -n _R; hexdump -e "/4 \"%u\"" -n 16 /dev/urandom'

The above is for FreeBSD; other operating systems may use some slightly different command syntax. The only thing we need to care about is that $GENID is a shell command that generates a hopefully unique file name on each invocation.

Again, consider a rule such as this one:

:0
* ^Subject:.*This is spam.*
$MAILDIR/.Spam/

Replace it with the following:

:0:
* ^Subject:.*This is spam.*
| bzip2 -c >$MAILDIR/.Spam/new/$(eval $GENID).gz

Repeat this for all the rules in the file. Done.

Warning: Having bzip2 write directly to the Maildir may be unsafe in case another process tries to read the file while it is being written. You may want to consider combining the above with the use of safecat.