I stumbled over this post while looking at how other people had set-up virtual domains with Exim4 and Dovecot.
It made me realise I’d only half-implemented a virtual domain solution. The key part is that there is a user (vmail) which owns all the virtual mailboxes and operates on behalf of the virtual domain users. I’ve implemented a slighly different approach to that outlined in the post.
Virtual Domain Structure
The virtual domain mailboxes are held in /home/vmail
, structured as follows:
/home/vmail /domain1 /aliases /user1 /mail /user2 /mail /domain2 /aliases /user1 /mail /user2 /mail
The aliases file under each domain is the domain specific alias file,
organised exactly as /etc/aliases
.
Exim4
The router
This is the modified router configuration for virtual domains, using
the above structure to identify a virtual domain user. The domain name
must exist as a directory in the /home/vmail
account and contain an
aliases file to validate the local_part of the address. If the
local_part cannot be located in the aliases file, the email will not
be accepted for the virtual domain.
# Router for virtual domains # Use of domain_data to avoid using tainted data # Data is considered tainted if if comes from the mail virtual_domains: debug_print = "R: virtual_domains for $local_part@$domain" driver = accept domains = dsearch;/home/vmail local_parts = wildlsearch;/home/vmail/${domain_data}/aliases transport = virtual_mailboxes
So, the aliases file for example.com say, could have the following contents:
user.alias: user ^user\\W.*: user
You’ll note the use of wildlsearch
for looking up names in the
domain file. In this setup, a mail directed to user@example.com would
not be accepted.
The configuration file was named 250_exim4-config_virtual_domain
which means it is defined right after the primary configuration for
sending mail and before routers for local delivery.
The transport
# Transport for virtual mail boxes # Use of local_part_data/domain_data to avoid "tainted data" # Data is considered tainted if it comes from the mail virtual_mailboxes: debug_print = "T: virtual_mailboxes for $local_part$domain" driver = appendfile file = /var/mail/${local_part_data}@${domain_data} user = vmail # group must be set to allow exim to write to user's mailbox group = mail
The transport directs the delivery to the users mailbox. The mailbox name is in the form name@example.com, and will be owned by vmail:mail.
Note that local_part_data
and domain_data
are used to avoid taint
errors.
Transports are not sensitive to the order of definition, so this
transport configuration was place in a file called
30_exim4-config_virtual_mailboxes
.
Authentication
The virtual domain users need to be added to the /etc/exim4/passwd
file, the format of which is described in the man page for
exim4-config_files
. User names are in the form user@example.com.
Dovecot
Mailbox configuration
Dovecot has to be configured to use the correct path for the user’s
incoming mailbox. This is set in the
/etc/dovecot/conf.d/10-mail.conf
file.
mail_location = mbox:~/mail:INBOX=/var/mail/%u:LAYOUT=maildir++:\ INDEX=~/mail/index:CONTROL=~/mail/control
The use of "%u" in the INBOX definition uses the full login name of the virtual user as the mailbox name.
The mail for real local users is still delivered (by Exim4) to
/var/mail/user
so to allow Dovecot access, a link can be created
from user@realdomain to user in the /var/mail
directory. Another
solution might be to alter the Exim4 transport
30_exim4-config_mail_spool
to deliver incoming mail to the same
name@domain name format as the virtual domain.
In this latter approach, the command line mail program would need
configuring to consult the correct mailbox file. For example, for GNU
mail, put this in the users ~/.mail
file:
mailbox { mailbox-pattern "/var/mail/${user}@domain"; }
Authentication
I use Dovecot’s passwd-file to authenticate users, rather than /etc/passwd. This allows the users of the domain to have their email address as the username. The uid and gid for virtual users should be those of the vmail user. E.g. if both the vmail uid and gid is 1234:
user@domain.com:{CRYPT}password:1234:1234::/home/vmail/domain.com/user
It’s a shame that Dovecot and Exim4 authentication is completely separate.
Updating the system
The new Exim4 configuration template can be created and installed with the following commands:
sudo update-exim4.conf.template -r sudo update-exim4.conf
Restart Exim4 with:
sudo systemctl restart exim4 sudo systemctl restart dovecot
Update
That comment above, about Dovecot and Exim4 authentication separation,
is not quite true. I found the clue in
this
article. While the example in the article is based on OpenSMTPD and
Dovecot, it turns out that they cannot share an authorisation
file. The table type of passwd
, used in the sample smtpd.conf
file is no longer supported by OpenSMTPD.
The exim auth file format is a subset of dovecot’s and exim can successfully use the dovecot auth file. To make this work, permissions on the shared auth file must be set to allow both exim and dovecot to read the file. For example:
# mv /etc/dovecot/auth-users /etc/auth/mail # chmod 640 /etc/auth/mail # chown dovecot:Debian-exim /etc/auth/mail