MAS - Mail Access Server

Dovecot Logo

Dovecot is an open source IMAP and POP3 server for Linux/UNIX-like systems, written primarily with security in mind. Dovecot is an excellent choice for both small and large installations. It’s fast, simple to set up, requires no special administration and it uses very little memory.

Install Software

Dovecot is in the Ubuntu software packages repository:

$ sudo apt-get install dovecot-mysql dovecot-pop3d dovecot-imapd dovecot-managesieved

You will be asked about security certificate, and if a self-signed certificate should be created for you. Answer <No> to that, as we will use the already created Certificates and Keys.

The installation creates the following items:

  • The user and group dovecot for the mail server.

  • The user and group dovenull to process mail server logins.

  • The directory /etc/dovecot

  • The main configuration file /etc/dovecot/dovecot.conf

  • Various other configuration files in the directory /etc/dovecot/conf.d

  • The Ubuntu Upstart service configuration /etc/init/dovecot.conf

Other example configuration files are found in the /usr/share/doc/dovecot-core/example-config/ directory.

Main Configuration

The main configuration file /etc/dovecot/dovecot.conf has a limited amount of settings, as most things are included from individual files in the /etc/dovecot/conf.d directory.

Services

Dovecot can provide a number of mail services. We activate IMAP and LMTP.

# Enable installed protocols
!include_try /usr/share/dovecot/protocols.d/*.protocol
protocols = imap lmtp

IP-Addresses

Dovecot would bind to all available addresses, to change that, we remove the comment hashtag and set the IP address the IMAP server should listen to connections:

# A comma separated list of IPs or hosts where to listen in for connections. 
# "*" listens in all IPv4 interfaces, "::" listens in all IPv6 interfaces.
# If you want to specify non-default ports or anything more complex,
# edit conf.d/master.conf.
listen = 127.0.0.1,192.0.2.40,::1,2001:db8::40

Database Connection

Dovecot can use our mailserver database to validate domains, mailboxes and authenticate users. The configuration is set in the file /etc/dovecot/dovecot-sql.conf.ext.

Type of Database

What type of database or server to use:

# Database driver: mysql, pgsql, sqlite
driver = mysql

Database Server Login

How to connect to the database server and what username and password to use:

# Database connection string. This is driver-specific setting.
connect = host=127.0.0.1 dbname=mailserver user=mailuser password=********

The database-name, user and password are identical to what you have set in /etc/postfix/mysql-virtual-mailbox-maps.cf for MTA - Mail Transfer Server.

Password Scheme

How are passwords stored (hashed) in the password database:

# Default password scheme.
#default_pass_scheme = SHA512-CRYPT

The Dovecot Wiki describes the available password schemes.

Database Query

The MySQL query to retrieve username and (hashed) password for a mail-address.

# passdb query to retrieve the password. It can return fields:
#   password - The user's password. This field must be returned.
#   user - user@domain from the database. Needed with case-insensitive lookups.
#   username and domain - An alternative way to represent the "user" field.
#  FROM users WHERE username = '%n' AND domain = '%d'

Services

The file /etc/dovecot/conf.d/10-master.conf defines the properties of the services Dovecot provides to other hosts.

We use Dovecot to provide the following services:

  • IMAP - for MUA to access their mailbox

  • LMTP & LDA - Delivery of mail to local mailboxes

  • AUTH - let other services (i.e. MSA or XMPP) authenticate users by Dovecot.

IMAP Settings

The IMAP service configuration can be left at its defaults.

In the file /etc/dovecot/conf.d/20-imap.conf we add the imap_sieve pluing as loaded (more on sieve later).

It also advisable to increase the number of IMAP connections per user from the default 10, considering multiple devices (PC, Laptop, Notebook, Tablet, Smartphone) and probably most of it trough NAT.

LMTP - Local Mail Transport

  • When the MTA server has accepted a message from the Internet he uses an LDA to send it to the server who holds the recipients mailbox.

  • When the MSA server has accepted a message from an MUA he then sends it by LMTP to the MTA who takes care of the transer to other Internet domains.

  • A script running on a web-server creates a mail to a user, as part of some transaction (registraion confirmation, password-reset). The web server uses LMTP to send it to the MTA.

To allow our MTA Postfix to deliver mails to mailboxes trough the Dovecot LMTP service:

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

The configuration file /etc/dovecot/conf.d/20-lmtp.conf holds settings specific to the LMTP service.

We load the Dovecot Sieve plugin.

protocol lmtp {
  # Space separated list of plugins to load (default is global mail_plugins).
  mail_plugins = $mail_plugins sieve
}
			  

LDA - Local Delivery Agent

Local delivery happens when mails are to be delivered to a mailbox of the local system. Here are some uses-cases:

The file /etc/dovecot/conf.d/15-lda.conf is used to set-up local delivery.

The name and domain of our server is only availabel in our local LAN and not valid on the Internet. We therefore need to override the server-name and the postmaster mail address to values which are valid and recognizible, as these will be inserted in the header of messages.

# Address to use when sending rejection mails.
# Default is postmaster@<your domain>. %d expands to recipient domain.
postmaster_address = postmaster@example.net

# Hostname to use in various parts of sent mails (e.g. in Message-Id) and
# in LMTP replies. Default is the system's real hostname@domain.
hostname = mail.example.net

We load the Dovecot Sieve plugin.

protocol lda {
  # Space separated list of plugins to load (default is global mail_plugins).
  #mail_plugins = $mail_plugins
  mail_plugins = $mail_plugins sieve
}

AUTH Settings

Other services can use Dovecot for user authentication instead of maintaining their own user-database. A registred user on our mail server can use the same username and password with other services.

To allow our MSA Postfix to use the user authentication service, the UNIX socket that Postifx will access, needs specific access rights:

service auth {
  # Postfix smtp-auth
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }

Transport Layer Security

See also the Dovecot SSL configuration in the Dovecot wiki.

The file /etc/dovecot/conf.d/10-ssl.conf contains settings for TLS protocol settings, certificates and keys.

We enforce encryption and server authentication on all connections:

# SSL/TLS support: yes, no, required. <doc/wiki/SSL.txt>
ssl = required

Where the servers certificate and private key are stored:

ssl_cert = </etc/ssl/certs/example.net.chained.cert.pem
ssl_key = </etc/ssl/private/example.net.key.pem

Note

Note the “<” character in front of the filenames. Dovecot will fail with errors about unreadable PEM encoded key files, if they are omitted.

Diffie-Hellmann Parameters

Encryption strenght of session keys negotiated by Diffie-Hellman key exchange.

Dovecot creates its own DH parameters and also refesehes them periodically. There is no need to provide a DH parameters file, as with some other servers.

# DH parameters length to use.
ssl_dh_parameters_length = 4096

SSL & TLS Protocol Versions

# SSL protocols to use
# Default: !SSLv3
ssl_protocols = !SSLv3 !TLSv1 !TLSv1.1

Set our selected Cipher Suite Selection.

# SSL cipher list
# Default: ALL:!LOW:!SSLv2:!EXP:!aNULL

Let the server choose the cipher-suite during handhake.

# Prefer the server's order of ciphers over client's.

Authentication

The file /etc/dovecot/conf.d/10-auth.conf defines how users logins are processed.

# Space separated list of wanted authentication mechanisms:
#   plain login digest-md5 cram-md5 ntlm rpa apop anonymous gssapi otp skey
#   gss-spnego
# NOTE: See also disable_plaintext_auth setting.
auth_mechanisms = plain

Disable login for system users and enable the MySQL user database, by commenting out the first line with a hashtag and activating the auth- sql.conf.ext line with a exclamation mark:

#!include auth-deny.conf.ext
#!include auth-master.conf.ext

#include auth-system.conf.ext
!include auth-sql.conf.ext
#!include auth-ldap.conf.ext
#!include auth-passwdfile.conf.ext
#!include auth-checkpassword.conf.ext
#!include auth-vpopmail.conf.ext
#!include auth-static.conf.ext

The now included file /etc/dovecot/conf.d/auth-sql.conf.ext contains references to the database configuration file.

First where (hashed) paswords are retrieved for authenticating users:

passdb {
  driver = sql

  # Path for SQL configuration file, see example-config/dovecot-sql.conf.ext
  args = /etc/dovecot/dovecot-sql.conf.ext
}

And how other used properties, like mailbox directory, are retrieved:

userdb {
  driver = static
  args = uid=vmail gid=vmail home=/var/vmail/%d/%n allow_all_users=yes
}

The parameter static above means. they are not retrieved from the database, but are all the same for all our users according to the values in args.

The args values are translated as follows:

  • The system user profile and group used who accesses the mailbox directory

    is vmail.

  • Mailboxes are stored in the directory /var/vmail/%d/%n/ where

    %d will be replaces by the domain name (e.g. example.net) and %n will be replaced by the user name.

  • allow_all_users=yes, is to allow mail delivery, also for mails to users not found yet in the database.

This basically means, that mails for user@example.net will be stored in the /var/vmail/example.net/user directory.

Mailbox Locations

In the file /etc/dovecot/conf.d/10-mail.conf we set up parameters for our virtual mailboxes.

mail_location = maildir:/var/vmail/%d/%n/Maildir
# System user and group used to access mails. If you use multiple, userdb
# can override these by returning uid or gid fields. You can use either numbers
# or names. <doc/wiki/UserIds.txt>
mail_uid = vmail
mail_gid = vmail

IMAP Folder Creation

Most mail clients use a common set of IMAP folders, besides the “Inbox” for storing various types of mails:

  • Drafts

  • Sent

  • Archives

  • Junk

  • Trash

We can tell Dovecot to create these folders automatically, if they don’t already exists, on users login. The user will also be subcribed to them, depending on settings. If a user accidentely deletes one of these folders, they will be re-created automatically on the next login.

/etc/dovecot/conf.d/15-mailboxes.conf.

##
## Mailbox definitions -  ( for Dovecot 2.3.7.2 )
##

# Each mailbox is specified in a separate mailbox section. The section name
# specifies the mailbox name. If it has spaces, you can put the name
# "in quotes". These sections can contain the following mailbox settings:
#
# auto:
#   Indicates whether the mailbox with this name is automatically created
#   implicitly when it is first accessed. The user can also be automatically
#   subscribed to the mailbox after creation. The following values are
#   defined for this setting:
#
#     no        - Never created automatically.
#     create    - Automatically created, but no automatic subscription.
#     subscribe - Automatically created and subscribed.
#
# special_use:
#   A space-separated list of SPECIAL-USE flags (RFC 6154) to use for the
#   mailbox. There are no validity checks, so you could specify anything
#   you want in here, but it's not a good idea to use flags other than the
#   standard ones specified in the RFC:
#
#     \All      - This (virtual) mailbox presents all messages in the
#                 user's message store.
#     \Archive  - This mailbox is used to archive messages.
#     \Drafts   - This mailbox is used to hold draft messages.
#     \Flagged  - This (virtual) mailbox presents all messages in the
#                 user's message store marked with the IMAP \Flagged flag.
#     \Junk     - This mailbox is where messages deemed to be junk mail
#                 are held.
#     \Sent     - This mailbox is used to hold copies of messages that
#                 have been sent.
#     \Trash    - This mailbox is used to hold messages that have been
#                 deleted.
#
# comment:
#   Defines a default comment or note associated with the mailbox. This
#   value is accessible through the IMAP METADATA mailbox entries
#   "/shared/comment" and "/private/comment". Users with sufficient
#   privileges can override the default value for entries with a custom
#   value.

# NOTE: Assumes "namespace inbox" has been defined in 10-mail.conf.
namespace inbox {

    # These mailboxes are widely used and could perhaps be created automatically:
    mailbox Drafts {
        special_use = \Drafts
        auto = subscribe
    }
    mailbox Junk {
        special_use = \Junk
        auto = subscribe
        autoexpunge = 90d
    }
    mailbox Trash {
        special_use = \Trash
        auto = subscribe
    }
    mailbox Archives {
        special_use = \Archive
        auto = subscribe
    }

    # For \Sent mailboxes there are two widely used names. We'll mark both of
    # them as \Sent. User typically deletes one of them if duplicates are created.
    mailbox Sent {
        special_use = \Sent
        auto = subscribe
    }
    mailbox "Sent Messages" {
        special_use = \Sent
    }

    # Archive (singular form without the 'S')
    mailbox "Archive" {
        special_use = \Archive
    }

    # If you have a virtual "All messages" mailbox:
    #mailbox virtual/All {
    #   special_use = \All
    #   comment = All my messages
    #}

    # If you have a virtual "Flagged" mailbox:
    #mailbox virtual/Flagged {
    #   special_use = \Flagged
    #   comment = All my flagged messages
    #}
}

# -*- mode: txt; indent-tabs-mode: nil; tab-width: 4; -*-

Sieve Filter Management Server

Todays users access their mail from multiple devices and locations. Desktop computers at the office and at home, laptops, notebooks, tablets, smartphones, while commuting or from coffee-shops, hotel-rooms etc. They use dedicated mail clients like Thunderbird or Outlook, but also with their browser on webmail clients.

Classic client-side mail filter-rules don’t cut it anymore. Mail has to be categorized and filtered on the server on delivery, to provide a consistent view accross all clients.

Sieve is a basic script language to manage mail on the server, by triggering simple actions (move to folder, delete, mark as read, etc.), based on message attributes like sender or recipient, spam-flags, mailing-listss, headers, etc. The famous “Out-of Office” or “Vacation” auto-answer is a typical use case.

The ManageSieve server allows administrators to define a set of sieve-scripts for all accounts on the server, but also lets users to manage their own mail filters.

User can manage their own filter-scripts with a sieve client. Either integrated in their mail-client, on their webmail-page or with standalone software which then connects to the ManageSieve server provided by dovecot.

The ManageSieve server is configured in the file /etc/dovecot/conf.d/20-managesieve.conf.

##
## ManageSieve specific settings
##

# Uncomment to enable managesieve protocol:
protocols = $protocols sieve

# Service definitions

service managesieve-login {

    inet_listener sieve {
        port = 4190
    }

    # Number of connections to handle before starting a new process. Typically
    # the only useful values are 0 (unlimited) or 1. 1 is more secure, but 0
    # is faster. <doc/wiki/LoginProcess.txt>
    #service_count = 1

    # Number of processes to always keep waiting for more connections.
    #process_min_avail = 0

    # If you set service_count=0, you probably need to grow this.
    #vsz_limit = 64M
}

service managesieve {

    # Max. number of ManageSieve processes (connections)
    #process_limit = 1024
}

# Service configuration

protocol sieve {
    # Maximum ManageSieve command line length in bytes. ManageSieve usually does
    # not involve overly long command lines, so this setting will not normally
    # need adjustment
    #managesieve_max_line_length = 65536

    # Maximum number of ManageSieve connections allowed for a user from each IP
    # address.
    # NOTE: The username is compared case-sensitively.
    #mail_max_userip_connections = 10

    # Space separated list of plugins to load (none known to be useful so far).
    # Do NOT try to load IMAP plugins here.
    #mail_plugins =

    # MANAGESIEVE logout format string:
    #  %i - total number of bytes read from client
    #  %o - total number of bytes sent to client
    #managesieve_logout_format = bytes=%i/%o

    # To fool ManageSieve clients that are focused on CMU's timesieved you can
    # specify the IMPLEMENTATION capability that Dovecot reports to clients.
    # For example: 'Cyrus timsieved v2.2.13'
    #managesieve_implementation_string = Dovecot Pigeonhole

    # Explicitly specify the SIEVE and NOTIFY capability reported by the server
    # before login. If left unassigned these will be reported dynamically
    # according to what the Sieve interpreter supports by default (after login
    # this may differ depending on the user).
    #managesieve_sieve_capability =
    #managesieve_notify_capability =

    # The maximum number of compile errors that are returned to the client upon
    # script upload or script verification.
    #managesieve_max_compile_errors = 5

    # Refer to 90-sieve.conf for script quota configuration and configuration of
    # Sieve execution limits.
}

# -*- mode: txt; indent-tabs-mode: nil; tab-width: 4; -*-

Pigeonhole Sieve interpreter

Sieve plugin itself is configured in the file /etc/dovecot/conf.d/90-sieve.conf.

plugin {
   sieve = ~/.dovecot.sieve
   sieve_global_path = /var/lib/dovecot/sieve/default.sieve
   sieve_dir = ~/sieve
   sieve_global_dir = /var/lib/dovecot/sieve/
}

Dovecot Sieve & RSPAMD

Sieve is also used to intergrate Dovecot nicely with the RSPAMD Spamfilter:

  • Mail marked as Spam by RSPAMD is moved to the Junk folder, instead of the Inbox.

  • When a user moves a message from any folder to the Junk folder, that message is passed on to RSPAMD as training data to improve its reliablitly in detecting spam.

  • When a user is movin a message out of the Junk folder, its also passed on to RSPAMD for training to reduce false postives.

darix on GitHub has prepared a set of scripts and configurations for doing all that.

Installation

Clone and install darix’s repository:

$ cd /usr/local/src/
$ git clone git@github.com:darix/dovecot-sieve-antispam-rspamd.git
$ cd dovecot-sieve-antispam-rspamd
$ make install

Configuration

The dovecot sieve scripts need access to the RPSPAMD controller socket. Write your RPSPAMD controller password in to the file /etc/dovecot/rspamd-controller.password.

Most other settings are found in the file /etc/dovecot/conf.d/99-antispam_with_sieve.conf.

Change the lines containing the Spamfolder to the one we use:

...
imapsieve_mailbox1_name = Junk
...
imapsieve_mailbox2_from = Junk

The same needs to be done in the sieve script /usr/lib/dovecot/sieve/global-spam.sieve:

...
fileinto :create "Junk";
...

Mailbox Quota

Quota Plugins Activation

In the file /etc/dovecot/conf.d/20-imap.conf:

# Enable quota plugin for tracking and enforcing the quota.
mail_plugins = $mail_plugins quota

# Enable the IMAP QUOTA extension, allowing IMAP clients to ask for the
# current quota usage.
mail_plugins = $mail_plugins imap_quota

Qupta Plugins Configuration

Quota plugins configurations in the file /etc/dovecot/conf.d/90-quota.conf.

##
## Quota configuration.
##

# Note that you also have to enable quota plugin in mail_plugins setting.
# <doc/wiki/Quota.txt>

##
## Quota limits
##

# Quota limits are set using "quota_rule" parameters. To get per-user quota
# limits, you can set/override them by returning "quota_rule" extra field
# from userdb. It's also possible to give mailbox-specific limits, for example
# to give additional 100 MB when saving to Trash:

plugin {
    quota_rule = *:storage=15G
    quota_rule2 = Trash:storage=+500M
    quota_rule3 = Junk:storage=+500M

    # LDA/LMTP allows saving the last mail to bring user from under quota to
    # over quota, if the quota doesn't grow too high. Default is to allow as
    # long as quota will stay under 10% above the limit. Also allowed e.g. 10M.
    quota_grace = 10%%

    # Quota plugin can also limit the maximum accepted mail size.
    quota_max_mail_size = 25M
}

##
## Quota warnings
##

# You can execute a given command when user exceeds a specified quota limit.
# Each quota root has separate limits. Only the command for the first
# exceeded limit is executed, so put the highest limit first.
# The commands are executed via script service by connecting to the named
# UNIX socket (quota-warning below).
# Note that % needs to be escaped as %%, otherwise "% " expands to empty.

plugin {
    quota_warning = storage=95%% quota-warning 95 %u
    quota_warning2 = storage=80%% quota-warning 80 %u
}

# Quota-warning service. The unix listener's permissions should be set in a way
# that mail processes can connect to it. Below example assumes
# that mail processes run as vmail user. If you use mode=0666, all system users
# can generate quota warnings to anyone.
service quota-warning {
    executable = script /usr/local/bin/dovecot-quota-warning
    user = vmail
    unix_listener quota-warning {
        user = vmail
    }
}

##
## Quota backends
##

# Multiple backends are supported:
#   dirsize: Find and sum all the files found from mail directory.
#            Extremely SLOW with Maildir. It'll eat your CPU and disk I/O.
#   dict: Keep quota stored in dictionary (eg. SQL)
#   maildir: Maildir++ quota
#   fs: Read-only support for filesystem quota

plugin {

    # Track the current quota usage in Dovecot’s index files.
    quota = count:User quota

    #quota = dirsize:User quota
    quota = maildir:User quota
    #quota = dict:User quota::proxy::quota
    #quota = fs:User quota

    # Required by quota=count backend. Indicates that the quota plugin should
    # use virtual sizes rather than physical sizes when calculating message
    # sizes.
    quota_vsizes = yes

    # Controls the maximum message size that is allowed to be saved (e.g. by
    # LMTP, IMAP APPEND or doveadm save).
    quota_max_mail_size = 25M

}

# Multiple quota roots are also possible, for example this gives each user
# their own 100MB quota and one shared 1GB quota within the domain:
plugin {
  #quota = dict:user::proxy::quota
  #quota2 = dict:domain:%d:proxy::quota_domain
  #quota_rule = *:storage=102400
  #quota2_rule = *:storage=1048576
}

# -*- mode: txt; indent-tabs-mode: nil; tab-width: 4; -*-

Quota Warning Mails

Create the simple shell script /usr/local/bin/dovecot-quota-warning:

#!/bin/sh

PERCENT=$1
USER=$2

cat << EOF | /usr/lib/dovecot/dovecot-lda -d "$USER" \
    -o "plugin/quota=maildir:User quota:noenforcing"
From: postmaster@urown.net
Subject: Mail service quota warning

Your mailbox $USER is now $PERCENT% full.

You should delete some messages from the server.


WARNING: Do not ignore this message as if your mailbox
reaches 100% of quota, new mail will be rejected.

EOF

Make it executable:

$ chmod +x /usr/local/bin/dovecot-quota-warning

Service Dependencies

Since we use MariaDB as database backend for Dovecot, we want to ensure that Dovecot is always able to connect to the database server while running.

The Systemd services file for the Dovecot server /lib/systemd/system/dovecot.service is created as part of the software package installation. The recommended method is to create a Systemd override-file and not change anything in the provided service file, as it would be lost on software package updates.

You can create a override file easily with the help of the systemctl command:

$ sudo systemctl edit dovecot.service

This will start your editor with an empty file, where you can add your own custom Systemd service configuration options.

[Unit]
After=mariadb.service
BindsTo=mariadb.service

The configuration statement After=mariadb.service ensures that mariadb.service is fully started up before the dovecot.service is started.

The line BindsTo=mariadb.service ensures that if the Database service is stopped, the PowerDNS server will be stopped too.

After you save and exit of the editor, the file will be saved as /etc/systemd/system/dovecot.service.d/override.conf and Systemd will reload its configuration:

systemctl show dovecot.service |grep -E "After=|BindsTo="