Email with Postfix, Dovecot and MySQL on CentOS 5
Updated by Elle Krout Written by Linode
DeprecatedThis guide has been deprecated and is no longer being maintained.
The Postfix Mail Transfer Agent (MTA) is a high performance open source e-mail server system. This guide will help you get Postfix running on your CentOS 5 Linode, using Dovecot for IMAP/POP3 service, and MySQL to store information on virtual domains and users.
Prior to using this guide, be sure you have followed the getting started guide and set your hostname.
NoteThe steps in this guide require root privileges. Be sure to run the steps below asroot
, or usesu - root
to log in as root. Certain commands below cannot be run assudo
and must be run as root.
Install Required Packages
Install any outstanding package updates:
yum update
The version of Postfix included in the main CentOS repository does not include support for MySQL; therefore, you will need install Postfix from the CentOS Plus repository. Before doing so, add exclusions to the
[base]
and[updates]
repositories for the Postfix package to prevent it from being overwritten with updates that do not have MySQL support:- /etc/yum.repos.d/CentOS-Base.repo
-
1 2 3 4 5 6 7 8
[base] name=CentOS-$releasever - Base exclude=postfix # released updates [updates] name=CentOS-$releasever - Updates exclude=postfix
Install the required packages:
yum --enablerepo=centosplus install postfix yum install dovecot mysql-server
This installs the Postfix mail server, the MySQL database server, the Dovecot IMAP and POP daemons, and several supporting packages that provide services related to authentication.
Next, set up a MySQL database to handle virtual domains and users.
Set up MySQL for Virtual Domains and Users
Configure MySQL to start on boot, then start MySQL:
chkconfig mysqld on service mysqld start
Run
mysql_secure_installation
. You will be presented with the opportunity to change the MySQL root password, remove anonymous user accounts, disable root logins outside of localhost, remove test databases, and reload privilege tables. It is recommended that you answer yes to these options:mysql_secure_installation
Start the MySQL shell:
mysql -u root -p
Create a database for your mail server and switch to it:
CREATE DATABASE mail; USE mail;
Create a mail administration user called
mail_admin
and grant it permissions on themail
database. Please be sure to replacemail_admin_password
with a strong password:GRANT SELECT, INSERT, UPDATE, DELETE ON mail.* TO 'mail_admin'@'localhost' IDENTIFIED BY 'mail_admin_password'; GRANT SELECT, INSERT, UPDATE, DELETE ON mail.* TO 'mail_admin'@'localhost.localdomain' IDENTIFIED BY 'mail_admin_password'; FLUSH PRIVILEGES;
Create the virtual domains table:
CREATE TABLE domains (domain varchar(50) NOT NULL, PRIMARY KEY (domain) );
Create a table to handle mail forwarding:
CREATE TABLE forwardings (source varchar(80) NOT NULL, destination TEXT NOT NULL, PRIMARY KEY (source) );
Create the users table:
CREATE TABLE users (email varchar(80) NOT NULL, password varchar(20) NOT NULL, PRIMARY KEY (email) );
Create a transports table:
CREATE TABLE transport ( domain varchar(128) NOT NULL default '', transport varchar(128) NOT NULL default '', UNIQUE KEY domain (domain) );
Exit the MySQL shell:
quit
Bind MySQL to localhost (127.0.0.1) by editing
/etc/my.cnf
, and adding the following to the[mysqld]
section of the file:- /etc/my.cnf
-
1
bind-address=127.0.0.1
This is required for Postfix to be able to communicate with the database server. If you have MySQL set up to listen on another IP address (such as an internal IP), you will need to substitute this IP address in place of
127.0.0.1
during the Postfix configuration steps. It is not advisable to run MySQL on a publicly-accessible IP address.Restart the database server:
service mysqld restart
Next, perform additional Postfix configuration to set up communication with the database.
Configure Postfix to work with MySQL
NoteFor the next four steps, replacemail_admin_password
with themail_admin
password input earlier.
Create a virtual domain configuration file for Postfix called
/etc/postfix/mysql-virtual_domains.cf
:- /etc/postfix/mysql-virtual_domains.cf
-
1 2 3 4 5
user = mail_admin password = mail_admin_password dbname = mail query = SELECT domain AS virtual FROM domains WHERE domain='%s' hosts = 127.0.0.1
Create a virtual forwarding file for Postfix called
/etc/postfix/mysql-virtual_forwardings.cf
:- /etc/postfix/mysql-virtual_forwardings.cf
-
1 2 3 4 5
user = mail_admin password = mail_admin_password dbname = mail query = SELECT destination FROM forwardings WHERE source='%s' hosts = 127.0.0.1
Create a virtual mailbox configuration file for Postfix called
/etc/postfix/mysql-virtual_mailboxes.cf
:- /etc/postfix/mysql-virtual_mailboxes.cf
-
1 2 3 4 5
user = mail_admin password = mail_admin_password dbname = mail query = SELECT CONCAT(SUBSTRING_INDEX(email,<'@'>,-1),'/',SUBSTRING_INDEX(email,<'@'>,1),'/') FROM users WHERE email='%s' hosts = 127.0.0.1
Create a virtual email mapping file for Postfix called
/etc/postfix/mysql-virtual_email2email.cf
:- /etc/postfix/mysql-virtual_email2email.cf
-
1 2 3 4 5
user = mail_admin password = mail_admin_password dbname = mail query = SELECT email FROM users WHERE email='%s' hosts = 127.0.0.1
Set proper permissions and ownership for these configuration files:
chmod o= /etc/postfix/mysql-virtual_*.cf chgrp postfix /etc/postfix/mysql-virtual_*.cf
Create a user and group for mail handling. All virtual mailboxes will be stored under this user’s home directory:
groupadd -g 5000 vmail useradd -g vmail -u 5000 vmail -d /home/vmail -m
Complete the remaining steps required for Postfix configuration. Please be sure to replace
server.example.com
with the Linode’s fully qualified domain name. If you are planning on using your own SSL certificate and key, replace/etc/pki/dovecot/private/dovecot.pem
with the appropriate path:postconf -e 'myhostname = server.example.com' postconf -e 'mydestination = $myhostname, localhost, localhost.localdomain' postconf -e 'mynetworks = 127.0.0.0/8' postconf -e 'inet_interfaces = all' postconf -e 'message_size_limit = 30720000' postconf -e 'virtual_alias_domains =' postconf -e 'virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual_forwardings.cf, mysql:/etc/postfix/mysql-virtual_email2email.cf' postconf -e 'virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains.cf' postconf -e 'virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailboxes.cf' postconf -e 'virtual_mailbox_base = /home/vmail' postconf -e 'virtual_uid_maps = static:5000' postconf -e 'virtual_gid_maps = static:5000' postconf -e 'smtpd_sasl_type = dovecot' postconf -e 'smtpd_sasl_path = private/auth' postconf -e 'smtpd_sasl_auth_enable = yes' postconf -e 'broken_sasl_auth_clients = yes' postconf -e 'smtpd_sasl_authenticated_header = yes' postconf -e 'smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination' postconf -e 'smtpd_use_tls = yes' postconf -e 'smtpd_tls_cert_file = /etc/pki/dovecot/certs/dovecot.pem' postconf -e 'smtpd_tls_key_file = /etc/pki/dovecot/private/dovecot.pem' postconf -e 'virtual_create_maildirsize = yes' postconf -e 'virtual_maildir_extended = yes' postconf -e 'proxy_read_maps = $local_recipient_maps $mydestination $virtual_alias_maps $virtual_alias_domains $virtual_mailbox_maps $virtual_mailbox_domains $relay_recipient_maps $relay_domains $canonical_maps $sender_canonical_maps $recipient_canonical_maps $relocated_maps $transport_maps $mynetworks $virtual_mailbox_limit_maps' postconf -e 'virtual_transport = dovecot' postconf -e 'dovecot_destination_recipient_limit = 1'
Edit the file
/etc/postfix/master.cf
and add the Dovecot service to the bottom of the file:- /etc/postfix/master.cf
-
1 2
dovecot unix - n n - - pipe flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}
Shut down Sendmail, then configure Postfix to start on boot and start the service for the first time:
service sendmail stop chkconfig sendmail off chkconfig postfix on service postfix start
This completes the configuration for Postfix.
Configure Dovecot
Move
/etc/dovecot.conf
to a backup file:mv /etc/dovecot.conf /etc/dovecot.conf-backup
Copy the following into the now-empty
dovecot.conf
file, substituting your system’s domain name forexample.com
in line 17:- /etc/dovecot.conf
-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
protocols = imap imaps pop3 pop3s log_timestamp = "%Y-%m-%d %H:%M:%S " mail_location = maildir:/home/vmail/%d/%n/Maildir ssl_cert_file = /etc/pki/dovecot/certs/dovecot.pem ssl_key_file = /etc/pki/dovecot/private/dovecot.pem namespace private { separator = . prefix = INBOX. inbox = yes } protocol lda { log_path = /home/vmail/dovecot-deliver.log auth_socket_path = /var/run/dovecot/auth-master postmaster_address = postmaster@example.com } protocol pop3 { pop3_uidl_format = %08Xu%08Xv } auth default { user = root passdb sql { args = /etc/dovecot-sql.conf } userdb static { args = uid=5000 gid=5000 home=/home/vmail/%d/%n allow_all_users=yes } socket listen { master { path = /var/run/dovecot/auth-master mode = 0600 user = vmail } client { path = /var/spool/postfix/private/auth mode = 0660 user = postfix group = postfix } } }
MySQL will be used to store password information, so
/etc/dovecot-sql.conf
must be created. Insert the following contents into the file, making sure to replacemail_admin_password
with your mail password:- /etc/dovecot-sql.conf
-
1 2 3 4
driver = mysql connect = host=127.0.0.1 dbname=mail user=mail_admin password=mail_admin_password default_pass_scheme = CRYPT password_query = SELECT email as user, password FROM users WHERE email='%u';
Restrict access to the file by changing the permissions to allow users in the
dovecot
group to access it, while denying access to others:chgrp dovecot /etc/dovecot-sql.conf chmod o= /etc/dovecot-sql.conf
Configure Dovecot to start on boot, and start it for the first time:
chkconfig dovecot on service dovecot start
Now check
/var/log/maillog
to make sure Dovecot started without errors. Your log should have lines similar to the following:- /var/log/maillog
-
1 2 3 4
Mar 18 10:00:23 li833-84 dovecot: Dovecot v1.0.7 starting up Mar 18 10:00:23 li833-84 dovecot: Generating Diffie-Hellman parameters for the first time. This may take a while.. Mar 18 10:00:23 li833-84 dovecot: auth-worker(default): mysql: Connected to 127.0.0.1 (mail) Mar 18 10:00:25 li833-84 dovecot: ssl-build-param: SSL parameters regeneration completed
Test your POP3 server to make sure it’s running properly:
telnet localhost pop3
The terminal should output results similar to the following:
Trying 127.0.0.1... Connected to localhost.localdomain. Escape character is '^]'. +OK Dovecot ready.
Enter the command
quit
to return to your shell. This completes the Dovecot configuration.
Next, you’ll make sure aliases are configured properly.
Configure Mail Aliases
Edit the file
/etc/aliases
, making sure thepostmaster
androot
directives are set properly for your organization:- /etc/aliases
-
1 2
postmaster: root root: postmaster@example.com
Update aliases and restart Postfix:
newaliases service postfix restart
This completes alias configuration. Next, test Postfix to make sure it’s operating properly.
Testing Postfix
Test Postfix for SMTP-AUTH and TLS:
telnet localhost 25
While still connected, issue the following command:
ehlo localhost
You should see output similar to the following:
250-hostname.example.com 250-PIPELINING 250-SIZE 30720000 250-VRFY 250-ETRN 250-STARTTLS 250-AUTH PLAIN 250-AUTH=PLAIN 250-ENHANCEDSTATUSCODES 250-8BITMIME 250 DSN
Issue the command
quit
to terminate the telnet connection.
Next, populate the MySQL database with domains and email users.
Set Up and Test Domains and Users
NoteBefore continuing, modify the DNS records for any domains that you wish to handle email by adding an MX record that points to your mail server’s fully qualified domain name. If MX records already exist for a domain you would like to handle the email for, either delete them or set them to a higher priority number than your mail server. Smaller priority numbers indicate higher priority for mail delivery, with “0” being the highest priority.
In the following example, the MySQL shell is used to add support for the domain “example.com”, which will have an email account called “sales”.
Log into the MySQL shell:
mysql -u root -p
Switch to the
mail
database, add support for your domain, and create an email account. Be sure to replaceexample.com
with your domain name,sales@example.com
with your chosen email, andpassword
with a strong password:USE mail; INSERT INTO domains (domain) VALUES ('example.com'); INSERT INTO users (email, password) VALUES ('sales@example.com', ENCRYPT('password')); quit
Prior to accessing any newly-created email accounts, a test message needs to be sent to create that user’s mailbox:
mailx sales@example.com
Press
Ctrl+D
to complete the message. You can safely leave the field forCc:
blank. This completes the configuration for a new domain and email user.
NoteGiven the possibility for virtual hosting a large number of domains on a single mail system, the username portion of an email address (i.e. before the@
sign) is not sufficient for authentication. When email users authenticate to the server, they must supply the entire email address created above as their username.
Check Your Logs
After the test mail is sent, check the mail logs to make sure the mail was delivered.
Check the
maillog
located in/var/log/maillog
. You should see something similar to the following:- /var/log/maillog
-
1 2 3 4 5 6
Mar 18 10:19:08 li833-84 postfix/cleanup[4568]: 73A35BE52: message-id=<201503181419.t2IEJ7jn004561@server.example.com> Mar 18 10:19:08 li833-84 postfix/qmgr[4510]: 73A35BE52: from=<root@server.example.com>, size=630, nrcpt=1 (queue active) Mar 18 10:19:08 li833-84 sendmail[4561]: t2IEJ7jn004561: to=sales@example.com, ctladdr=root (0/0), delay=00:00:01, xdelay=00:00:00, mailer=relay$ Mar 18 10:19:08 li833-84 postfix/smtpd[4562]: disconnect from localhost.localdomain[127.0.0.1] Mar 18 10:19:08 li833-84 postfix/pipe[4570]: 73A35BE52: to=<sales@example.com>, relay=dovecot, delay=0.07, delays=0.05/0.01/0/0.01, dsn=2.0.0, s$ Mar 18 10:19:08 li833-84 postfix/qmgr[4510]: 73A35BE52: removed
Check the Dovecot delivery log located in
/home/vmail/dovecot-deliver.log
. The contents should look similar to the following:- /home/vmail/dovecot-deliver.log
-
1
deliver(<sales@example.com>): 2011-01-21 20:03:19 Info: msgid=<<20110121200319.E1D148908@hostname.example.com>>: saved mail to INBOX
Now test to see what the users of your email server would see with their email clients.
Test the Mailbox
To test the
sales@example.com
mailbox, navigate to the mailbox directory/home/vmail/example.com/sales/Maildir
and issue the following command:cd /home/vmail/example.com/sales/Maildir find
You should see output similar to the following:
. ./dovecot-uidlist ./cur ./new ./new/1285609582.P6115Q0M368794.li172-137 ./dovecot.index ./dovecot.index.log ./tmp
Test the mailbox by using a mail client. For this test, using mutt is recommended. If it is not installed by default, install it with
yum install mutt
, then run:mutt -f .
You may be prompted to create the root mailbox. This is not required.
If there is an email in the inbox, Postfix, Dovecot, and MySQL have been successfully configured! To quit mutt press
q
.
More Information
You may wish to consult the following resources for additional information on this topic. While these are provided in the hope that they will be useful, please note that we cannot vouch for the accuracy or timeliness of externally hosted materials.
- ISP-style Email Server with Debian-Lenny and Postfix 2.5 guide
- Groupware Server With Group-Office, Postfix, Dovecot And SpamAssassin On Debian Lenny (5.0)
- Postfix MySQL Howto
- Postfix SASL Howto
- Dovecot Documentation Wiki
- MySQL Documentation
Join our Community
Find answers, ask questions, and help others.
This guide is published under a CC BY-ND 4.0 license.