on mar 28th, 2007
tagged nerd, postfix
and
never commented on
share this page
my postfix setup has a bunch of virtual domains and their users stored in a mysql database, which is queried by postfix for smtp/routing, and by dovecot for imap authentication.
this setup is nothing new and is fairly common, but since it all runs through postfix's virtual(8), it provides no way of per-virtual-user procmail filtering to move messages into separate mailboxes, filter spam, or push them back out to other addresses. after reading lots of postfix docs and refusing to look at the 8 billion linux-style crappy howto's on postfix-plus-some-other-combination-of-crap that look like they're all copied from eachother anyway, here's how i implemented it.
enable fowarding for the specific virtual user to an address at a private domain (i used "filter.") in the mysql table. for "example@superblock.net", it is being forwarded to "superblock.net-example@filter." (note the trailing dot to prevent postfix from tacking on the local hostname).
in postfix's main.cf, add an alias_maps file that will be used to store these fake addresses and their corresponding procmail lines.
alias_maps = $alias_maps, hash:/etc/postfix/filters
in that new file, create an entry for the fake address
superblock.net-example "|/usr/local/bin/procmail -m /d/mail/superblock.net/example/.procmailrc"
now create a transport for this fake domain in postfix's transport file that will make postfix route mail for it through a new service (aptly named "filter"):
filter filter:
then define that new "filter" service in master.cf to look just like the built-in "local" service, but adding an option to override the "default_privs" setting to run as _vmail (which postfix's virtual service normally delivers as):
filter unix - n n - - local -o default_privs=_vmail
hint: to test whether that's working, change the procmail forward in the aliases file to something cute like "sh -c 'id; exit 1'" and watch the maillog on delivery to see it echo the uid local(8) is being run as.
Mar 28 01:02:30 qualia postfix/local[22011]: BED04514B: to=<superblock.net-example@filter>, orig_to=<example@vmail.superblock.net>, relay=filter, delay=0.02, delays=0.01/0/0/0.01, dsn=5.3.0, status=bounced (Command died with status 1: "sh -c 'id; exit 1'". Command output: uid=999(_vmail) gid=999(_vmail) groups=999(_vmail) )
now with all of this shenanigans in place, mail routes for example@superblock.net as such:
- inbound mail for example@superblock.net gets looked up in mysql
- mysql tells it to forward to "superblock.net-example@filter."
- mail for @filter routes through the filter service
- the filter service runs the local(8) delivery agent as the user _vmail so it can read/write to the virtual mail directories in /d/mail/
- local(8) then looks up "superblock.net-example@filter." in the new aliases file
- the alias for that address pipes the mail through procmail and tells it to load the specific procmailrc file for that virtual user
- this particular procmailrc sets $DEFAULT to /d/mail/superblock.net/example/ and does its magic
seems kinda kludgey but it works within postfix's framework and doesn't have the overhead of having to run every message (or even every message for a whole domain) through procmail.
of course, these per-virtual-user procmail recipies can and should only be managed by an administrator, since a bad rule could write mail to any other virtual user's mailboxes or spawn commands to delete stuff since all of the other users and domains are owned by the same _vmail user.
leave the first comment or contact me