Appbead Blog

How to Setup Mail Server on Debian 8 Jessie with Postfix + Dovecot (2)

We have just installed the necessary softwares of our mail server in previous article. Now, let's integrate them all together against this diagram.

The Listening Ports

According to the diagram, Postfix listen the port SMTP(25) and Submission(587), and Dovecot listen the port IMAPS(993).

Postfix

To configure the ports, edit the master.cf with your favorite editor:

$ sudo vi /etc/postfix/master.cf

Enable the service Submission by making the line 17 is NOT commented:

......
smtp      inet  n       -       -       -       -       smtpd
#smtp      inet  n       -       -       -       1       postscreen
......
submission inet n       -       -       -       -       smtpd
#  -o syslog_name=postfix/submission
......

The service SMTP is enabled by default.

Then edit the main.cf:

$ sudo vi /etc/postfix/main.cf
  • Find smtpd_tls_cert_file and insert definition of smtpd_tls_CAfile as below.
  • Specify our certificate files prepared in previous article.
  • Also replace smtpd_use_tls = yes with smtpd_tls_security_level = may.
  • Add smtp_tls_security_level = may (Thanks goes to @ajdunevent, Biganon and Dave):
smtpd_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
smtpd_tls_cert_file = /etc/ssl/certs/appbead.com.chain.crt
smtpd_tls_key_file = /etc/ssl/private/appbead.com.key
smtpd_tls_security_level = may
smtp_tls_security_level = may

Dovecot

I prefer to just have a single dovecot.conf file instead of split files, so backup the original one. Then create new one and edit it.

$ sudo -i
# doveconf -n > /etc/dovecot/dovecot.conf.new
# mv /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.orig
# mv /etc/dovecot/dovecot.conf.new /etc/dovecot/dovecot.conf
# vi /etc/dovecot/dovecot.conf

Note: $ for normal user, # for root.

Find the line ssl = no, and delete it. Then insert following block:

service imap-login {
  inet_listener imap {
    port = 0
  }
  inet_listener imaps {
    port = 993
  }
}

ssl = required
ssl_ca = </etc/ssl/certs/ca-certificates.crt
ssl_cert = </etc/ssl/certs/appbead.com.chain.crt
ssl_key = </etc/ssl/private/appbead.com.key

Note:
Listen the IMAPS port 993 by define the service imap-login
To disable IMAP, set port to 0
Force SSL connect, and use our certificate files

Don't allow systemd monitor the IMAP(143) port to prevent error:

# cp /lib/systemd/system/dovecot.socket /etc/systemd/system/
# systemctl reenable dovecot.socket
# sed -i '/:143$/s/^/#/' /etc/systemd/system/dovecot.socket

Test

On the Server side:

# systemctl restart postfix
# systemctl restart dovecot
# netstat -lnpt

Check if the ports (25, 587 and 993) are listed in the column 'Local Address'. Also check the logs:
less /var/log/mail.log and less /var/log/syslog

On the Local side:

$ openssl s_client -starttls smtp -crlf -connect <your_mail_server>:587
$ openssl s_client -connect <your_mail_server>:993

In both cases, the third line from the bottom of output should be:

    Verify return code: 0 (ok)

Authentication and Mailbox

Postfix

$ sudo vi /etc/postfix/main.cf

Handing off authentication to Dovecot. Insert following block:

smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
# The path is relative to $queue_directory:
#   # postconf |grep queue_directory
#   queue_directory = /var/spool/postfix
smtpd_sasl_path = private/auth
# Do not accept SASL authentication over unencrypted connections
smtpd_tls_auth_only = yes

Dovecot

$ sudo vi /etc/dovecot/dovecot.conf

Insert following block

# Allows plaintext authentication only when SSL/TLS is used first.
#   http://wiki2.dovecot.org/Authentication
auth_mechanisms = plain login
disable_plaintext_auth = yes

service auth-worker {
  # Forbid to access /etc/shadow
  user = $default_internal_user
}

service auth {
  # IMPORTANT: Match the path to smtpd_sasl_path of Postfix
  unix_listener /var/spool/postfix/private/auth {
    group = postfix
    user = postfix
    mode = 0666
  }
}

Replace the definition of mail_location, passdb and userdb as following:

mail_location = maildir:/var/vmail/%d/%n

passdb {
  driver = passwd-file
  # The entire email address will be used as the username for email client.
  # Don't bother about the scheme here, will be overwritten by a strong scheme from file.
  #    (http://wiki2.dovecot.org/AuthDatabase/PasswdFile)
  args = scheme=CRYPT username_format=%u /etc/dovecot/users
}

userdb {
  # For static type, LDA verify the user's existence by lookup passdb
  #   ( http://wiki2.dovecot.org/UserDatabase/Static )
  driver = static
  args = uid=vmail gid=vmail home=/var/vmail/%d/%n
}

For details of variables(%d, %n, and %u), see http://wiki2.dovecot.org/Variables.
Why not use the existing mail as UID instead of new one? Check this error.

For the first time, either authenticate successfully, or new mail arrive. All the special directories of the mailbox will be automatically created by Dovecot, for that account. So we need specify the format of mailbox in mail_location, also a system user to execute the operations of mailbox.

Add the system user vmail:

# adduser --system --home /var/vmail --uid 550 --group --disabled-login vmail

The directory /var/vmail will be created, and owned by system user vmail.

The First Mail Account

  • Generate a password HASH with SHA512-CRYPT scheme.
$ doveadm pw -s SHA512-CRYPT

Input your password, and the output may looks like,

{SHA512-CRYPT}$6$VaEOV5mzsbP1q2H9$Ctar1HzJCZGXmlXcJDluXEFjGdEwjDKIZ80I0KhG6YD4c2X13YDX/dIb1kGPLAwo7.fTnRaQpcsN5O5O9QjaJ0
  • Append the user record into the passwd-file /etc/dovecot/users, and the format is user:{SCHEME}password. We run the command cat as root.
sudo -i
cat << EOF >> /etc/dovecot/users
user1@example.com:{SHA512-CRYPT}$6$VaEOV5mzsbP1q2H9$Ctar1HzJCZGXmlXcJDluXEFjGdEwjDKIZ80I0KhG6YD4c2X13YDX/dIb1kGPLAwo7.fTnRaQpcsN5O5O9QjaJ0
EOF
  • Set the file modes:
# chmod 640 /etc/dovecot/users
# chown root:dovecot /etc/dovecot/users

Test

On the Server side:

Restart service, and confirm the Unix socket file created automatically.

# systemctl restart postfix
# systemctl restart dovecot
# ls -l /var/spool/postfix/private/auth

On the Local side:

$ openssl s_client -connect <your_mail_server>:993
......
* OK ......
a login user1@example.com mypassword  <- Input Line
a OK [......] Logged in
b logout  <- Input Line
......

Mail Delivery (LMTP)

Postfix

$ sudo vi /etc/postfix/main.cf

Add a line mydomain = appbead.com before $myhostname. And change variables as following:

mydomain = appbead.com
myhostname = mx.$mydomain
myorigin = $mydomain
mydestination = localhost

Replace appbead.com with yours. The value of $mydomain and $myhostname must match to the names used to request your SSL certification. The common usages of variables:

  • $myhostname: The hostname to send in the SMTP HELO or EHLO command, and SMTP greeting banner.
  • $myorigin, $mydestination: For aliases, see comments in /etc/postfix/virtual_aliases later.
  • $myorigin, $virtual_mailbox_domains, $virtual_alias_maps: reject_unauth_destination

Insert following lines:

# Handing off local delivery to Dovecot's LMTP
# http://wiki2.dovecot.org/HowTo/PostfixDovecotLMTP
#
# The path relative to $queue_directory, that is:
#    /var/spool/postfix/private/dovecot-lmtp
virtual_transport = lmtp:unix:private/dovecot-lmtp

# Check domains only, query users and aliases in Dovecot
#
# IMPORTANT: Don't overlap with $mydestination
#virtual_mailbox_domains = example1.com, example2.com
virtual_mailbox_domains = $mydomain

#virtual_alias_domains = $virtual_alias_maps
virtual_alias_maps = hash:/etc/postfix/virtual_aliases

Aliases

# vi /etc/postfix/virtual_aliases

And fill with these lines:

# The input(left column) without domain, will match user@$myorigin
#   and user@$mydestination (e.g. root@example.com, root@localhost)
#
# The result(right column) without domain, Postfix will append
#   $myorigin as $append_at_myorigin=yes
# So the user user1@appbead.com must exists in /etc/dovecot/users
# See: The section TABLE FORMAT in manual virtual(5)

postmaster          root
webmaster           root

# Person who should get root's mail
root                user1

info@appbead.com    user1

# A catch-all address is at the risk of spam
#@appbead.com       user1

Replace user1 and appbead.com with yours, and feel free to add or remove maps for any users.

Then build the necessary DB file after every change:

# postmap /etc/postfix/virtual_aliases
# postfix reload

Dovecot

$ sudo vi /etc/dovecot/dovecot.conf

Insert following block:

service lmtp {
 unix_listener /var/spool/postfix/private/dovecot-lmtp {
   mode = 0666
   user = postfix
   group = postfix
  }
}

IMPORTANT: The full path of dovecot-lmtp must match to $virtual_transport in Postfix.

Test

On the Server side:

Restart service, and confirm the Unix socket file created automatically.

# systemctl restart postfix
# systemctl restart dovecot
# ls -l /var/spool/postfix/private/dovecot-lmtp

Send out an email report. With above alias maps, the user1@appbead.com will receive that message:

$ sendmail -bv webmaster
$ sudo ls -l /var/vmail/appbead.com/user1/new

DNS Records

It's time to configure our DNS records, so outside mail server knows what's the IP our mail server uses. In the control panel of your domain service provider, add two records as follows:

Type Host Answer Prio
A mx.appbead.com 123.44.55.66 -
MX appbead.com mx.appbead.com 10

In order to avoid being a victim of Sender Address Forgery, also add this SPF record (syntax).

Type Host Answer Prio
TXT appbead.com "v=spf1 a mx -all" -
  • Replace 123.44.55.66 with your IP.
  • Replace mx.appbead.com with the host name of your mail server, it must be same as the $myhostname in /etc/postfix/main.cf.
  • Replace appbead.com with your domain name.
  • You may use "@" instead of "appbead.com" in the column "Host" for some providers.

Also in the control panel of your hosting service provider, add this PTR record:

Type Host Answer Prio
PTR 123.44.55.66 mx.appbead.com -

Without this record, the emails sending by our MTA may be rejected by others.
The steps to modify PTR record on DigitalOcean is:
Click Droplets > Droplet > Settings > Rename
Fill with mx.appbead.com (your host name of mail server)

Use dig to test:

$ dig +short mx appbead.com |awk '{print $2}'
mx.appbead.com.
$ dig +short a mx.appbead.com
123.44.55.66
$ dig +short -x 123.44.55.66
mx.appbead.com.

Read and Send Emails with MUA

We have a new email on the server just a moment ago. To read it on the local, or even use the mail account to send mails to others, open your favorite MUA, and create a new email account with following information:

Configuring IMAP accounts

Server Name: mx.appbead.com
Port: 993
Connection security: SSL/TLS
Authentication method: Normal password
User Name: user1@appbead.com

Configuring the outgoing (SMTP) server

Server Name: mx.appbead.com
Port: 587
Connection security: STARTTLS
Authentication method: Normal password
User Name: user1@appbead.com

Congratulation!

Now your mail server is up and running. And you can receive and send emails with your favorite MUA on the local!

You may stop configuration here, and wait for a couple of days to see interesting things happen, but keep an eye on your /var/log/mail.log!

However, I'd recommend you to take a break, then continue to the next page. It's the most important and interesting part of our mail server!

< Previous Page Next Page >

References

http://www.postfix.org/postconf.5.html
http://wiki2.dovecot.org/HowTo/PostfixAndDovecotSASL
http://wiki2.dovecot.org/HowTo/PostfixDovecotLMTP

UID Error

~# doveadm user user1@example.com
doveadm(root): Error: user user1@example.com: Mail access for users with UID 8 not permitted (see first_valid_uid in config file, uid from userdb lookup).
field   value
~# doveconf |grep first_valid_uid
first_valid_uid = 500

Obviouslly the UID of user mail is 8, it's not meet the condition of first_valid_uid.

Comments