This code was created by Andrew McNamara and adapted to snapshot 20001121 by Xavier Beaudouin. It was merged with mainstream Postfix for snapshot 20010128 by Wietse. Purpose of this software ======================== You can use the virtual delivery agent for mailbox delivery of some or all domains that are handled by a machine. This mechanism is different from simulated virtual domains. Those are implemented by translating every recipient address into a different address. For that, see the virtual(5) manual page. With the virtual delivery agent, every recipient adress can have its own mailbox. There is no translation from recipient addresses into different addresses. This is what Andrew McNamara wrote when he made the virtual delivery agent available. "This code is designed for ISP's who offer virtual mail hosting. It looks up the user mailbox location, uid and gid via separate maps, and the mailbox location map can specify either mailbox or maildir delivery (controlled by trailing slash on mailbox name). The agent allows but ignores user+foo address extensions, does not support aliases or .forward files (use the virtual table instead), and therefore doesn't support file or program aliases. This choice was made to simplify and streamline the code (it allowed me to dispense with 70% of local's code - mostly the bits that are a security headache) - if you need this functionality, this agent isn't for you. It also doesn't support writing to a common spool as root and then chowning the mailbox to the user - I felt this functionality didn't fit with my overall aims." [End of Andrew McNamara's words] The result is the most secure local delivery agent that you will find with Postfix. This delivery agent requires three different lookup tables in order to define its recipients as (mailbox path, user ID, group ID). This is because Postfix table lookups can't return multiple results. If your virtual mailboxes are all owned by the same user/group ID, just specify "static" maps that always return the same result. See below for examples. If your virtual mailboxes must be owned by different user/group IDs, and if it is too inconvenient for you to maintain three parallel tables, use an LDAP or MYSQL database (or generate the three parallel tables from one common template). Configuration parameters ======================== virtual_mailbox_base Specifies a path that is prepended to all mailbox paths. This is a safety measure to ensure an that out of control map doesn't litter the filesystem with mailboxes (or worse). While it could be set to "/", this isn't recommended. virtual_mailbox_domains Specifies the list of domains that should be delivered to the $virtual_transport delivery agent (default: virtual). As of version 2.0, Postfix is smart enough that you don't have to list every virtual domain in a Postfix transport map. virtual_mailbox_maps Recipients are looked up in this map to determine the path to their mailbox. If the returned path ends in a slash ("/"), maildir-style delivery is carried out, otherwise the path is assumed to specify a mailbox file. The virtual_mailbox_base directory is unconditionally prepended to this path. If the recipient is not found the mail is bounced. In a lookup table, specify a left-hand side of @domain.tld to match any user in the specified domain that does not have her own user@domain.tld entry. While searching a lookup table, an address extension (user+foo@domain.tld) is ignored. If a recipient is not found the mail is returned to the sender. Regular expression maps are allowed. For security reasons, regular expression substitution of $1 etc. is disallowed, because that would open a security hole. The mail administrator is expected to create and chown recipient mailbox files or maildir directories ahead of time. virtual_minimum_uid Specifies a minimum uid that will be accepted as a return from a virtual_uid_maps lookup. Returned values less than this will be rejected, and the message will be deferred. virtual_uid_maps Recipients are looked up in this map to determine the UID (owner privileges) to be used when writing to the target mailbox. In a lookup table, specify a left-hand side of @domain.tld to match any user in the specified domain that does not have a specific user@domain.tld entry. While searching a lookup table, an address extension (user+foo@domain.tld) is ignored. Regular expression maps are allowed. For security reasons, regular expression substitution of $1 etc. is disallowed, because that would open a security hole. Specify a static map if all mailboxes should be owned by the same UID. For example, to specify that all mailboxes are owned by the UID 5000, specify: virtual_uid_maps = static:5000 virtual_gid_maps Recipients are looked up in this map to determine the GID (group privileges) to be used when writing to the target mailbox. In a lookup table, specify a left-hand side of @domain.tld to match any user in the specified domain that does not have a specific user@domain.tld entry. While searching a lookup table, an address extension (user+foo@domain.tld) is ignored. Regular expression maps are allowed. For security reasons, regular expression substitution of $1 etc. is disallowed, because that would open a security hole. Specify a static map if all mailboxes should be owned by the same GID. For example, to specify that all mailboxes are owned by the GID 5000, specify: virtual_gid_maps = static:5000 virtual_mailbox_lock This setting is ignored in case of maildir delivery. Locking method to use when updating a mailbox. Defaults to fcntl or flock depending on the system. Depending on the POP or IMAP server you may have to specify dotlock locking, which requires that the recipient UID or GID has write access to the parent directory of the mailbox file. Use the "postconf -l" command to find out what locking methods Postfix supports on your system. virtual_mailbox_limit An upper limit on the size of a mailbox file or maildir file. Example 1: using the virtual delivery agent for all local mail ============================================================== This example does not use the Postfix local delivery agent at all. With this configuration Postfix does no alias expansion, no .forward file expansion, no lookups of recipients in /etc/passwd, and allows but ignores user+foo address extensions. Instead of "hash" specify "dbm" or "btree", depending on your system type. The command "postconf -m" displays possible lookup table types. /etc/postfix/main.cf: # Don't send mail to the local delivery agent. mydestination = # All domains that are listed in $virtual_mailbox_domains # are delivered via $virtual_transport, which is the virtual # delivery agent by default. virtual_mailbox_domains = $myhostname localhost.$mydomain virtual1.domain virtual2.domain virtual_transport = virtual virtual_mailbox_base = /var/mail/vhosts virtual_mailbox_maps = hash:/etc/postfix/vmailbox virtual_minimum_uid = 100 virtual_uid_maps = hash:/etc/postfix/vuid virtual_gid_maps = hash:/etc/postfix/vgid Define a virtual delivery agent if the entry doesn't already exist: /etc/postfix/master.cf: virtual unix - n n - - virtual Example recipients, one UNIX-style mailbox, one qmail-style maildir: /etc/postfix/vmailbox: test1@virtual1.domain test1 test2@virtual2.domain test2/ /etc/postfix/vuid: test1@virtual1.domain 5001 test2@virtual2.domain 5002 /etc/postfix/vgid: test1@virtual1.domain 5001 test2@virtual2.domain 5002 Execute something like the following commands for each mailbox recipient: # touch /var/mail/vhosts/test1 # chown 5001:5001 /var/mail/vhosts/test1 Execute something like the following commands for each maildir recipient: # mkdir /var/mail/vhosts/test2 # chown 5002:5002 /var/mail/vhosts/test2 Be sure to make the necessary entries for root@$myhostname, postmaster@$myhostname and for any other necessary addresses. Example 2: co-existing with the default local delivery agent ============================================================ In this example, the default Postfix local delivery agent handles the mail for non-virtual recipients; the virtual delivery agent handles virtual recipients, and all virtual mailboxes are owned by user ID 5000, group ID 5000. Instead of "hash" specify "dbm" or "btree", depending on your system type. The command "postconf -m" displays possible lookup table types. /etc/postfix/main.cf: # All domains and users delivered by the virtual local delivery agent. virtual_transport = virtual virtual_mailbox_base = /var/mail/vhosts virtual_mailbox_maps = hash:/etc/postfix/vmailbox virtual_mailbox_domains = $virtual_mailbox_maps virtual_minimum_uid = 100 virtual_uid_maps = static:5000 virtual_gid_maps = static:5000 # All domains and users delivered by the local delivery agent. # local_recipient_maps is used by the SMTP server to reject mail # for unknown users. local_transport = local mydestination = $myhostname $localhost.$mydomain local_recipient_maps = unix:passwd.byname $alias_maps Define a virtual delivery agent if the entry doesn't already exist: /etc/postfix/master.cf: virtual unix - n n - - virtual Example recipients, one UNIX-style mailbox, one qmail-style maildir: /etc/postfix/vmailbox: test1@virtual1.domain test1 test2@virtual2.domain test2/ /etc/postfix/vmaildomains: virtual1.domain required to prevent relay access denied errors virtual2.domain required to prevent relay access denied errors Execute something like the following commands for each mailbox recipient: # touch /var/mail/vhosts/test1 # chown 5000:5000 /var/mail/vhosts/test1 Execute something like the following commands for each maildir recipient: # mkdir /var/mail/vhosts/test2 # chown 5000:5000 /var/mail/vhosts/test2 Remember that each domain is required to have a postmaster contact address. Example 3: hosting many virtual users ===================================== Example 2 is fine if you host only a few virtual users. With many users you will want to separate the information that changes often (the user addresses) from the information that changes rarely (the names of hosted domains). This example is the same as above, with co-existing local and virtual domains, but it uses a separate table for specifying the virtual domain names. /etc/postfix/main.cf: # All domains and users delivered by the virtual local delivery agent. virtual_transport = virtual virtual_mailbox_base = /var/mail/vhosts virtual_mailbox_maps = hash:/etc/postfix/vmailbox virtual_mailbox_domains = hash:/etc/postfix/vmaildomains virtual_minimum_uid = 100 virtual_uid_maps = static:5000 virtual_gid_maps = static:5000 # All domains and users delivered by the local delivery agent. # local_recipient_maps is used by the SMTP server to reject mail # for unknown users. local_transport = local mydestination = $myhostname $localhost.$mydomain local_recipient_maps = unix:passwd.byname $alias_maps Define a virtual delivery agent if the entry doesn't already exist: /etc/postfix/master.cf: virtual unix - n n - - virtual Example recipients, one UNIX-style mailbox, one qmail-style maildir: /etc/postfix/vmailbox: test1@virtual1.domain test1 test2@virtual2.domain test2/ /etc/postfix/vmaildomains: virtual1.domain required to prevent relay access denied errors virtual2.domain required to prevent relay access denied errors Execute something like the following commands for each mailbox recipient: # touch /var/mail/vhosts/test1 # chown 5000:5000 /var/mail/vhosts/test1 Execute something like the following commands for each maildir recipient: # mkdir /var/mail/vhosts/test2 # chown 5000:5000 /var/mail/vhosts/test2 Remember that each domain is required to have a postmaster contact address. Example 4: forwarding mail for an old account to a new address ============================================================== In order to forward mail for a user who no longer exists, one would set up a rule in a virtual table (please ignore the text in the virtual configuration file about virtual domains): /etc/postfix/main.cf: virtual_maps = hash:/etc/postfix/virtual /etc/postfix/virtual: old_user@old.domain new_user@new.domain Example 5: setting up a virtual vacation autoresponder ====================================================== In order to set up an autoreply for virtual recipients while still delivering mail as normal, set up a rule in a virtual table (please ignore the text in the virtual configuration file about virtual domains): /etc/postfix/main.cf: virtual_maps = hash:/etc/postfix/virtual /etc/postfix/virtual: user@domain.tld user@domain.tld, user@autoreply.domain.tld This delivers mail to the recipient, and sends a copy of the mail to the address that produces automatic replies. The address can be serviced on a different machine, or it can be serviced locally by setting up a transport map entry that pipes all mail for the autoreply.domain.tld into some script that sends an automatic reply back to the sender.