September 15, 2008

Managing Your Own Mail: Part 2, Stupid Recipe Tricks and Sending Mail

Filed under: Uncategorized — numist @ 7:02 pm

So, if you were following the previous article, you now have mail on your server, but you’re still sending it the Old Way. Let’s fix that. In this post you’ll have recipes for rewriting From: headers, marking incoming messages as read, and sending mail for multiple accounts through your server based on the From: header of the message.

Stupid trick the first

automatically marking mail as read. This shouldn’t be hard, but when you want to be using bash, procmail feels very restrictive, even antique. Using Maildir (because you should be), this breaks down to a move command. If you’re worried about concurrency (and with dovecot hanging on inotify, you should be), two move commands, one of which may fail. Here’s the file I include when I want to mark a message as read:

# move-and-mark-read.rc
# vim:set syntax=procmail:
# deliver message to folder and mark as read


# usage:
# :0 c  # omit the c argument if you want to terminate on delivery.
# * expression(s)
# {
#     folder=""
#     INCLUDERC=$RC/move-and-mark-read.rc
# }

# see for
# an explanation of the recipes in this document, and
# for
# their origins.

    # this delivers a copy because we don't want to terminate before
    # we can know where the message was delivered, so we can move it.
    :0 wc

    # get the filename from the path the message was saved to
    :0 w
    * LASTFOLDER ?? /\/[^/]+$

    # move the message from an unread/unseen name to a read filename.
    # * avoid potential race condition if an IMAP client beats us to this step
    # see:
    # with bash cleanup (don't move if nonexist test).
    * VERBOSE ?? on
        # only use mv -v(erbose) if VERBOSE is on
        TRAP="[ -f \"$LASTFOLDER\" ] && mv -v $LASTFOLDER ${folder}cur/$tail ; mv -v ${folder}cur/$tail* ${folder}cur/$tail:2,S"
        TRAP="[ -f \"$LASTFOLDER\" ] && mv $LASTFOLDER ${folder}cur/$tail ; mv ${folder}cur/$tail* ${folder}cur/$tail:2,S"


# there doesn't seem to be a reason why you can't use the recipe below, other
# than that the above is more involved and clever.  I use the above because
# it promotes greater learning and understanding of procmail.

    # :0 w
    # | [ -f "$LASTFOLDER" ] && mv -v $LASTFOLDER $folder/cur/$tail ; mv -v $folder/cur/${tail}* $folder/cur/$tail:2,S

Stupid trick the second

I more or less gave up on server-side message signing and encrypting (although it seems like it wouldn’t be too hard to do with perl and openssl), and sending from an arbitrary address is implemented but never used after discovering that and the mail client on the iPhone both allow for sending from multiple addresses already via a hidden mechanism. For folks that still have a client that can’t change senders effectively, here’s something you can do early on in your mail-sending process in procmail:

# rewrite-from.rc
# vim:set syntax=procmail:
# divine the intended sender of the message and make it so.
# thanks to Joe Auricchio for this recipe

NAME="My Name"

# If I've set a rewrite in the subject, do it.
# to use this, append the subject line with <<foo@bar.baz>>
:0 wf
* ^Subject:.*<<\/.*>>
* MATCH ?? ()\/[^>]+
| /usr/bin/formail -I "From: $NAME <$MATCH>" | sed '/^Subject:/ s/<<[^>]*>>//'

How do I sent mail through procmail?

oh right, I kinda skipped that part, didn’t I? Let’s back up a bit.

Assuming you’re running postfix, you’ll want to make sure these lines exist in your /etc/postfix/ file:

# procmail smtp magic: inet n      -       n       -       -       smtpd
    -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o content_filter=filter:dummy

filter    unix  -       n       n       -       10      pipe
  flags=Rq user=username argv=/usr/bin/procmail /home/username/.procmail/outgoing.rc

This makes sure that postfix is listening to port 587 of your server for authenticated SMTP requests. It probably won’t work yet, since dovecot provides the authentication to postfix. Let’s head over to /etc/dovecot/dovecot.conf and find a line that contains “pam”. If you find a line like passdb pam {, uncomment it and it’s matching }. Otherwise just add them to the end of the file. Restart dovecot and postfix and you should be ready to go.

Now procmail is being called when you send mail, and your message enters it’s life in your ~/.procmail/outgoing.rc file. Instead of delivering, you want to run your recipes and modify the message as you like, and then pass it off to a program to actually send it out. I recently discovered the excellent software msmtp and integrated it into the last step of my outgoing recipe:

# send.rc
# vim:set syntax=procmail:
# this rcfile terminates all messages.
# see: .msmtprc

* ^From:.*myaccount@gmail\.com
| /usr/bin/msmtp -a gmail -t

:0 E
* ^From:.*username@(cs\.)?ucsd\.edu
| /usr/bin/msmtp -a ucsd -t

:0 E
* ^From:.*(user|alias)@company\.com
| /usr/bin/msmtp -a company -t

# this sends out all messages from any of my
# accounts that weren't previously matched.
:0 E
| /usr/sbin/sendmail -t -i

Now you’re sending and receiving mail on your own server, congratulations!


1 Comment »

  1. […] Sending mail through your server […]

    Pingback by Managing Your Own Mail: Part 1 of Many « ScottLog — September 15, 2008 @ 7:04 pm | Reply

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at

%d bloggers like this: