Email Logins for Dovecot and Exim

While I was cleaning up my Ubuntu Email server configuration, I consolidated my login security.  My SMTP server is Exim and my IMAP server is Dovecot.  Mail User Agents (MUAs) use authentication over TLS encrypted connections to access IMAP and SMTP.   Both programs had their own password configuration.

Exim includes Dovecot in its supported authentication mechanisms.  This enables one authentication mechanism to be used for both SMTP and IMAP (or POP3).   This post also includes configuration details for forced authentication over the Submission port.

Configuring Dovecot

The configuration for Dovecot supports inclusion of directory contents.  This makes adding local modifications simpler as the main configuration file does not need to be modified.

I had already enabled TLS in dovecot. Both IMAP and IMAPS are enabled, with plain text passwords being disabled on unsecured connections. Connections from localhost are considered secure. Otherwise, IMAP connections must use STARTTLS before authenticating. The relevant lines from /etc/dovecot/conf.d/local.conf are:

protocols = imap imaps
disable_plaintext_auth = yes
ssl_cert_file = /etc/ssl/certs/
ssl_key_file = /etc/ssl/private/

The main configuration file supports use of pam for the user database and passwords.   On my mail server most users have their password disabled, so I need to provide a password database.  If  you are only using pam, you do NOT need to configure a passdb.  I also provide for a secondary passdb with an alternate password for use in Internet cafes, and similar locations.  Configuration of authentication mechanism and the password files is done with the file /etc/dovecot/auth.d/passwd.auth.  It contains:

  mechanisms = plain
  passdb passwd-file {
    args = /etc/dovecot/passwd.dovecot
  # Extra passwords for Internet cafes (only the first match in each file is used).
  passdb passwd-file {
    args = /etc/dovecot/passwd.secondary

To enable Exim to authenticate against the Dovecot database a socket is required.  I configured this with the file /etc/dovecot/auth.d/socket.auth. It contains:

  socket listen {
    client {
      path = /var/run/dovecot/auth-client
      mode = 0660
      group = Debian-exim

Passwords in the file can be encrypted using any supported mechanism. They can be encoded in either base64 or hex. The password file is a simple two field file consisting of a user-id and a password.  The encryption mechanism can be included with the password using the standard mechanism in curly brackets prefix, “{mechanism}“. I chose to use the salted SHA256 mechanism so my lines look like:


Once these files have been created and Dovecot restarted, other programs can use the Dovecot auth-client socket to authenticate.

Configuring Exim

I use a split configuration for Exim as this retains my modifications across upgrades. It also helps isolate local modifications. Like Dovecot I had already configured TLS, and authentication. All three protocols (SMTP, SMTPS, and Submission) are enabled. The relevant lines from /etc/exim4/conf.d/main/00_localmacros are:

# Enable smtps and submission ports; require tls for auth
auth_advertise_hosts = ${if eq{$tls_cipher}{}{}{*}}
daemon_smtp_ports = 25 : 465 : 587
tls_on_connect_ports = 465

# Enable TLS; only on submission port
MAIN_TLS_ADVERTISE_HOSTS = ${if eq {$interface_port}{587}{*}{}}
MAIN_TLS_CERTIFICATE = /etc/ssl/certs/
MAIN_TLS_PRIVATEKEY =  /etc/ssl/private/
hosts_require_auth = ${if eq {$interface_port}{587}{*}{}}

A couple of ACL changes are appropriate if you are using the Submission port.  To ensure authentication, a simple deny rule should be added to the top of the Mail ACL.  If  you are not using the Mail ACL, it can be added to the top of the Recipient ACL.  This is the condition I use:

 message = Authentication required before MAIL command
 !authenticated = *
 condition = ${if eq {$interface_port}{587}{true}}

The second change is to treat an authenticated connection as equivalent to a local connection.  This is done in the recipient ACL.  Find  find the accept rule which has the condition “hosts = +relay_from_hosts“.  Duplicate it replacing the hosts condition with “authenticated = *“.  My accept rule (which is adapted for DKIM) reads as follows:

 authenticated = *
 control = submission/sender_retain
 control = dkim_disable_verify

Exim’s authentication configuration is stored in the /etc/exim4/conf.d/auth directory.   I removed the previous client authentications and created a new file 10_local-dovecot. This contains a single plain-text authentication mechanism. As with Dovecot authentication is only available on encrypted (secured) connections. This file contains:

### auth/10_local-dovecot

  driver = dovecot
  public_name = PLAIN
  server_socket = /var/run/dovecot/auth-client
  server_set_id = $auth1

After these configuration changes have been done and Exim restarted, Dovecot and Exim will be using the same authentication mechanisms.


As alway, you will need to edit the files as appropriate for your configuration. In this case, only the names of the TLS files should need to change.

If you are using  a password file, you will need to populate it and secure it appropriately.  Only root and any password change utility need the file.

Changing passwords

I did not provide a mechanism for maintaining the user database and their passwords. The simplest mechanism may be to configure dovecot-sql. A minimal web application could then be developed to maintain the table. This would be be a good test project for learning Spring or some other framework.

If you are using a dovecot database as a userdb, you have a options for configuring Exim.

  • Configure a router and transport as documented in This may require manual creation of the users directory. If the home directories are locally or via NFS, then they may already exist.
  • Configure a router and transport that access the database for the required data. This configuration could allow automatic creation of the user’s directory.

TLS Issues

If you have problems with either program accessing the TLS certificate add their user id to the ssl-cert group. The certificate should be made readable by this group if it is not already.

I use self-signed TLS certificates, so users need to permanently accept the certificate the first time they connect with a  client.   As I use tinyCA as my certificate authority, an optional solution is to install the certificate authorities certificate in the relevant store(s) on the client.