Setup Email Server From Scratch Debian #2 - 04 Dovecot IMAP

03 Postfix SMTPD <- Intro -> 05 PostfixAdmin

We believe in data independence, and support others who want data independence.
Debian Email From Scratch version 2 finished 2025-07-30.

We are still adding to it but it all works!

###############################
# INSTALL DOVECOT IMAP SERVER #
###############################

# Install Dovecot

apt install dovecot-core dovecot-imapd dovecot-mysql dovecot-lmtpd

# If you plan to use ARGON2I check if it is supported.

root@okdeb.com:~# doveadm pw -l
SHA1 SSHA512 SCRAM-SHA-256 BLF-CRYPT PLAIN HMAC-MD5 OTP SHA512 SHA DES-CRYPT CRYPT SSHA
MD5-CRYPT PLAIN-MD4 PLAIN-MD5 SCRAM-SHA-1 SHA512-CRYPT CLEAR CLEARTEXT ARGON2I ARGON2ID
SSHA256 MD5 PBKDF2 SHA256 CRAM-MD5 PLAIN-TRUNC SHA256-CRYPT SMD5 DIGEST-MD5 LDAP-MD5 

# Make backups of original configuration and working postfix configuration. We are
# going to make a lot of changes to these files so back up everything including
# subdirectorieds so we can always roll back to a working configuration.

cd /etc
cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.bak
cp /etc/postfix/main.cf /etc/postfix/main.cf.bak
cp /etc/postfix/master.cf /etc/postfix/master.cf.bak
cp -R dovecot dovecot_bak
cp -R postfix postfix_bak

# Configure Dovecot or confirm imap is enabled

nano /etc/dovecot/dovecot.conf
# ---
# Enable installed protocols
protocols = imap
!include_try /usr/share/dovecot/protocols.d/*.protocol
# ---

# Check what protocols are in the protocols.d directory
ls /usr/share/dovecot/protocols.d/*
/usr/share/dovecot/protocols.d/imapd.protocol

# Enable Submission service in Postfix - insert the following lines to master.cf

nano /etc/postfix/master.cf
# ---
#tlsproxy  unix  -       -       y       -       0       tlsproxy
submission     inet     n    -    y    -    -    smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_tls_wrappermode=no
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
smtps     inet  n       -       y       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
# Choose one: enable submission for loopback clients only, or for any client.
# ---

# Configure Postfix
# - Remove Debian from the banner

nano /etc/postfix/master.cf
# ---
smtpd_banner = $myhostname ESMTP $mail_name

# TLS parameters
smtpd_tls_cert_file=/etc/letsencrypt/live/mx.okdeb.com/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/mx.okdeb.com/privkey.pem
smtpd_tls_security_level=may
smtpd_tls_loglevel = 1
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache

tls_server_sni_maps = hash:/etc/postfix/sni_maps

smtp_tls_CApath=/etc/ssl/certs
smtp_tls_security_level=may
smtp_tls_loglevel = 1
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

# Enforce TLSv1.3 or TLSv1.2
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
# ---

# Setup our SNI maps in case we want multiple domains

nano /etc/postfix/sni_maps
# ---
mx.okdeb.com /etc/letsencrypt/live/mx.okdeb.com/privkey.pem /etc/letsencrypt/live/mx.okdeb.com/fullchain.pem
mail.okdeb.com /etc/letsencrypt/live/mx.okdeb.com/privkey.pem /etc/letsencrypt/live/mx.okdeb.com/fullchain.pem
# ---

postmap /etc/postfix/sni_maps

systemctl restart postfix
systemctl status postfix

# Check mailbox location
postconf mail_spool_directory
mail_spool_directory = /var/mail

# Reconfigure mailbox location

nano /etc/dovecot/conf.d/10-mail.conf
# ---
mail_location = maildir:~/Maildir
# ---

# Set automatic mailbox creation and subscriptions (viewed on client).

nano /etc/dovecot/conf.d/15-mailboxes.conf
# --- set auto = subscribe ---
namespace inbox {
  # These mailboxes are widely used and could perhaps be created automatically:
  mailbox Drafts {
    auto = subscribe
    special_use = \Drafts
  }
  mailbox Junk {
    auto = subscribe
    special_use = \Junk
  }
  mailbox Trash {
    auto = subscribe
    special_use = \Trash
  }

  # 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 {
    auto = subscribe
    special_use = \Sent
  }
  mailbox "Sent Messages" {
    special_use = \Sent
  }
  ...
}
# ---

# Add user dovecot to mail group

adduser dovecot mail

# Install and configure lmtp protocol

apt install dovecot-lmtpd

nano /etc/dovecot/dovecot.conf
# ---
protocols = imap lmtp 
# ---

nano /etc/dovecot/conf.d/10-master.conf
# ---
service lmtp {
 unix_listener /var/spool/postfix/private/dovecot-lmtp {
   mode = 0600
   user = postfix
   group = postfix
  }
}
# ---

# Add lmtp to end of main.cf file

nano /etc/postfix/main.cf
# ---
mailbox_transport = lmtp:unix:private/dovecot-lmtp
smtputf8_enable = no
# ---

# Change dovecot authentication

nano /etc/dovecot/conf.d/10-auth.conf
# ---
disable_plaintext_auth = yes
auth_username_format = %n
auth_mechanisms = plain login
# ---

# Configure Dovecot SSL for multiple domains with SNI maps - this is generally 
# the better configuration since it adds flexibility and reduces number of certs 
# per domain.

nano /etc/dovecot/conf.d/10-ssl.conf
# ---
# Default
ssl_cert = </etc/letsencrypt/live/mx.okdeb.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mx.okdeb.com/privkey.pem

local_name mx.okdeb.com {
ssl_cert = </etc/letsencrypt/live/mx.okdeb.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mx.okdeb.com/privkey.pem
}
local_name mail.okdeb.com {
ssl_cert = </etc/letsencrypt/live/mx.okdeb.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mx.okdeb.com/privkey.pem
}
# ---

# Configure SASL Authentication

nano /etc/dovecot/conf.d/10-master.conf
# ---
service auth {
  # auth_socket_path points to this userdb socket by default. It's typically
  # used by dovecot-lda, doveadm, possibly imap process, etc. Users that have
  # full permissions to this socket are able to get a list of all usernames and
  # get the results of everyone's userdb lookups.
  #
  # The default 0666 mode allows anyone to connect to the socket, but the
  # userdb lookups will succeed only if the userdb returns an "uid" field that
  # matches the caller process's UID. Also if caller's uid or gid matches the
  # socket's uid or gid the lookup succeeds. Anything else causes a failure.
  #
  # To give the caller full permissions to lookup all users, set the mode to
  # something else than 0666 and Dovecot lets the kernel enforce the
  # permissions (e.g. 0777 allows everyone full permissions).
  #unix_listener auth-userdb {
    #mode = 0666
    #user = 
    #group = 
  #}

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

  # Auth process is run as this user.
  #user = $default_internal_user
}
# ---

# Check 15-mailboxes.conf

nano /usr/local/etc/dovecot/conf.d/15-mailboxes.conf
# ---
...
  # These mailboxes are widely used and could perhaps be created automatically:
  mailbox Drafts {
    auto = create
    special_use = \Drafts
  }
  mailbox Junk {
    auto = create
    special_use = \Junk
  }
  mailbox Trash {
    auto = create
    special_use = \Trash
  }

  # 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 {
    auto = create
    special_use = \Sent
  }
  mailbox "Sent Messages" {
    special_use = \Sent
  }
...
# ---

systemctl restart postfix dovecot
systemctl status dovecot

# Check if dovecot is listening
root@okdeb.com:/etc/dovecot# ss -lnpt | grep dovecot
LISTEN 0  100    0.0.0.0:143       0.0.0.0:*    users:(("dovecot",pid=7563,fd=36))                                                                                                                                                     
LISTEN 0  100    0.0.0.0:993       0.0.0.0:*    users:(("dovecot",pid=7563,fd=38))                                                                                                                                                     
LISTEN 0  100       [::]:143          [::]:*    users:(("dovecot",pid=7563,fd=37))                                                                                                                                                     
LISTEN 0  100       [::]:993          [::]:*    users:(("dovecot",pid=7563,fd=39))                                                                                       

# Setup Thunderbird email client - use advanced settings
Add Mail Account
Incoming / IMAP
Full Name: Jack Pumpkin
Email address: jack@okdeb.com
Password: <secretpassword>
Click Configure Manually
Protocol: IMAP
Hostname: mx.okdeb.com
Port: 993
Security: SSL/TLS

Outgoing / SMTP
Username: jack@okdeb.com
Protocol: Outgoing
Hostname: mx.okdeb.com
Port: 587
Security: STARTTLS
Username: jack@okdeb.com
<Re-test>

# Thunderbird Errors

# If you encounter the following Thunderbird error when sending mail change 
# SSL/TLS to STARTTLS for the Outgoing Server.

Sending of the message failed. The message could not be sent because the connection to Outgoing server (SMTP) mx.coragarden.com 
was lost in the middle of the transaction. Try again.

# This seems to occur when Thunderbird caches bad autoconfig data from the server and 
# doesn't set the encryption method properly.

# Go to Account Settings / Outgoing Server and delete the relevant smtp server 
# entries. Then delete the account(s). Then go to Tools / Clear Recent History / 
# Delete Everything. Restart Thunderbird. Run a fresh test.

# I tried SNI, server name indication wasn't working.

Sending of the message failed. An error occurred while sending mail: Outgoing 
server (SMTP) error. The server responded: TLS not available due to local 
problem.

# SNI configuration requires default certs in both Postfix and Dovecot. After 
# SNI was fixed it was necessary to stop and restart Thunderbird to test if it 
# was fixed.

# At first I could not authenticate because I used auth_username_format = %u. At
# this stage in the setup use auth_username_format = %n, and switch to %u later on.

# To troubleshoot use ...
systemctl status dovecot
journalctl -eu dovecot

# Make dovecot restart if killed

mkdir -p /etc/systemd/system/dovecot.service.d/

nano /etc/systemd/system/dovecot.service.d/restart.conf
# ---
[Service]
Restart=always
RestartSec=5s
# ---
systemctl daemon-reload

# Test it
systemctl status dovecot
pkill dovecot
systemctl status dovecot
<wait 10 seconds>
systemctl status dovecot

# Autoconfig and Autodiscover

# Autoconfig and Autodiscover help mail clients find the settings for your mail server.
# https://github.com/smartlyway/email-autoconfig-php. I had some difficulty later on
# with Thunderbird because port 587 is defined with SSL in config-v1.1.xml. This
# result got cached in Thunderbird and removing the account didn't remove the cached
# data.

apt install git
cd /tmp
git clone https://github.com/smartlyway/email-autoconfig-php
cd email-autoconfig-php/mail
mkdir -p /var/www/okdeb/mail
cp /tmp/email-autoconfig-php/mail/config-v1.1.xml /var/www/okdeb/mail

# Edit these files and change to suit your needs, this is tested and works with 
# Thunderbird. Make sure change the SMTP settings to 587 with STARTTLS in 
# config-v1.1.xml.

nano /var/www/okdeb/mail/config-v1.1.xml
# ---
<?xml version="1.0"?>
<clientConfig version="1.1">
    <emailProvider id="okdeb.com">
      <domain>okdeb.com</domain>
      <displayName>okdeb.com</displayName>
      <displayShortName>okdeb.com</displayShortName>
      <incomingServer type="imap">
         <hostname>mx.okdeb.com</hostname>
         <port>993</port>
         <socketType>SSL</socketType>
         <authentication>password-cleartext</authentication>
         <username>%EMAILADDRESS%</username>
      </incomingServer>
      <outgoingServer type="smtp">
         <hostname>mx.okdeb.com</hostname>
         <port>587</port>
         <socketType>STARTTLS</socketType>
         <username>%EMAILADDRESS%</username>
         <authentication>password-cleartext</authentication>
      </outgoingServer>
    </emailProvider>
</clientConfig>
# ---

# Do the same for Outlook clients, this is untested ...

cd ~/email-autoconfig-php
cp -r /tmp/email-autoconfig-php/Autodiscover/Autodiscover.xml /var/www/okdeb/mail

nano /var/www/okdeb/mail/Autodiscover.xml/index.php
# ---
<?php
$raw = file_get_contents('php://input');
$matches = array();
preg_match('/<EMailAddress>(.*)<\/EMailAddress>/', $raw, $matches);
header('Content-Type: application/xml');
?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
  <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
    <User>
      <DisplayName>okdeb.com</DisplayName>
    </User>
    <Account>
      <AccountType>email</AccountType>
      <Action>settings</Action>
      <Protocol>
        <Type>IMAP</Type>
        <Server>mx.okdeb.com</Server>
        <Port>993</Port>
        <DomainRequired>off</DomainRequired>
        <SPA>off</SPA>
        <SSL>on</SSL>
        <AuthRequired>on</AuthRequired>
        <LoginName><?php echo $matches[1]; ?></LoginName>
      </Protocol>
      <Protocol>
        <Type>SMTP</Type>
        <Server>mx.okdeb.com</Server>
        <Port>587</Port>
        <DomainRequired>off</DomainRequired>
        <SPA>off</SPA>
        <SSL>on</SSL>
        <AuthRequired>on</AuthRequired>
        <LoginName><?php echo $matches[1]; ?></LoginName>
      </Protocol>
    </Account>
  </Response>
</Autodiscover>
# ---

# You will need to add a SV records for Autodiscover for NameCheap I added ...
# Namecheap Domain List -> DNS -> Advanced DNS

Type		Service		Protocol  Priority  Weight  Port  Target
SRV Record	_autodiscover	_tcp      5         0       443   mx.okdeb.com

# Autoconfig needs the path http://autoconfig.okdeb.com/mail/config-v1.1.xml

/etc/apache2/sites-available/mx.okdeb.conf
# ---
  ServerAlias autoconfig.okdeb.com
  ServerAlias autodiscover.okdeb.com

  # autoconfig
  Alias /mail "/var/www/okdeb/mail"
# ---

# I generated a new cert for autoconfig and autodiscover but this isn't 
# necessary because autoconfig doesn't use https and autodiscover uses the 
# domain to points to, mx.okdeb.com which already has a cert. Autodiscover needs 
# the path https://okdeb.com/Autodiscover/Autodiscover.xml.

nano /etc/apache2/sites-available/ssl-mx.okdeb.conf

   # probably don't need the ServerAlias and if needed we'd need to update the cert
   # ServerAlias autodiscover.okdeb.com

    Alias /mail "/var/www/okdeb/mail"
    Alias "/Autodiscover/Autodiscover.xml" "/var/www/okdeb/mail/Autodiscover.xml/index.php"
    <Directory /var/www/okdeb/mail/>
        DirectorySlash Off
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

apachectl restart

# Confirm these files can be accessed by http and https and output xml.

http://mx.okdeb.com/mail/config-v1.1.xml
https://mx.okdeb.com/Autodiscover/Autodiscover.xml

# Test it by removing the account in Thunderbird and adding it back. If it is 
# working properly it should configure quickly with mx.okdeb.com. If 
# Thunderbird said it is testing well known server names, takes a while, and 
# comes up with mail.okdeb.com then autoconfig is not working properly and check
# your apache configuration and paths. See the readme in /tmp/email-autoconfig-php.

# Caution! Thunderbird caches data! When testing, delete the relevant outgoing 
# server(s), delete the relevant mail account(s) in Thunderbired, go to Tools -> 
# Clear Recent History and delete everything, close and restart Thunderbird.

# Then add the account(s) back as new to test again.

# Next we will install PostfixAdmin

03 Postfix SMTPD <- Intro -> 05 PostfixAdmin