Separate Domains with Virtual Accounts
The drawback for the techniques so far is that you must maintain system accounts for all email addresses on your server. As the number of domains you host increases, so does the effort to maintain all the accounts. In particular, if users only receive email at your server, and don't otherwise log in, you probably don't want to have to create system accounts for each one. Instead, configure Postfix to deliver to a local message store where each virtual email address can have its own mailbox file. Your users then retrieve their messages through a POP/IMAP server.
The local message store works much like normal local delivery, but it doesn't require a one-to-one correspondence between each mail file and a local user account. For this configuration, list each virtual domain in the virtual_mailbox_domains parameter:
virtual_mailbox_domains = ora.com, oreilly.com
If you have many domains, you can list them in a file and point virtual_mailbox_domains to the file:
virtual_mailbox_domains = /etc/postfix/virtual_domains
The file /etc/postfix/virtual_domains then contains a line for each domain:
# # /etc/postfix/virtual_domains # ora.com oreilly.com
Virtual domains listed in virtual_mailbox_domains are delivered by the virtual delivery agent, which is actually a streamlined version of the local delivery agent. It makes deliveries in a highly secure and efficient manner, but local aliases, .forward files, and mailing list programs are not available. You can make use of the virtual_alias_maps parameter that you saw earlier in the chapter to accomplish aliasing, and we'll look at a technique to accomplish delivery to programs later in this chapter.
When setting up the virtual mailboxes, you should structure the directories to accommodate the expectations of your POP/IMAP server. Let's assume for this explanation that the virtual mailboxes are all located below the base directory /usr/local/vmail. Each virtual domain has its own subdirectory below that, so that you have directories like the following:
/usr/local/vmail/ora.com /usr/local/vmail/oreilly.com
This is a common configuration for POP/IMAP servers that support virtual hosting. Below each domain subdirectory are the mail files for each user. Indicate to Postfix the base directory of the mail store with the virtual_mailbox_base parameter:
virtual_mailbox_base = /usr/local/vmail
You must create a lookup file that maps email addresses to their mailbox files. Specify the lookup table with the virtual_mailbox_maps parameter:
virtual_mailbox_maps = hash:/etc/postfix/virtual
Every user receiving mail to a virtual mailbox file must have an entry in a Postfix lookup table. The mailbox file is specified relative to virtual_mailbox_base. Mail files can use either mbox or maildir format (see Chapter 7). To use maildir format, include a slash at the end of the filename. A virtual mailbox map file looks like the following:
info@ora.com ora.com/info info@oreilly.com oreilly.com/info
The email address info@ora.com goes to a different mailbox from the address info@oreilly.com.
8.3.1 Mailbox File Ownership
The virtual mailbox files must be owned by a user account and associated with a group on your system. How your users retrieve their messages determines what the ownership of mailbox files should be. Often, your POP/IMAP server executes under its own account and expects all of the mailbox files to be owned by this user, but if necessary, Postfix lets you configure ownership for mailbox files in any way you need. Each can be owned by a separate user, or one user can own all of the mailboxes for one domain, while a different user owns the mailboxes of another.
The virtual_uid_maps and virtual_gid_maps parameters determine the owner and group Postfix uses when making deliveries to virtual mailbox files. You can specify that all of the virtual mailboxes should be owned by the same user account with the static map type. Assume, for this example, that you have created an account called vmail that has a UID of 1003, and a group called vmail that has a GID of 1005. You want all of the virtual mailbox files to be owned by this user and group.
Set the virtual_uid_maps and virtual_gid_maps parameters in main.cf:
virtual_uid_maps = static:1003 virtual_gid_maps = static:1005
If you want to use different UIDs for different mailbox files, you must create a lookup file that maps the addresses to the UIDs. Then point the mapping parameter to your lookup file:
virtual_uid_maps = hash:/etc/postfix/virtual_uids
If most of your virtual mailboxes should have the same fixed ownership but some require different UIDs, you can combine static and table lookups:
virtual_uid_maps = hash:/etc/postfix/virtual_uids static:1003
If you also need separate group mappings, they work exactly the same way.
The file /etc/postfix/virtual_uids contains entries like the following, with each address mapped to the correct UID. In this case, the mailboxes for ora.com use one ID and those for oreilly.com use another:
# # /etc/postfix/virtual_uids # info@ora.com 1004 kdent@ora.com 1004 info@oreilly.com 1007 service@oreilly.com 1007
8.3.2 Virtual Aliases
It is possible for a virtually hosted domain to have some addresses that are delivered to the local message store and some that are forwarded. Since all recipient addresses are checked for virtual aliasing regardless of their class, simply place the forwarded addresses in the virtual_alias_maps file instead of the virtual_mailbox_maps file. Make sure the virtual_alias_maps parameter points to a virtual alias lookup table:
virtual_alias_maps = hash:/etc/postfix/virtual_alias
The /etc/postfix/virtual_alias file contains entries for addresses that should be forwarded elsewhere:
kdent@oreilly.com kyle.dent@onlamp.com
Do not list a domain in both virtual_mailbox_domains and virtual_alias_domains. Use virtual_mailbox_domains for domains that have a mix of aliases and mailboxes and virtual_alias_domains only when all of the addresses are aliases.
8.3.3 Catchall Addresses
For either virtual mailboxes or virtual aliases, your lookup table can have a key value of the domain without a local part to catch any message destined for the domain addressed to a nonexistent address. Catchall addresses should be used advisedly, since they tend to receive a lot of spam. Spammers often send messages to nonexistent accounts at a domain, which are received by catchall addresses.
8.3.3.1 Virtual mailbox catchall
The first step is to identify a mailbox to receive messages sent to nonexistent addresses. You can use an existing mailbox or create a new one. Add a new virtual_mailbox_maps entry like the following to deliver any message with an unknown destination address to the service mailbox:
@ora.com ora.com/service
8.3.3.2 Virtual alias catchall
Catchall addresses with virtual aliases work similarly to virtual mailboxes, but you should set up a catchall alias address only if all addresses in a domain are configured as aliases and not mailboxes. Since virtual aliases are checked before virtual mailboxes, a catchall alias intercepts all messages, including those otherwise destined for virtual mailbox addresses. Once you've identified the address that should receive messages sent to nonexistent addresses, add a new virtual_alias_maps entry like the following:
@ora.com customer.service@onlamp.com
It's possible to have a virtual alias catchall address in conjunction with virtual mailbox addresses by creating entries for all of your virtual mailbox addresses in your virtual alias lookup maps. Assuming you have virtual mailboxes configured like the following:
info@ora.com ora.com/info info@oreilly.com oreilly.com/info
your virtual alias lookup table that includes a catchall alias must also contain the mailbox entries:
@ora.com customer.service@onlamp.com kdent@oreilly.com kyle.dent@onlamp.com info@ora.com info@ora.com info@oreilly.com info@oreilly.com
In this way, a message addressed to info@oreilly.com won't be intercepted by the @ora.com catchall alias.