Skip navigation.
Home
Voluntary-Simplicity.org's Linux Pages

Procmail + Postfix + Virtual Mail User Howto

This post documents my configuration of Procmail for Postfix using virtual mail users.

A virtual user is one who does not have a "real" Linux user account. Virtual mail users are extremely convenient for handling multiple mail accounts and virtual domains. This configuration allows some (privileged) virtual mail users to receive their email via procmail, and all others via postfix's standard "virtual" transport.

I use postfixadmin for virtual mailbox management, so this configuration coincides with my postfixadmin configuration. (This does not cover installation of postfixadmin on Debian.) Specifically, I use the following postfixadmin settings to define the mailbox structure:

POSTFIXADMIN CONFIGURATION
config.inc.php:
// Mailboxes
// If you want to store the mailboxes per domain set this to 'YES'.
// Example: /usr/local/virtual/domain.tld/username@domain.tld
$CONF['domain_path'] = 'YES';
// If you don't want to have the domain in your mailbox set this to 'NO'.
// Example: /usr/local/virtual/domain.tld/username
$CONF['domain_in_mailbox'] = 'NO';

Note that I have created a user "vmail" to handle virtual mail delivery (see postfixadmin setup):
crnatural:~# grep vmail /etc/passwd vmail:x:150:8:Virtual mailbox:/home/vmail:/sbin/nologin

On my server, this makes the path to a user mailbox to be: /home/vmail/mydomain.com/username It is important to remember that procmail must also deliver email following this path structure.

POSTFIX CONFIGURATION
First we configure procmail as an available transport type in postfix's master.cf.:

procmail unix - n n - - pipe
  -o flags=RO user=vmail argv=/usr/bin/procmail -t -m USER=${user} EXTENSION=${extension} /etc/postfix/procmailrc.common

The default transport type for virtual users will be set to be "virtual" in main.cf.

main.cf:
virtual_transport = virtual
# uncomment the following line to have procmail deliver to all virtual users
# virtual_transport = procmail
# TRANSPORT MAP
procmail_destination_recipient_limit = 1
transport_maps = hash:/etc/postfix/transport

/etc/postfix/transport:
user1@mydomain.com procmail
user2@mydomain.com procmail

With the above configuration, procmail run the procmail script at /etc/postfix/procmailrc.common for users/domains named in /etc/postfix/transport.

/etc/postfix/procmailrc.common:
MAILDIR="$HOME/mydomain.com/$USER"
DEFAULT="$MAILDIR/"
#VERBOSE=ON
#each user will set his own log file
#LOGFILE="/home/vmail/proclog-$USER"
NL="
"
WS="    "
SWITCHRC="$HOME/.procmail/$USER"

Note that $HOME contains "/home/vmail," the home directory of the user that handles virtual mail delivery.  Thus, the delivery path matches the virtual mail delivery path.

Bugs: This setup hard-codes the delivery domain, so it can only deliver to email addresses on a single domain.  To deliver to more than one domain, you could pass the full destination email address as an argument to procmail, and write procmail recipes to extract the domain for the SWITCHRC assignment.

(See comments below for code to do multiple-domain delivery in 2 different ways.)

Credits: The idea for this configuration came from a post on the procmail mailing list, procmail Digest, Vol 53, Issue 4 (procmail at lists.RWTH-Aachen dot DE) by "LuKreme"

I solved the bug by adding

I solved the bug by adding $NEXTHOP=${nexthop} in master.cf
procmail unix - n n - - pipe
-o flags=RO user=vmail argv=/usr/bin/procmail -t -m USER=${user} EXTENSION=${extension} NEXTHOP=${nexthop} /etc/postfix/procmailrc.common

then I changed mydomain.com in $NEXTHOP in procmailrc.common

You also can use $NEXTHOP if you have same users in different domains.
Like SWITCHRC="$HOME/.procmail/$USER-$NEXTHOP"

I don't know what $EXTENSION is doing, but it's empty in my setup.

Fixing delivery for multiple domains

That's a cool fix! Thanks very much! Did you test that for virtual domains? If your fix works perfectly, it is probably better (simpler) than my solution below.

I also had a need to fix this, and this is how I did it. I modified the procmail service line in master.cf as follows:

procmail unix - n n - - pipe
flags=DRO user=vmail argv=/usr/bin/procmail -t -m USER=${user} RECIPIENT=${recipient} /etc/postfix/procmailrc.common

I added what's in boldfaced: RECIPIENT=${recipient}. Note that I removed EXTENSION=${extension}, since I don't use it.

The "O" flag prepends an "X-Original-To: recipient" message header with the recipient address as given to Postfix. Note: for this to work, the procmail_destination_recipient_limit (in main.cf) must be 1.

Next, I modifed procmailrc.common as follows (this is my full procmailrc.common):
----------------------------------------------
:0
* RECIPIENT ?? .*@\/.*$
{ DOMAIN = "$MATCH" }
#added RECIPIENT variable and we extract domain name
MAILDIR="$HOME/$DOMAIN/$USER"
DEFAULT="$MAILDIR/"
#each user will set his own log file
NL="
"
WS=" "
SWITCHRC="$HOME/.procmail/$USER"
-------------------------------------------------

Notes: The "\/" in this recipe captures everything that matches after it to the variable MATCH. The idea, of course, is to extract the domain name from the email address.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <p> <br> <img> <alt>
  • Lines and paragraphs break automatically.

More information about formatting options

CAPTCHA
(for spam prevention)
Image CAPTCHA
Copy the characters (respecting upper/lower case) from the image.