Translations of this page:

Postfix+Dovecot tutorial

This tutorial is for mbox mailboxes which is default on centos. You could use Maildir - there are plenty of tutorials how to do that.


Add admin user

Add your first user and set system mail to go to it:

useradd johnsmith

then add this to /etc/aliases:

root: johnsmith

and run newaliases

This will make all the mail generated by the OS go to this user.


In postfix configuration long lines can be split to multiple lines as long as you put leading blank space on the next line.

First you need to remove sendmail and install postfix:

yum erase sendmail
yum install postfix

This will make /usr/sbin/sendmail work as if sendmail was installed. Technically it makes symlink to /usr/sbin/sendmail.postfix which can be used in the same way as sendmail

alternatives --set mta /usr/sbin/sendmail.postfix


master.cf describes protocols and ports. You can also define milters or other options here

# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================
smtp      inet  n       -       n       -       80      smtpd

submission inet n       -       n       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
#  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING

smtps     inet  n       -       n       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_reject_unlisted_recipient=no
#  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING

#the next lines were there in default centos installation, so I leave them there:
#628       inet  n       -       n       -       -       qmqpd
pickup    unix  n       -       n       60      1       pickup
cleanup   unix  n       -       n       -       0       cleanup
qmgr      unix  n       -       n       300     1       qmgr
#qmgr     unix  n       -       n       300     1       oqmgr
tlsmgr    unix  -       -       n       1000?   1       tlsmgr
rewrite   unix  -       -       n       -       -       trivial-rewrite
bounce    unix  -       -       n       -       0       bounce
defer     unix  -       -       n       -       0       bounce
trace     unix  -       -       n       -       0       bounce
verify    unix  -       -       n       -       1       verify
flush     unix  n       -       n       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       n       -       -       smtp
relay     unix  -       -       n       -       -       smtp
#       -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq     unix  n       -       n       -       -       showq
error     unix  -       -       n       -       -       error
retry     unix  -       -       n       -       -       error
discard   unix  -       -       n       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       n       -       -       lmtp
anvil     unix  -       -       n       -       1       anvil
scache    unix  -       -       n       -       1       scache


#queue_directory         =       /var/spool/postfix
#command_directory       =       /usr/sbin

#daemon_directory       =       /usr/libexec/postfix
#mail_owner             =       postfix

myhostname = mail.example.com
mydomain = example.com
myorigin = $mydomain
#mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
mydestination = $myhostname
mynetworks =,
inet_interfaces = all
#inet_protocols = all
inet_protocols = ipv4
relay_domains =
#home_mailbox = mail

virtual_alias_domains   =       /etc/postfix/local-host-names
virtual_alias_maps      =       hash:/etc/postfix/virtusertable, hash:/etc/postfix/aliases, hash:/etc/postfix/virtual
canonical_maps          =       hash:/etc/postfix/canonical

# NIS overrice
alias_maps              =

mailbox_command         =       /usr/bin/procmail

smtpd_helo_required     =       yes
disable_vrfy_command    =       yes

#inet_interfaces         =,,

mynetworks              =,
  • queue_directory, command_directory, daemon_directory, mail_owner - if you use distro package you probably don't need to set these. Just leave defaults
  • myhostname - the hostname of the server. This should be your MX record - usually mail.example.com or smtp.example.com
  • mydomain - the main domain name - this is the domain after the @. Specify only the “main” domain. You can add multiple domains in “virtual_alias_domains”
  • mydestination - use $myhostname here. I've seen some tutorials suggest to also include localhost and the main domain here, but I had problems with it
  • mynetworks - tells postfix which networks to relay. Put local host or any local networks here. You can always set it to a file (ex. /etc/postfix/networks)
  • inet_interfaces - what interfaces to listen on
  • inet_protocols - if you don't want to enable ipv6 you can limit this to ipv4

Enable authentication

Add this to your /etc/postfix/main.cf file:

# enable SASL authentication
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_sasl_authenticated_header = yes
smtpd_recipient_restrictions =

and enable saslauthd service:

/bin/systemctl enable saslauthd.service
/bin/systemctl start saslauthd.service

Start postfix

If you have systemd-based OS:

systemctl enable postfix.service
systemctl start postfix.service

Configure SSL

First you need to create certificate.

edit /etc/pki/tls/openssl.cnf and change following parameters:

# expire after 20 years
default_days    = 7300

countryName_default             = BG
stateOrProvinceName_default    = Sofia Grad
localityName_default            = Sofia
0.organizationName_default      = Nicksoft Solutions Ltd
organizationalUnitName_default  = Mail Server

Then run:

cd /etc/pki/tls/certs
make postfix.pem DAYS=7300

To check the certificate run: openssl x509 -noout -in /etc/pki/tls/certs/postfix.pem -text

Add this to your main.cf file:

# TLS parameters
smtpd_tls_auth_only = yes
smtp_tls_security_level = may
smtpd_tls_security_level = may
smtpd_sasl_security_options = noanonymous, noplaintext
smtpd_sasl_tls_security_options = noanonymous

Then restart postfix:

/bin/systemctl restart postfix.service



Install dovecot

First you need to remove sendmail and install postfix:

yum install dovecot

Condigure dovecot

Edit /etc/dovecot/dovecot.conf and uncomment following lines:

protocols = imap pop3 lmtp
listen = *

Edit /etc/dovecot/conf.d/10-auth.conf and change the auth mechanisms:

auth_mechanisms = plain login

Edit /etc/dovecot/conf.d/10-mail.conf add/uncomment following line. On centos : mail_location = mbox:~/mail:INBOX=/var/spool/mail/%u

Edit /etc/dovecot/conf.d/10-master.conf and switch to postfix auth:

service auth {

  unix_listener auth-userdb {
    #mode = 0666
    #user =
    #group =

  # Postfix smtp-auth
  #unix_listener /var/spool/postfix/private/auth {
  #  mode = 0666

Edit /etc/dovecot/conf.d/20-pop3.conf and uncomment/add :

pop3_uidl_format = %08Xu%08Xv
pop3_client_workarounds = outlook-no-nuls oe-ns-eoh

Make sure that SSL is required. Edit 10-ssl.conf

ssl = required
ssl_cert = </etc/pki/dovecot/certs/dovecot.pem
ssl_key = </etc/pki/dovecot/private/dovecot.pem

Setup certificate

By default there should be a dovecot certificate installed in your OS:

openssl x509 -noout -in /etc/pki/dovecot/certs/dovecot.pem -text

However it's set to expire one year after dovecot install. If you are like me and you don't want to renew the certificate every year you could create a new one with longer validity period. To do that edit /etc/pki/dovecot/dovecot-openssl.cnf and enter your details in it - country, city … etc. You don't have to do that, but your mail client will ask you if you accept the mail certificate and it will show these details to you. However you should at least change CN to match your mail server's hostname or you will get a warning every time you open your mail. If you also change other things make sure to uncomment them first. Also you might want to change default_bits to at least 2048 to enhance security a bit (default is 1024). Example:

[ req ]
default_bits = 2048
encrypt_key = yes
distinguished_name = req_dn
x509_extensions = cert_type
prompt = no

[ req_dn ]
# country (2 letter code)

# State or Province Name (full name)
ST="Sofia Grad"

# Locality Name (eg. city)

# Organization (eg. company)
O="NickSoft Solutions"

# Organizational Unit Name (eg. section)
OU="IMAP server"

# Common Name (*.example.com is also possible)

# E-mail contact

[ cert_type ]
nsCertType = server

Technically you can run /usr/libexec/dovecot/mkcert.sh to create the key/certificate, but it'll force 365 days expiry. What I like to do is:

root@example dovecot# openssl req -new -x509 -nodes -config /etc/pki/dovecot/dovecot-openssl.cnf -out /etc/pki/dovecot/certs/dovecot.pem -keyout /etc/pki/dovecot/private/dovecot.pem -days 7300
Generating a 2048 bit RSA private key
writing new private key to '/etc/pki/dovecot/private/dovecot.pem'

root@example dovecot# openssl x509 -subject -fingerprint -noout -in /etc/pki/dovecot/certs/dovecot.pem
subject= /C=BG/ST=Sofia Grad/L=Sofia/O=NickSoft Solutions/OU=IMAP server/CN=mail.apptizer.net/emailAddress=postmaster@nicksoft.com
SHA1 Fingerprint=B6:92:A6:5C:4D:36:83:28:08:84:29:5F:82:E1:9F:B6:54:40:44:57

Where -days 7300 is 365 days/year * 20 years

Now check the certificate:

root@los dovecot# openssl x509 -noout -in /etc/pki/dovecot/certs/dovecot.pem -text
        Version: 3 (0x2)
        Serial Number:
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=BG, ST=Sofia Grad, L=Sofia, O=NickSoft Solutions, OU=IMAP server, CN=mail.apptizer.net/emailAddress=postmaster@nicksoft.com
            Not Before: Jan  1 11:10:45 2020 GMT
            Not After : Dec 27 11:10:45 2039 GMT
        Subject: C=BG, ST=Sofia Grad, L=Sofia, O=NickSoft Solutions, OU=IMAP server, CN=mail.apptizer.net/emailAddress=postmaster@nicksoft.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            Netscape Cert Type:
                SSL Server
    Signature Algorithm: sha256WithRSAEncryption

Start dovecot

/bin/systemctl enable dovecot.service /bin/systemctl start dovecot.service



Dovecot: Operation not permitted

The problem - you can't authenticate with dovecot and you see this in log:

Jan  1 13:25:08 los dovecot: imap(johnsmith): Error: fchown(/home/johnsmith/mail/.imap, group=12(mail))
 failed: Operation not permitted (egid=1007(johnsmith), group based on /var/spool/mail/johnsmith - see http://wiki2.dovecot.org/Errors/ChgrpNoPerm)

What's causing it is that dovecot tries to set the same user/group as your inbox file - /var/spool/mail/johnsmith which by default on centos has mode 660 and group mail. That's not ideal because other users on the same system can ready your mail in some cases.

So the solution is:

chmod 600 /var/spool/mail/*

The problem is that every time you create a new user it'll have these permissions. To avoid that you can edit /etc/default/useradd and comment this line:

lcb/mail/postfix-dovecot.txt · Last modified: 01.04.2020 18:23 by npelov
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki