Wednesday, July 14, 2010

Setting up an perfect email server in CentOS

SkyHi @ Wednesday, July 14, 2010

Setting up an email server in CentOS

From (mt) Wiki

WARNING: This page is a work in progress. The steps here should work, but they have not been extensively tested.




I am working on setting up a functional email server on my (ve) using CentOS. The online documentation for this seems to be rather scattered, so I am going to document my work here. I am not an expert at email server configuration, so please do not take anything here as gospel. There are references to more authoritative sources at the bottom of this page.

There are many different tools that you can use for this job on Linux. I am going to be using Postfix as the MTA and Dovecot as the IMAP/POP server to let users retrieve their email. Postfix and Dovecot are both standard components of CentOS/RedHat Linux, which means that they are easily available in the CentOS software repositories, and they will be well-supported with long term security updates. Additionally, the two integrate well with each other, so I will let Dovecot handle the authentication for Postfix SMTP AUTH and also have Dovecot's LDA (local delivery agent) take over responsibility from Postfix's MDA component. The Dovecot LDA offers some extra functionality, such as enforcing disk space quotas, and has a reputation for being very efficient.

The simplest way to set up an email server is to have all the email users be UNIX user accounts (appearing in /etc/passwd) with a Maildir folder in their home directory. However, if you're hosting multiple domains and many email addresses on your server, that setup can quickly become unwieldy. For this reason, I am going to configure the server with "virtual" domains and "virtual" users. These will be specified in a MySQL database, which should be easier to maintain. To further ease administration, I'll be installing a PHP frontend, Postfixadmin which helps you to manage the database, as well as letting users change their own email passwords and some other nice perks.




Install Postfix and Dovecot

postfix - Postfix is a Mail Transport Agent (MTA), supporting LDAP, SMTP AUTH (SASL), TLS

dovecot - Dovecot is an IMAP server for Linux/UNIX-like systems, written with security primarily in mind. It also contains a small POP3 server. It supports mail in either of maildir or mbox formats.

For some reason, the default Postfix package in CentOS is not compiled with database support. There are many guides online that show you how to patch the source .rpm and recompile it, but I think an easier option is to get the version you need from the CentOS-plus repository. Here's how:

Open the yum repository file for the basic CentOS packages:

# vim /etc/yum.repos.d/CentOS-Base.repo

and add the line exclude=postfix to the end of the [base] and [updates] section.

name=CentOS-$releasever - Base

#released updates
name=CentOS-$releasever - Updates

Then, go to the [centosplus] section and enable it:


and add includepkgs=postfix

name=CentOS-$releasever - Plus

These changes ensure that yum will install the version of Postfix from centosplus, instead of from the base

Save that file, and then do:

# yum install postfix dovecot

If you have correctly excluded the standard Postfix version, you should get the package: postfix.x86_64 2:2.3.3-2.1.centos.mysql_pgsql

You can verify that your Postfix has the capabilities we need by entering:

# postconf -m

and making sure that the output includes "mysql".

You can also check that Postfix supports authentication through Dovecot by entering:

postconf -a

and verifying that 'dovecot' is one of the options.

(Optional) Upgrade Dovecot

If you want to enforce disk space quotas for your email users, you may want to upgrade Dovecot. The version 1.0.7 that comes from the CentOS 5.5 repository includes a minor, but irritating bug when storing quota values in a MySQL database. You can download the source for the newest version of Dovecot here, but if you'd rather not compile it, it's also possible to get a newer version of Dovecot compiled for RHEL/CentOS 5 from the ATrpms repository.

You can upgrade to Dovecot 1.2.11 with this command: # rpm -Uvh

Install Apache/PHP/MySQL

If you're running a web server on your (ve), you may already have some or all of these packages installed. The php-mbstring and php-imap packages are required for functionality in postfix admin.

# yum install httpd mysql-server php php-mbstring php-imap php-mysql

Configure MySQL

Initial setup

If you are installing the MySQL server for the first time, you will want to enter

# service mysqld start

to start the server, and then run

# /usr/bin/mysql_secure_installation

to set the MySQL root user password, remove sample data, and some other steps to secure the MySQL server.

For added security, you might want to edit /etc/my.cnf and add:


which will tell the MySQL daemon to only accept connections from the local host.

Enter # /etc/init.d/mysqld restart to restart MySQL and pick up the configuration changes.

If you want mysqld to start automatically when your (ve) boots, enter:

# chkconfig mysqld on

Setup for mail database

Once you have a running MySQL server, you need to create a database to hold your email configuration, and a database user that Postfix and Dovecot can use to access it.

Log into the MySQL shell as the MySQL root user: # mysql -u root -p

Create a database called 'mail' (or whatever name you choose): mysql> CREATE DATABASE mail;

Create a database user named 'mail_admin' and grant it SELECT, INSERT, UPDATE and DELETE privileges on the mail database. Be sure to replace in the commands below with whatever password you want for that user.

mysql> GRANT ALL ON mail.* TO 'mail_admin'@'localhost' IDENTIFIED BY '';

Setup Postfix Admin

Download files and configure Apache

Download Postfixadmin from the project site:

Watch out for the version numbers in the next few commands, in case postfixadmin has been updated since I wrote this.

# wget

You can install it anywhere you want. I think this is a reasonable place:

# tar xzf postfixadmin_2.3.tar.gz
# mv postfixadmin-2.3/ /usr/share/postfixadmin

Then, configure Apache to know where to find it by opening a file in the conf.d directory: # vim /etc/httpd/conf.d/postfixadmin.conf

And inserting the following lines:

# Web application to manage Postfix email server

Order Allow,Deny
Allow from all

Alias /postfixadmin /usr/share/postfixadmin
Alias /PostFixAdmin /usr/share/postfixadmin
Alias /PostfixAdmin /usr/share/postfixadmin

Then, restart Apache to make sure the configuration is active: # service httpd restart

By adding this section to the Apache configuration, you should be able to reach Postfix Admin from any domain on your server by going to

Configure Postfix Admin

If you go to you should see a Postfix Admin welcome page, with links to some documentation, including the INSTALL.TXT. It's worth reading, but I'll summarize what I did here.

Open the config file for editing:

# vim /usr/share/postfixadmin/

Change $CONF['configured'] = false; to

$CONF['configured'] = true;

Fill out the database configuration section:

// Database Config
// mysql = MySQL 3.23 and 4.0, 4.1 or 5
// mysqli = MySQL 4.1+
// pgsql = PostgreSQL
$CONF['database_type'] = 'mysqli';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'mail_admin';
$CONF['database_password'] = '';
$CONF['database_name'] = 'mail';
$CONF['database_prefix'] = '';

If you're using CentOS 5.5 that comes on the (ve), you should have MySQL version 5, so you'll want to set the database type to 'mysqli' for better performance.

You can set the address that welcome emails come from: $CONF['admin_email'] = '';

I set up Postfixadmin to use Dovecot to encrypt the email passwords using the CRAM-MD5 scheme. This will allow you to offer CRAM-MD5 authentication, which is more secure in some situations. $CONF['encrypt'] = 'dovecot:CRAM-MD5';

There are some other settings in that are worth taking a look at, but they mostly seem to be personal preferences about the way you'd like Postfix Admin to look and behave.

One section I modified had to do with mailbox locations. This is a preference, but it will affect the structure of the MySQL queries we'll set up Postfix to do in the next section. I'm going to keep my mailboxes at /var/mail/vhosts/ and these settings reflect that.

// Mailboxes
// If you want to store the mailboxes per domain set this to 'YES'.
// Examples:
// YES: /usr/local/virtual/domain.tld/username@domain.tld
// NO: /usr/local/virtual/username@domain.tld
$CONF['domain_path'] = 'YES';
// If you don't want to have the domain in your mailbox set this to 'NO'.
// Examples:
// YES: /usr/local/virtual/domain.tld/username@domain.tld
// NO: /usr/local/virtual/domain.tld/username
// Note: If $CONF['domain_path'] is set to NO, this setting will be forced to YES.
$CONF['domain_in_mailbox'] = 'NO';

I also adjusted these settings which set the default limits for a domain. By default, when you create a domain, the domain administrator will be restricted to these limits. The best values for you are going to depend on how many domains you want to host email for, and how much disk space you have available. Note that 'maxquota' is specified in MB and only enforced if you enable quota support.

$CONF['aliases'] = '100';
$CONF['mailboxes'] = '100';
$CONF['maxquota'] = '100';

Postfix Admin has support for reading mail directly in the web interface using a retrieval script called Fetchmail. I haven't installed Fetchmail, and there are other, better, webmail options out there, so I don't have any need for this feature. This setting just hides that tab.

$CONF['fetchmail'] = 'NO';

The following parameters have to do with disk space quotas. If you aren't enforcing quotas, you can skip them.

Enforce quotas: $CONF['quota'] = 'YES';

Display the amount of quota used up in the Postfix Admin interface: $CONF['used_quotas'] = 'YES';

If you took my advice above and upgraded to Dovecot 1.2.X, you will need to use the newer style of quota table: $CONF['new_quota_table'] = 'YES';

Install Postfix Admin

Save that file, and then go to

It will run some tests to verify that requirements are met. In my case, I had to go back and install some PHP packages, but you should already have those installed from the instructions above.

Now Postfix Admin will create the database schema that Postfix and Dovecot are going to read.

Next, it prompts you to enter a 'setup password'. You enter a password twice, and it will give you a hash (a long string of gibberish) to enter in /usr/shared/postfixadmin/

Find this line,

$CONF['setup_password'] = 'changeme'

and replace 'changeme' with the hashed password. I believe this measure prevents anyone else from re-installing Postfix Admin and wiping out your configuration. You could open up the Apache configuration now.

Finally, it will ask you to create a super-administrator account. I named mine, but you can name it whatever you want. The name does have to be in the format of an email address, even though it's not an account that receives mail.

Configure Postfix

Basic configuration

Postfix keeps most of its configuration settings in the file /etc/postfix/

You can find more details in the Postfix Basic Configuration README.

Uncomment and modify the following lines to reflect the details of your server:
#myhostname = host.domain.tld
#mydomain = domain.tld

I set mine both to be the same thing, the primary domain/hostname of my (ve). But you could probably do:
myhostname =
mydomain =

Uncomment this line, but you can probably leave it set to $mydomain
myorigin = $mydomain

According to the Postfix documentation, this setting specifies, "the domain name that locally-posted mail appears to come from, and that locally posted mail is delivered to"

Set Postfix to listen on all interfaces:
inet_interfaces = all

I changed the line:
mydestination = $myhostname, localhost.$mydomain, localhost

To to be:
mydestination = localhost

Because I intend to manage everything as virtual domains and virtual users.

You probably also want to uncomment this line, mynetworks_style = host

This will make postfix consider only the localhost part of the trusted "mynetwork". By default, it considers all other machines on the same subnet as part of your network, but that's probably not the setup you want if your server is in a data center with many other servers belonging to different customers.

Virtual Domains Setup

For more details, see Postfix Virtual Domain Hosting Howto. There is also good information in the Postfix Admin documentation at /usr/share/postfixadmin/DOCUMENTS/POSTFIX_CONF.txt (assuming you installed to the same path as I did above)

I created a 'vmail' user account that will have ownership of all the mail folders. I believe that strictly speaking you could have those folders belong to the postfix or dovecot user, but this way is perhaps a bit cleaner.

# useradd -u 5000 -d /var/mail/vhosts/ -m -s /sbin/nologin vmail

This sets the home directory for the vmail user to be /var/mail/vhosts/ and this is where I will be keeping my mail folders. I prefer that location because of the parallel with Apache's /var/www/vhosts/ folder, for its own virtual hosted domains. Obviously, you can keep your mail wherever you like.

In order for Postfix to communicate with with the MySQL database, you have to create several special files that contain database queries to return the information about your email users. First, we need to tell Postfix to look for those files. Open to edit again, # vim /etc/postfix/

Look for the section that deals with virtual domains, and make it look like this:

# The VIRTUAL_README document gives information about the many forms
# of domain hosting that Postfix supports.
# See:
# The follwing lines connect Postfix with the MySQL database that contains information about
# the virtual users/accounts hosted. See proxymap(8) virtual(5) and mysql_table(5)
virtual_mailbox_domains = proxy:mysql:/etc/postfix/
virtual_alias_maps = proxy:mysql:/etc/postfix/
virtual_mailbox_maps = proxy:mysql:/etc/postfix/
# Additional for quota support
virtual_create_maildirsize = yes
virtual_mailbox_extended = yes
virtual_mailbox_limit_maps = mysql:/etc/postfix/
virtual_mailbox_limit_override = yes
virtual_maildir_limit_message = Sorry, this user has exceeded their disk space quota, please try again later.
virtual_overquota_bounce = yes
#Specify the user/group that owns the mail folders. I'm not sure if this is strictly necessary when using Dovecot's LDA.
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
#Specifies which tables proxymap can read:
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

We've told Postfix to find information about the virtual addresses by making MySQL queries specified in the files named above (, etc.) but we need to create those files to tell it what queries to make.

Create the first file, # vim /etc/postfix/

And insert these lines:

user = mail_admin
password =
hosts = localhost
dbname = mail
query = SELECT domain FROM domain WHERE domain='%s' AND active = '1'
#optional query to use when relaying for backup MX
#query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '0' AND active = '1'

Create the next file, # vim /etc/postfix/

user = mail_admin
password =
hosts = localhost
dbname = mail
query = SELECT goto FROM alias WHERE address='%s' AND active = '1'

Create the third file, # vim /etc/postfix/

user = mail_admin
password =
hosts = localhost
dbname = mail
query = SELECT CONCAT(domain,'/',maildir) FROM mailbox WHERE username='%s' AND active = 1

If you included support for email quotas, create this file, # vim /etc/postfix/

user = mail_admin
password =
hosts = localhost
dbname = mail
query = SELECT quota FROM mailbox WHERE username='%s' AND active = '1'

SMTP AUTH settings

Add the following section:

# The following options set parameters needed by Postfix to enable
# SMTP AUTH support using Dovecot's SASL component for authentication of mail clients.
# See: /usr/share/doc/postfix-2.3.3/README_FILES/SASL_README -
# And /usr/share/doc/dovecot-1.0.7/wiki/HowTo.PostfixAndDovecotSASL.txt -
# Turns on sasl authorization
smtpd_sasl_auth_enable = yes
#Use dovecot for authentication
smtpd_sasl_type = dovecot
# Path to UNIX socket for SASL
smtpd_sasl_path = /var/run/dovecot/auth-client
#Disable anonymous login. We don't want to run an open relay for spammers.
smtpd_sasl_security_options = noanonymous
#Adds support for email software that doesn't follow RFC 4954.
#This includes most versions of Microsoft Outlook before 2007.
broken_sasl_auth_clients = yes
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination

Set Postfix to use Dovecot's LDA for delivery

A Local Delivery Agent (LDA) is the program that finally places the messages in a user's inbox. Postfix has its own component that can do this, but using Dovecot's LDA has some advantages. It offers some extra features such as quota enforcement, and autoresponders. Furthermore, it does indexing-on-delivery that reportedly makes it faster to access email with IMAP.

You'll need to add the following two lines to /etc/postfix/

virtual_transport = dovecot
dovecot_destination_recipient_limit = 1

As you can see, I put them in the TRANSPORT MAP section, but they can really go wherever.

Next, you'll have to edit Postfix's other important configuration file (I did say most of the settings were in # vim /etc/postfix/

Add these lines to the end of the file, in the "Interfaces to non-Postfix software" section:

# Dovecot LDA, as explained here:
dovecot unix - n n - - pipe flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}

(Optional) Enable port 587

If you would like your email server to also be able to accept SMTP connections on port 587 (some ISPs block the default port 25), then edit and uncomment this line:

#submission inet n       -       n       -       -       smtpd

Configure Dovecot

So far, we've set up Postfix to ask certain things of Dovecot: SASL authentication and mail delivery. However, the other side of that equation is we have to configure Dovecot to be willing to provide those services for Postfix.

For more details, there's a good readme included with Postfix Admin; you can find it at /usr/share/postfixadmin/DOCUMENTS/DOVECOT.TXT

Dovecot's main configuration file can be found at /etc/dovecot.conf

Note: When editing the Dovecot configuration, you may notice that the files are formatted a bit differently than the Postfix files. Dovecot is a newer piece of software and keeps its configuration options grouped together in stanzas, marked with curly braces {e.g. these things} —this is great for organization, but it means you have to be a bit more careful when editing. Watch out that you're un/commenting the closing brace, too. Otherwise, you'll learn like I did when Dovecot complains about all kinds of syntax errors. Vim and other modern text editors will probably give you some color highlighting that can make this easier.

Basic Settings

# vim /etc/dovecot.conf

I uncommented these two lines, to remind myself that they're things I (and perhaps you) might care about in the future, but I didn't change their defaults:

# Protocols we want to be serving: imap imaps pop3 pop3s
# If you only want to use dovecot-auth, you can set this to "none".
protocols = imap imaps pop3 pop3s
# Disable LOGIN command and all other plaintext authentications unless
# SSL/TLS is used (LOGINDISABLED capability). Note that if the remote IP
# matches the local IP (ie. you're connecting from the same computer), the
# connection is considered secure and plaintext authentication is allowed.
disable_plaintext_auth = no

Pay attention to the double-negative here. By leaving the setting at 'no' you're not-disabling (i.e. enabling) plaintext authentication. This shouldn't be a security risk for your server, but it could potentially be for your users, if they were connecting from a hostile network.

Set the mail_location variable, which specifies where Dovecot should look for email. The %h will be replaced with the 'home' directory as specified in the MySQL database, and that already includes the trailing slash. So the mail location for a user will look like /var/mail/vhosts/

mail_location = maildir:%hMaildir


The namespace feature of Dovecot lets you manually specify some parameters to help IMAP clients find the Inbox and other folders. It's probably a good idea to include this information, given that email software seems to do a pretty mediocre job supporting IMAP. Apple Mail in particular does a poor job with IMAP path prefixes when left to its own devices.

These settings are based on this guide, and should be backward-compatible with Courier-IMAP which is another very popular IMAP server in use today.

namespace private {
# Hierarchy separator to use. You should use the same separator for all
# namespaces or some clients get confused. '/' is usually a good one.
# The default however depends on the underlying mail storage format.
separator = .

# Prefix required to access this namespace. This needs to be different for
# all namespaces. For example "Public/".
prefix = INBOX.

# Physical location of the mailbox. This is in same format as
# mail_location, which is also the default for it.
#location =

# There can be only one INBOX, and this setting defines which namespace
# has it.
inbox = yes

# If namespace is hidden, it's not advertised to clients via NAMESPACE
# extension or shown in LIST replies. This is mostly useful when converting
# from another server with different namespaces which you want to depricate
# but still keep working. For example you can create hidden namespaces with
# prefixes "~/mail/", "~%u/mail/" and "mail/".
#hidden = yes

Protocol-specific settings


If you want quota support, find the stanza that begins with protocol imap { and set this line:

mail_plugins = quota imap_quota


Find the stanza that begins with protocol pop3 { and uncomment this line:

pop3_uidl_format = %08Xu%08Xv

This will be the default in future versions of Dovecot, and makes some clients, such as Outlook 2003 work better with POP3.

If you want support for disk space quotas, also set this line:

mail_plugins = quota


The stanza beginning with protocol lda { sets parameters relevant for Dovecot's LDA that will be delivering the messages. Here's what mine looks like, note that you may want to change the postmaster address and the hostname to suit your own preferences, and again, if you want quota enforcement, add the quota plugin.

protocol lda {
# Address to use when sending rejection mails.
postmaster_address =

# Hostname to use in various parts of sent mails, eg. in Message-Id.
# Default is the system's real hostname.
#hostname =

# Support for dynamically loadable plugins. mail_plugins is a space separated
# list of plugins to load.
mail_plugins = quota
#mail_plugin_dir = /usr/lib/dovecot/lda

# Binary to use for sending mails.
#sendmail_path = /usr/lib/sendmail

# UNIX socket path to master authentication server to find users.
#auth_socket_path = /var/run/dovecot/auth-master



Find the stanza that starts with auth default {

Edit the line: mechanisms = plain

You will probably at least want to add "login", which is a different style of plaintext authentication used by some email programs, including certain versions of Outlook. I also added support for CRAM-MD5, which is not really necessary, but supported by some email programs (for instance, if you check "use secure authentication" in Thunderbird)

mechanisms = plain login cram-md5

Note: If you set up your server and email software to use TLS/SSL, as explained later in this guide, then it doesn't really matter which authentication mechanism you use. The entire session will be encrypted by TLS, so even plaintext authentication will be protected. The only time CRAM-MD5 would really matter is if you needed to authenticate securely in a non-TLS session. For details, see here.

Next, we need to tell Dovecot where it's going to look to check those passwords.


Find the the stanza passdb pam { and comment it out:

# passdb pam { (Don't forget the closing bracket!)

PAM stands for "pluggable authentication modules," which is a commonly-used authentication standard on Linux/UNIX systems. I think theoretically, it would be possible to set Dovecot to ask PAM, and then have PAM query our MySQL database for the users/passwords. However, that's a more complex setup, and I'm not sure what advantages you would gain.

Find the stanza passdb sql { and un-comment it to make it active.

To tell it where to find the database information, set the line:

args = /etc/dovecot-sql.conf

Then, un-comment the stanza, userdb prefetch { to make it active.

Further down, comment out the stanza userdb passwd { to disable it.

Then, after the userdb prefetch stanza, set the userdb sql stanza:

# SQL database 
userdb sql {
# Path for SQL configuration file, see doc/dovecot-sql-example.conf
args = /etc/dovecot-sql.conf

There may already be a commented-out userdb sql stanza before the userdb prefetch. You can leave it there, or delete it to not confuse yourself later. This may seem silly, but the order matters.

Here's what's going on: The passdb and userdb settings tell Dovecot where to check to verify passwords and look up other user information, respectively. In our case, that information all stored in the same place--the 'mailbox' table in our MySQL database. So, rather than having Dovecot make two separate MySQL queries any time a user connects with POP or IMAP, you can have it 'prefetch' the user's information at the same time it validates the password. That's what the 'prefetch' is about. However, because we want Dovecot's LDA to be responsible for delivering mail to user's folders, it has to have a way of looking up that user information even when there isn't anyone logging in with a password to validate. That's why we still need the 'userdb sql' stanza AFTER the prefetch stanza. For all the details about prefetching, you can refer to the Dovecot wiki'

Set the user account that's Dovecot's authentication process will run as. I'm using the 'vmail' user we created earlier.

# User to use for the process. This user needs access to only user and
# password databases, nothing else. Only shadow and pam authentication
# requires roots, so use something else if possible. Note that passwd
# authentication with BSDs internally accesses shadow files, which also
# requires roots. Note that this user is NOT used to access mails.
# That user is specified by userdb above.
#user = root
user = vmail


The are two different UNIX sockets that dovecot-auth will listen for authentication requests on, one 'master' used by Dovecot itself, and a 'client' socket used by other software that wants to use Dovecot for authentication--in our case, this is Postfix.

Here's what my version of this looks like. Watch out for all the nested brackets here.

This works just fine in the default CentOS install. If you're running Postfix 'chrooted' for security reasons (on some other distributions this is the default setting) you would need to change the location of the client socket to put it within Postfix's chroot directory.

  # It's possible to export the authentication interface to other programs:
socket listen {
master {
# Master socket provides access to userdb information. It's typically
# used to give Dovecot's local delivery agent access to userdb so it
# can find mailbox locations.
path = /var/run/dovecot/auth-master
mode = 0600
# Default user/group is the one who started dovecot-auth (root)
user = vmail
#group =
client {
# The client socket is generally safe to export to everyone. Typical use
# is to export it to your SMTP server so it can do SMTP AUTH lookups
# using it.
path = /var/run/dovecot/auth-client
mode = 0660
user = postfix
group = postfix

Database connections

As with Postfix, we need to create another file containing the database settings. There's a sample of this file in the documentation that comes with Dovecot, so you can copy that to the /etc/ folder.

# cp /usr/share/doc/dovecot-`dovecot --version`/examples/dovecot-sql-example.conf /etc/dovecot-sql.conf

Now, you need to edit that file and configure the database settings for Dovecot.

# vim /etc/dovecot-sql.conf

Specify that this is a MySQL database: driver = mysql

Provide the credentials to access the database: connect = host=localhost dbname=mail user=mail_admin password=YOUR_PASSWORD

Because we told Postfix Admin to store the passwords encrypted with cram-md5, you should set: default_pass_scheme = CRAM-MD5

Your exact settings for the next lines are going to depend on the choices you made earlier about where to store the mail, and the user account to own the mail.

My user query line is: user_query = SELECT CONCAT('/var/mail/vhosts/', maildir) AS home, 5000 AS uid, 5000 AS gid, CONCAT('*:bytes=', quota) as quota_rule FROM mailbox WHERE username = '%u' AND active='1'

If you're not using quotas, yours could look like: user_query = SELECT CONCAT('/var/mail/vhosts/', maildir) AS home, 5000 AS uid, 5000 AS gid FROM mailbox WHERE username = '%u' AND active='1'

My password_query line is: password_query = SELECT username AS user, password, CONCAT('/var/mail/vhosts/', maildir) AS userdb_home, 5000 AS userdb_uid, 5000 AS userdb_gid, CONCAT('*:bytes=', quota) as userdb_quota_rule FROM mailbox WHERE username = '%u' AND active='1'

Again, if you don't care about quotas, password_query = SELECT username AS user, password, CONCAT('/var/mail/vhosts/', maildir) AS userdb_home, 5000 AS userdb_uid, 5000 AS userdb_gid FROM mailbox WHERE username = '%u' AND active='1'

Note that the password_query line actually returns all the same information included in the user_query as fields prefixed with userdb_--this is how the prefetch system works.

(Optional) Quota Table

So far you've told Dovecot how to check what the quota limits are supposed to be for a given user. Now, you also need to tell it where to keep information about how much mail the user already has.

Edit dovecot.conf # vim /etc/dovecot.conf

Find the dict { stanza, and set it

dict {
quotadict = mysql:/etc/dovecot-dict-quota.conf

Next, find the plugin { stanza and you can add these lines:

# Quota setting per /usr/share/postfixadmin/DOCUMENTS/DOVECOT.txt
quota = dict:user::proxy::quotadict

Save dovecot.conf, and then open the file: # vim /etc/dovecot-dict-quota.conf

And enter this:

connect = host=localhost dbname=mail user=mail_admin password=
map {
pattern = priv/quota/storage
table = quota2
username_field = username
value_field = bytes
map {
pattern = priv/quota/messages
table = quota2
username_field = username
value_field = messages

The preceding assumes that you've upgraded to Dovecot 1.2.X as I recommended at the start. Earlier versions of Dovecot have a different format for this file. You can find detailed information here.

Start and Test


Now for the moment of truth, you should be ready to start up your email server.

Start up Dovecot:

# service dovecot start

If you get errors like this, "Starting Dovecot Imap: Error: Error in configuration file /etc/dovecot.conf line 1109: Unknown setting" it's likely that you forgot to comment or uncomment all the curly brackets properly.

Next, start Postfix: # service postfix start

You'll probably want both of these components to start any time your server boots up, so you can use chkconfig to set that up:

# chkconfig dovecot on
# chkconfig postfix on

Assuming you don't get any error messages when you first start these programs, you may still want to check the mail logs to make sure there's no major warnings or errors recorded there.

# tail /var/log/maillog

A successful startup will probably look similar to this:

Jun 22 23:39:52 ve dovecot: Dovecot v1.2.11 starting up (core dumps disabled)
Jun 22 23:39:52 ve dovecot: Generating Diffie-Hellman parameters for the first time. This may take a while..
Jun 22 23:40:17 ve dovecot: auth-worker(default): mysql: Connected to localhost (mail)
Jun 22 23:40:17 ve dovecot: dict: mysql: Connected to localhost (mail)
Jun 22 23:40:48 ve postfix/postfix-script: starting the Postfix mail system
Jun 22 23:40:48 ve postfix/master[10208]: daemon started -- version 2.3.3, configuration /etc/postfix

Testing with telnet

Before you start setting up email accounts and testing with email clients, it's a good idea to make sure the daemons are at least listening correctly. Telnet is a good way to test this. To test SMTP, you can enter:

# telnet localhost 25

You should get a reply like:

Connected to localhost.
Escape character is '^]'.
220 ESMTP Postfix

Next, if you enter: EHLO

You will get a listing of the features your Postfix server is offering:
250-SIZE 10240000
250 DSN

Especially make sure your output includes the line that reads "250-AUTH PLAIN LOGIN DIGEST-MD5 CRAM-MD5" because this means that Postfix is advertising it can understand SMTP AUTH, which requires it to authenticate against Dovecot.

You can type "quit" to close the SMTP session.

You can test that Dovecot is listening for POP connections with: # telnet localhost 110

Which should give output like:

Connected to localhost.
Escape character is '^]'.
+OK Dovecot ready.

And to check IMAP connectivity, enter: # telnet localhost 143

A successful result will include Dovecot advertising its IMAP capabilities:

Connected to localhost.
Escape character is '^]'.

TLS (SSL) Encryption

TLS is the successor to SSL. Confusingly, the two terms are used somewhat interchangeably in many contexts. Most of the information in this section is from the CentOS wiki.

In order to enable TLS encryption, you will need an SSL certificate/key pair. There are several commercial vendors you can buy them from, and also some free non-profit sources. However, I'm going to be generating my own self-signed certificate. If you're using a commercial certificate, you may also need to install their root CA certificate, and so your steps for this section would vary slightly.

There are other ways to generate an SSL certificate, but there's a nice RedHat utility included as part of the crypto-utils package that helps automate the process. Install it: # yum install crypto-utils

Then, run the genkey tool and follow the relevant prompts to fill in details for your server: # genkey --days 365

When asked, Would you like to send a Certificate Request (CSR) to a Certificate Authority (CA)? select "No" unless you are going to be ordering a certificate from a 3rd party. Do not check the box for Encrypt the private key. While Dovecot does support encrypted, password-protected keys, Postfix does not, as of version 2.3.

The certificate and key, respectively will be saved to:



Next, tell Postfix to use your certificate and key: # vim /etc/postfix/

Add the following section:

#See CentOS wiki at

#Enables, but does not require use of TLS
smtpd_tls_security_level = may
#Location of private key
smtpd_tls_key_file = /etc/pki/tls/private/
#Public certificate
smtpd_tls_cert_file = /etc/pki/tls/certs/
#Certificate atuhority certificate, if you need this for a commercial certificate.
# smtpd_tls_CAfile = /etc/pki/tls/root.crt
#Log TLS sessions
smtpd_tls_loglevel = 1
#Cache TLS sessions for 1 hour to reduce CPU load
smtpd_tls_session_cache_timeout = 3600s
#Location to store cache
smtpd_tls_session_cache_database = btree:/var/spool/postfix/smtpd_tls_cache
#Raondom data source
tls_random_source = dev:/dev/urandom
#Require TLS security before allowing plaintext authentication
#smtpd_tls_auth_only = no

Save that file, and open Dovecot's configuration for editing: # vim /etc/dovecot.conf

Set the paths for the certificate and key:

ssl_cert_file = /etc/pki/tls/certs/
ssl_key_file = /etc/pki/tls/private/

If necessary, you can set the CA root certificate as well, #ssl_ca_file =

Uncomment this line to disable some weak ciphers: ssl_cipher_list = ALL:!LOW:!SSLv2

After you're done with the configuration, restart Dovecot and Postfix to make it active:

# service dovecot restart
# service postfix restart


ISP-style Email Server with Debian-Etch - This page is slightly outdated, and written for Debian, but it's the most accessible and broadly informative article I've found. If you're just starting out, and you want to actually understand what you're doing before blindly entering commands, I would begin here.

Mail server with Postfix and Dovecot - From the Gentoo wiki, but uses all the same components covered in this guide. Well-written and through.

Postfix Official Documentation - Comprehensive, but could be better organized and more accessible.

The Dovecot Wiki - Dovecot has a great deal of excellent, well-written documentation on its wiki.

CentOS Wiki - Contains several useful guides related to email. They are mostly geared toward a more basic setup than the one outlined in this guide.

CentOS Postfix-Dovecot Howto - Blog post covering a very similar setup to the one I've outlined. Considerably more terse than this guide; you might look here if you're already an expert or would like some other examples of the configuration files.