Simple E-Mail Config with Postfix and Cyrus IMAP
This is a quick, no-frills guide to getting email running on a minimal Linux installation (Red Hat, Fedora or CentOS), such as the one you get when you launch a node in AWS from a predefined AMI (Amazon Machine Image).
Red Hat-family distributions ship with Postfix as the MTA (Mail Transport Agent) and Cyrus IMAP as the MDA (Mail Delivery Agent), so this guide focuses on those two. Once both packages are installed, the work is mostly in the configuration files.
/etc/postfix/main.cf: the Postfix configuration. It controls which emails are accepted and how they are handled./etc/imapd.conf: Cyrus IMAP settings, such as where mailbox passwords are stored and which authentication mechanisms POP/IMAP support./etc/sasl2/smtpd.conf: SMTP authentication settings, needed if you want to run a mail relay. (This file may instead be at/usr/lib/sasl2/smtpd.conf.)
There is also /etc/cyrus.conf, which normally has sensible defaults after installation, so you probably won’t need to touch it. It defines the supported protocols (POP3, POP3S, IMAP, IMAPS) and the location of the LMTP socket, the interface between Postfix and Cyrus IMAP.
Add these essential settings to /etc/postfix/main.cf:
mailbox_transport = lmtp:unix:/var/lib/imap/socket/lmtp
virtual_transport = $mailbox_transport
virtual_mailbox_domains = /etc/postfix/virtual_domains
virtual_mailbox_maps = hash:/etc/postfix/virtual_maps
What this does: Mail addressed to the domains listed in virtual_domains is accepted for further processing. Postfix then looks up the destination mailbox in virtual_mailbox_maps; if no mailbox is found, an error goes back to the sender. Actual delivery happens through the socket defined in mailbox_transport.
Example file contents:
# cat /etc/postfix/virtual_domains
brainware.ro
# cat /etc/postfix/virtual_maps
john.doe@brainware.ro brainware.ro/john.doe
The virtual_maps file must be converted into a hash database with postmap:
# postmap hash:/etc/postfix/virtual_maps
Confirm the Cyrus daemon is listening on the right LMTP socket (it should be by default):
# cat /etc/cyrus.conf | grep lmtp
lmtpunix cmd="lmtpd" listen="/var/lib/imap/socket/lmtp" prefork=1
Note: At this point you may want to either disable SELinux (easy), or add the required SELinux rules (harder) so that Postfix and Cyrus IMAP can communicate over the socket.
For corporate-style addresses (name.surname@domain), the mailbox namespace separator has to be something other than the dot. Change it in /etc/imapd.conf:
unixhierarchysep: 1 # changes the separator to "/"
Other settings to review in imapd.conf:
admins: cyrus # user allowed to run Cyrus admin commands
sasl_mech_list: plain login cram-md5 digest-md5 ntlm gssapi # enable all mechanisms
sasl_pwcheck_method: auxprop # look up passwords in /etc/sasldb2
virtdomains: userid # derive the domain from the mailbox name (user@domain)
allowanonymouslogin: no # security
allowplaintext: yes # allow older login methods (e.g. testing with telnet)
Restart both services to apply the new configuration:
# service postfix restart
Shutting down postfix: [ OK ]
Starting postfix: [ OK ]
# service cyrus-imapd restart
Shutting down cyrus-imapd: [ OK ]
Exporting cyrus-imapd databases: [ OK ]
Importing cyrus-imapd databases: [ OK ]
Starting cyrus-imapd: [ OK ]
We’re close to done. First, check the permissions on /etc/sasldb2. (Be aware that passwords are stored there without any encryption.)
# ls -la /etc/sasldb2
-rw-r----- 1 cyrus mail 12288 Oct 15 12:34 sasldb2
Before running cyradm (the Cyrus IMAP admin tool) for the first time, set a password for the cyrus admin user defined in /etc/imapd.conf:
# saslpasswd2 -c "cyrus"
Password:
...
Now run cyradm, create your first mailbox, then set its password:
# cyradm -u cyrus localhost
IMAP Password:
localhost> cm user/john.doe@brainware.ro
localhost> quit
# saslpasswd2 -c "john.doe@brainware.ro"
Password:
...
Test a plaintext POP3 login using telnet:
# telnet localhost 110
Trying ::1...
Connected to localhost.
Escape character is '^]'.
+OK ...
user john.doe@brainware.ro
+OK Name is a valid mailbox
pass ...
+OK Mailbox locked and ready
list
+OK scan listing follows
...
quit
+OK
Connection closed by foreign host.
If you also want to relay email using SMTP authentication, first enable it in Postfix by adding to /etc/postfix/main.cf:
smtpd_sender_restrictions = permit_mynetworks, permit_sasl_authenticated
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, permit
smtpd_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
Then set up the authentication mechanism in /etc/sasl2/smtpd.conf (remember the alternate location, /usr/lib/sasl2/smtpd.conf, mentioned above):
pwcheck_method: auxprop # use /etc/sasldb2
auxprop_plugin: sasldb
mech_list: plain login cram-md5 digest-md5 ntlm gssapi # enable all mechanisms
After one more Postfix restart, you should have a simple, working email service built on Postfix and Cyrus IMAP. Thanks for reading!