Mail Configuration
- Basics (Exim)
- Maildir delivery to virtual users
- Outgoing mail
- Store copies of sent mail
- Aliases
- An infinite address pool for testing
- IMAP access
- Webmail
- Spam filtering
- Email client
- IMAP folders (Dovecot)
- Mail submission from firewalled machines
- Mail delivery to firewalled machines
- References
Basics (Exim)
First I need to set up forward and reverse DNS for the IP of the mail server.
Then:
primary_hostname = mail.bsdpower.com
Maildir delivery to virtual users
All mail users are virtual, that is, do not map to Unix user accounts. I want mail to be stored in Maildirs.
Create a Unix user for the virtual mail users:
useradd vmail
In order to prohibit world read access to mailboxes, mailnull
user (for Exim)
must be added to vmail group. Otherwise Exim will fail sender verification
when sending mail to remote machines. After this change Exim must be restarted.
Define the router:
dovecot:
driver = accept
local_part_suffix = +* : -*
local_part_suffix_optional
condition = ${if exists{/home/vmail/users/$local_part} {yes} {no} }
transport = dovecot
The dovecot router should be placed in front of the local users one.
Define the transport:
dovecot:
driver = appendfile
user = vmail
group = vmail
mode = 0600
directory=/home/vmail/users/${lc:$local_part}/
maildir_format = true
mode_fail_narrower = false
envelope_to_add = true
return_path_add = true
Outgoing mail
To send mail, I need to use the submission port (587) and set up authentication.
Submission port (Exim)
daemon_smtp_ports = 25 : 587
SMTP authentication (Exim)
# Allow any client to use TLS.
tls_advertise_hosts = *
# Specify the location of the Exim server's TLS certificate and private key.
tls_certificate = /usr/local/etc/exim/ssl/cert.pem
tls_privatekey = /usr/local/etc/exim/ssl/privatekey.pem
Now define an authenticator:
send:
driver = plaintext
server_set_id = $auth2
server_condition = ${if eq{$auth3}{${lookup{$auth2}lsearch{/usr/local/etc/exim/passwd}}}}
server_advertise_condition = ${if eq{$tls_cipher}{}{}{*}}
server_prompts = :
public_name = PLAIN
Sender override
By default, messages submitted via the submission protocol are modified by Exim to have the user that is used for authentication as the sender. This manifests in the sender user being in the envelope from header and also "on behalf of" addition to the originating email address.
In my case the user I use for authentication is not the user I send email from, therefore for this particular user I want to tell Exim to leave my original sender.
untrusted_set_sender = {if eq {$sender_ident}{send} {*} {}}
local_from_check = {if eq {$sender_ident}{send} {false} {true}}
Here, send
is the user I authenticate as when sending mail.
Removing Sender header / "On behalf of"
References:
- https://lists.exim.org/lurker/message/20040628.144414.ac656633.html
Store copies of sent mail
No matter how I send mail, I want to save the sent messages on the mail server.
The solution is based on
this post
and this one.
There is a difference between storing copies of submitted mail and
mail that is being delivered. In case of a mail to multiple recipients,
I want to make sure there is only one copy of it saved. Using
a transport with unseen
option operates on per-delivery basis, and therefore
creates multiple copies when mailing multiple recipients. System filter
creates a single copy.
First define a system filter:
system_filter = /usr/local/etc/exim/systemfilter
system_filter_directory_transport = sendcopy
System filter itself:
# Exim filter
if $sender_address_domain is bsdpower.com
or $sender_address_domain is mail.bsdpower.com
then
unseen save /home/vmail/sent/$sender_address/
endif
Define sendcopy transport:
sendcopy:
driver = appendfile
user = vmail
group = vmail
mode = 0600
#directory = /home/vmail/sent/$sender_address_local_part
directory = /home/vmail/sent/${if eq {${domain:$reply_address}}{bsdpower.com} {${local_part:$reply_address}} {$sender_address_local_part}}
#directory = /home/vmail/sent/${local_part:$reply_address}
maildir_format = true
create_directory = true
envelope_to_add
return_path_add
Aliases
For this I simply use the system alias file, /etc/aliases
.
I cycle email addresses used for registration. For example, reg2012
for an account created in 2012. In 2013 I would update the email
address if I still use the account. All current aliases are forwarded
to reg
, all expired/unused aliases are forwarded to reg-old
.
An infinite address pool for testing
Useful for developers testing web applications.
wildcard:
driver = redirect
domains = wildcard.bsdpower.com
local_part_prefix = wildcard-
data = wildcard-target@bsdpower.com
IMAP access
This will be done with dovecot.
Dovecot password file permissions
On my system, /usr/local/etc/dovecot/dovecot.passwd
is accessed by
Dovecot with dovecot
user and dovecot
as the only group.
Therefore:
chown root:dovecot /usr/local/etc/dovecot/dovecot.passwd
chmod 0640 /usr/local/etc/dovecot/dovecot.passwd
Webmail
None yet. All (working) webmail solutions I found use php and I am not excited to run php on the same system that handles my mail. Maybe on a separate system with access to selected accounts only.
Spam filtering
I use zen.spamhaus.org
blacklist. This kills a lot of the mail but
not everything. The remaining amount of spam is rather manageable at this
point.
deny message = rejected because $sender_host_address is blacklisted by $dnslist_domain\n$dnslist_text
dnslists = zen.spamhaus.org : cbl.abuseat.org
As my "pretty" email address appears in various public locations, it will always be receiving spam. I could work around this issue by cycling my public email address, but this would present an inconvenience to people emailing me.
Blacklist check: http://www.kloth.net/services/dnsbl.php
Email client
I use claws-mail. It works well and is lightweight.
IMAP folders (Dovecot)
It looks like the documentation for this is in
Maildir format page and
Maildir++ description.
The short version is a folder with name Foo is stored a a subdirectory with
name .Foo
under the maildir directory, and there is a marker file called
maildirfolder
in .Foo
.
Mail submission from firewalled machines
It turns out to be much easier to set up a local Exim to submit to the Internet server than to repeatedly configure SMTP for each user account. The downside to having a functional local MTA is that I need to be careful not to send real people email by accident.
Most of this configuration was taken from here with this used as initial inspiration.
First, comment out the dnslookup driver.
Then, create a smarthost driver in its place:
smarthost:
driver = manualroute
domains = ! +local_domains
transport = remote_smtp_submission
route_data = mail.bsdpower.com
no_more
Define submission transport:
remote_smtp_submission:
driver = smtp
port = 587
hosts_require_tls = *
hosts_require_auth = *
And define an authenticator for the client side:
plain:
driver = plaintext
public_name = plain
client_send = ^smtplogin^smtppassword
Here I just hardcoded login and password which works sufficiently well.
Mail delivery to firewalled machines
This is handy for a server that cannot receive mail on port 25 due to a firewall.
First, an MX record is configured for my "normal" server.
On the normal server, I have the following router:
firewalled:
driver = manualroute
domains = firewalled.bsdpower.net : *.firewalled.bsdpower.net
transport = remote_smtp_submission
route_list = * firewalled.bsdpower.net
And the transport to go with it:
remote_smtp_submission:
driver = smtp
port = 587
# If the public server is multihomed, specify which IP address to use
# for connecting.
#interface = 1.2.3.4