Zum Inhalt

Postfix als Mailserver mit Dovecot und PostfixAdmin

Stand: 10/2025
Postfix-logo
Verwendete Software
- Ubuntu 24.04 LTS
- Postfix 3.8.6
- PostfixAdmin 3.3.15
- Dovecot 2.3.21
- MariaDB 11.4.5
- Apache 2.4.58
- PHP 8.4
- Fail2ban 1.0.2
Weitere Dokumentationen:
- SPF, DKIM und DMARC in Postfix einrichten
- Postfix als Relayhost (Smarthost)
- SpamAssassin in Postfix einrichten

Vorwort

Diese Dokumentation beschreibt den Installationsvorgang eines Mailservers mit Postfix als SMTP-Server, Dovecot als IMAP-Server und PostfixAdmin als Administrations-Webinterface.
Sie eignet sich für alle, die einen professionellen Mailserver auf Ubuntu betreiben möchten. Fokus liegt auf Sicherheit, Transparenz und technischer Eleganz.


graph TD
  subgraph Webinterface
    Apache["Apache Webserver"]
    PostfixAdmin["PostfixAdmin"]
  end

  subgraph Mailserver
    Postfix["Postfix (SMTP)"]
    Dovecot["Dovecot (IMAP)"]
  end

  subgraph Datenbank
    MariaDB[(MariaDB)]
  end

  subgraph Server
    Webinterface
    Mailserver
    Datenbank
  end

  Webinterface -->Datenbank
  Mailserver -->Datenbank

    User1(E-Mail Admin)
    User2(E-Mail Client)
User1 -->|Administration|Webinterface
User2 -->|E-Mails senden/empfangen|Mailserver


Es sind Grundkenntnisse im Umgang mit Linux erforderlich, da die Vorgehensweise, wie sie hier beschrieben ist, in manchen Teilen abweichen kann. Kein System ist wie das Andere. Die Dokumentation wurde sorgfältig von mir geprüft. Dennoch kann ich keinerlei Haftung für Schäden an Ihrem System oder eine Gewährleistung übernehmen. Bitte verwenden Sie diese Dokumentation auf eigene Gefahr.


Was muss ich in der Konfiguration anpassen?

Einige Parameter müssen auf Ihre Umgebung angepasst werden. Im Verlauf dieser Dokumentation müssen Sie nur die Parameter anpassen, die in der nachfolgenden Tabelle aufgelistet sind. Sie können also ganz einfach durch die Funktion "Suchen und Ersetzen" (STRG + H), die Konfigurationsdateien auf Ihre Umgebung anpassen. Das Gleiche gilt für auszuführende Kommandos.

Folgende Parameter werden verwendet:

Wert Hinweis
Hostname mailserver.example.com Ersetzen Sie diesen Wert durch den FQDN Ihres Servers.
IPv4-Adresse 192.0.2.42 Ersetzen Sie diesen Wert durch die öffentliche IPv4-Adresse Ihres Servers.
IPv6-Adresse (falls vorhanden) 2001:db8:0:8d3:0:8a2e:70:7344 Ersetzen Sie diesen Wert, durch die öffentliche IPv6-Adresse Ihres Servers.
Domain example.com Ersetzen Sie diesen Wert durch Ihre Domain.
SSL
SSL-Zertifikat /etc/letsencrypt/live/mailserver.example.com/fullchain.pem Ersetzen Sie diesen Wert durch den Pfad und den Namen Ihres SSL-Zertifikats.
SSL-Zertifikat Private Key /etc/letsencrypt/live/mailserver.example.com/privkey.pem Ersetzen Sie diesen Wert durch den Pfad und den Namen des private Keys Ihres SSL-Zertifikats.
MySQL
root SicheresRootPasswortVerwenden! MySQL-Passwort für den Benutzer root. Ersetzen Sie dieses Passwort durch ein eigenes sicheres Passwort.
postfix SicheresRootPasswortVerwenden! MySQL-Passwort für den Benutzer postfix. Ersetzen Sie dieses Passwort durch ein eigenes sicheres Passwort.
E-Mail-Adressen
Test-Benutzer [email protected] Dieser Benutzer wird im Laufe der Dokumentation erstellt.
Root-E-Mail-Adresse [email protected] Ersetzen Sie diesen Wert durch die E-Mail-Adresse desjenigen, der E-Mails für Root erhalten soll.
Fail2ban-E-Mail-Adresse (Absender) [email protected] Absender-Adresse für den Dienst Fail2ban. Passen Sie hier einfach nur die Mail-Domain an.



Konfigurations-Dateien werden immer nach dem gleichen Muster erstellt. Unter jeder Datei, die eine Anpassung erfordert, finden Sie die nötigen Hinweise.
Dateien, die zwar Parameter aber keine eigentliche Konfiguration enthalten, werden nach dem vorgegebenen Syntax erstellt.

Beispiel:
Im folgenden Beispiel ist die Datei /home/beispiel.conf zu erstellen und der Parameter domain anzupassen.

Erstellen Sie eine neue Datei /home/beispiel.conf mit folgendem Inhalt:

nano /home/beispiel.conf
beispiel.conf
content = Dokumentationen

domain  = example.com
owner   = root
Anzupassende Parameter:
[...]
domain  = example.com
[...]


Im folgenden Beispiel ist die Datei /home/beispiel.map mit einer Liste Ihrer E-Mail-Adressen zu erstellen.

Erstellen Sie eine neue Datei /home/beispiel.map nach folgendem Syntax:
nano /home/beispiel.map



Server vorbereiten

Root-Rechte einräumen

Während der gesamten Dokumentation werden Root-Rechte benötigt. Um auf das Voranstellen von sudo zu verzichten, verschaffen Sie sich für die gesamte Sitzung erhöhte Rechte mit:

sudo -i

Update durchführen

Bringen Sie den Server auf den aktuellen Patchstand:

apt update && apt upgrade

Hostname vergeben

Vergeben Sie den hostname und den mailname:

hostnamectl set-hostname mailserver
cat /etc/hostname > /etc/mailname

Editieren Sie die Datei /etc/hosts und ändern Sie den Hostnamen nach folgendem Syntax:
nano /etc/hosts
/etc/hosts
127.0.1.1       mailserver.example.com mailserver
[...]


Software herunterladen und installieren

Da PHP 8.4 nicht im offiziellen Ubuntu-Repository von Ubuntu 24.04 enthalten ist, fügen wir zunächst das bewährte Drittanbieter-Repository ppa:ondrej/php hinzu:

apt install apt-transport-https
LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php
apt update


Auch die aktuelle Version von MariaDB ist noch nicht im Ubuntu-Repository von Ubuntu 24.04 enthalten. Fügen Sie daher das MariaDB-Repository hinzu:

curl -LsS https://r.mariadb.com/downloads/mariadb_repo_setup | sudo bash -s -- --mariadb-server-version="mariadb-11.4"
apt update


Installieren Sie Postfix, Dovecot, MariaDB, Apache mit PHP und Fail2ban:

apt install apt install postfix postfix-mysql postfix-pcre dovecot-core dovecot-imapd dovecot-mysql dovecot-managesieved dovecot-sieve mariadb-server apache2 libapache2-mod-php8.4 php8.4 php8.4-mysql php8.4-mbstring php8.4-imap fail2ban whois


Wählen Sie im Fenster Postfix Configuration Internet-Site aus und bestätigen Sie mit der Enter-Taste:

Postfix Setup

Im nächsten Fenster ist keine Anpassung erforderlich (der Parameter wird im weiteren Verlauf der Dokumentation angepasst). Bestätigen Sie das Fenster einfach mit der Enter-Taste:

Postfix Setup



Benutzer und Ordner für Virtual-Transport anlegen

Erstellen Sie einen Benutzer, der Zugriff auf alle lokalen Mailboxen hat:

groupadd -g 5000 vmailer
useradd -s /usr/sbin/nologin -u 5000 -g 5000 vmailer

Erstellen Sie einen Ordner für den virtuellen E-Mail-Transport und einen Ordner für gelöschte Mailboxen. Vergeben Sie anschließend die Zugriffsrechte für die Ordner:
mkdir /var/spool/mail/virtual
mkdir /var/spool/mail/virtual/deleted-maildirs
chown -R vmailer:vmailer /var/spool/mail/virtual


MariaDB konfigurieren

Vergeben Sie ein Root-Passwort und die Zugriffsrechte für den MySQL-Server.
Ersetzen Sie SicheresRootPasswortVerwenden! durch ein eigenes Passwort.

mysql_secure_installation
    [...]
    Enter current password for root (enter for none): "Enter"
    [...]
    Switch to unix_socket authentication [Y/n] n
    [...]
    Change the root password? [Y/n] :y
    New password: SicheresRootPasswortVerwenden!
    Re-enter new password: SicheresRootPasswortVerwenden!
    [...]
    Remove anonymous users? [Y/n] :y
    [...]
    Disallow root login remotely? [Y/n] :y
    [...]
    Remove test database and access to it? [Y/n] :y
    [...]
    Reload privilege tables now? [Y/n] :y
    [...]
    Thanks for using MariaDB!

Info

Da wir im vorherigen Schritt die klassische Passwort-Authentifizierung für den Benutzer root eingerichtet haben, ist die Anmeldung an der MySQL-Konsole aktuell nur mit Passwort möglich.
Wenn Sie stattdessen die passwortlose Unix-Socket-Authentifizierung aktivieren möchten – also eine Anmeldung per sudo mysql ohne Passwort – führen Sie folgende Befehle aus:

sudo mysql -u root -p
    MariaDB [(none)]> ALTER USER 'root'@'localhost' IDENTIFIED VIA unix_socket;
    MariaDB [(none)]> FLUSH PRIVILEGES;
Prüfen Sie, ob die Änderung erfolgreich übernommen wurde:
    MariaDB [(none)]> SELECT user, host, plugin FROM mysql.user WHERE user = 'root';
    +------+-----------+-------------+
    | user | host      | plugin      |
    +------+-----------+-------------+
    | root | localhost | unix_socket |
    +------+-----------+-------------+
    [...]
    MariaDB [(none)]> QUIT;

Ab jetzt erfolgt die Anmeldung zur MySQL-Konsole ausschließlich über das Betriebssystem – das heißt, nur Benutzer mit Root-Rechten (z.B. per sudo) können darauf zugreifen. Eine weitere Passwort-Eingabe ist nicht mehr erforderlich, unberechtigter Zugriff durch normale Benutzer aber weiterhin ausgeschlossen.

sudo mysql



TLS-Verschlüsselung einrichten

Der Mailserver soll zum Einen verhindern, dass bei der Authentifizierung der Benutzername und das Passwort im Klartext übertragen wird und zum Anderen die Möglichkeit bieten, E-Mails verschlüsselt zu empfangen. Mittlerweile nutzen die meisten Mailserver die TLS-Verschlüsselung. Mailservern, die immer noch kein STARTTLS unterstützen, räumt der Mailserver dennoch den unverschlüsselten Übertragungsweg ein. Das ist leider gängige Praxis, die auch in dieser Dokumentation berücksichtigt wird.


Let's Encrypt-Zertifikat erstellen

Info

Um den Mailserver mit STARTTLS zu verwenden, muss ein SSL-Zertifikat erstellt werden. Das SSL-Zertifikat wird auch für die Verschlüsselung des Webinterfaces von PostfixAdmin und Dovecot verwendet. Dieses kann entweder bei einer offiziellen Zertifizierungsstelle gekauft oder kostenlos über Let's Encrypt bezogen werden.

Für die reine Transportverschlüsselung STARTTLS sind kostenlos ausgestellte Zertifikate von Let's Encrypt und kostenpflichtige Zertifikate technisch gleichwertig, solange sie von einer vertrauenswürdigen CA stammen und gültig sind. Die meisten modernen Mailserver akzeptieren beide Varianten problemlos.

Wenn keine besonderen Anforderungen bestehen (z.B. erweiterte Validierung oder längere Laufzeit ohne Erneuerung), empfiehlt sich die Verwendung eines kostenlosen Let's-Encrypt-Zertifikats. Diese lassen sich automatisiert verwalten und decken in der Praxis alle gängigen Anforderungen ab.


Installieren Sie zunächst snapd und certbot:

apt update
apt install snapd
snap install core
snap refresh core
snap install --classic certbot
ln -s /snap/bin/certbot /usr/bin/certbot


Erstellen Sie das Zertifkat. Geben Sie als Common Name den FQDN des Mailservers an.
Das Zertifkat befindet sich unter /etc/letsencrypt/live/mailserver.example.com/.

sudo certbot certonly --apache -d mailserver.example.com


Let's Encrypt-Zertifikate haben eine Gültigkeit von 30 Tagen. Danach werden sie automatisch erneuert. Damit apache, postfix und dovecot erneuerte Zertifikate verwenden, müssen diese nachgeladen werden. Erstellen Sie hierzu einen Deploy-Hook:

nano /etc/letsencrypt/renewal-hooks/deploy/reload-services.sh

reload-services.sh
#!/bin/bash
services=(
    apache2
    postfix
    dovecot
)

for service in "${services[@]}"; do
    if systemctl is-active --quiet "$service"; then
        echo "[Certbot-Hook] Reloading $service"
        systemctl reload "$service"
    else
        echo "[Certbot-Hook] $service is not active"
    fi
done


Vergeben Sie die benötigte Berechtigung, damit die Datei ausgeführt werden kann:

chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-services.sh




Diffie-Hellman-Parameter erstellen

Info

Der Diffie-Hellman-Schlüsselaustausch gehört zu den asymmetrischen Kryptoverfahren und basiert auf der diskreten Exponentialfunktion. Dafür sind zwei Parameter notwendig:
Der erste Parameter ''p'' besteht aus einer grossen Primzahl und der Zweite gibt den sogenannten Generator-Wert ''g'' an (bei OpenSSL ist dieser Wert "2").
Beide Parameter werden anschließend in einer Datei abgelegt.

Da die, in RFC 2409 empfohlene, Schlüssellänge von 1024 Bit als nicht mehr sicher gilt, generieren wir die Parameter mit einer Schlüssellänge von 4096 Bit ("4096-bit MODP Group" gemäß RFC 3526.

In unserem Setup stellen wir die DH-Parameter formal für die TLS-Verschlüsselung via STARTTLS in Postfix bereit.

Den entsprechden Parameter finden Sie später in der Datei /etc/postfix/main.cf:

main.cf
[...]
#TLS
#############################################################
[...]
smtpd_tls_dh1024_param_file     = /etc/ssl/private/dh4096.pem
[...]

Hinweis!

In TLS 1.2 und 1.3 ist die Verwendung klassischer DH-Parameter technisch nicht mehr notwendig. TLS 1.3 ignoriert sie vollständig, und TLS 1.2 verwendet sie nur, wenn DHE-Cipher aktiv verhandelt werden. Der Parameter wird in dieser Konfiguration lediglich aus Kompatibilitätsgründen mit potenziell veralteten Gegenstellen eingebunden. Bei Einsatz moderner Cipher Suites (z.B. ECDHE) kommt er nicht zum Tragen. Eine regelmäßige Neuerzeugung ist nicht erforderlich, sofern ein starker Parameter (z. B. 4096 Bit) einmalig erzeugt wurde.


Erstellen Sie die Diffie-Hellman-Parameter im Ordner /etc/ssl/private:

cd /etc/ssl/private
openssl dhparam -out dh4096.tmp 4096 && mv dh4096.tmp dh4096.pem
chmod 600 dh4096.pem



Apache konfigurieren

Info

Informationen, die über das Webinterface von PostfixAdmin eingegeben werden, sollen selbstverständlich verschlüsselt übertragen werden.
Daher wird in dieser Apache-Konfiguration festgelegt, dass Verbindungen über http automatisch auf https umgeleitet werden.

  • /etc/apache2/sites-available/new-default.conf
    new-default.conf
    [...]
            #Weiterleitung von HTTP zu HTTPS
            RewriteEngine On
            RewriteCond %{HTTPS} !=on
            RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
    [...]
    

Zusätzlich stellen wir, dass Apache keine technischen Details wie Versionsnummern oder das verwendete Betriebssystem preisgibt. Die Standardkonfiguration setzt dies leider nicht voraus.

  • /etc/apache2/conf-available/security.conf
    security.conf
    [...]
    ServerTokens Prod
    [...]
    ServerSignature Off
    [...]
    


Default-Site einrichten

Deaktivieren Sie die Default-Site:

a2dissite 000-default.conf

Löschen Sie den Ordner html inkl. der Default-index.php:

rm -R /var/www/html

Erstellen Sie eine neue Datei /etc/apache2/sites-available/new-default.conf mit folgendem Inhalt:
nano /etc/apache2/sites-available/new-default.conf
new-default.conf
<VirtualHost *:80>
    ServerName example.com
    ServerAdmin [email protected]

    DocumentRoot /var/www

    #Weiterleitung von HTTP zu HTTPS
    RewriteEngine On
    RewriteCond %{HTTPS} !=on
    RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]

    LogLevel warn
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Anzupassende Parameter:
[...]
ServerName example.com
ServerAdmin [email protected]
[...]


Default-SSL-Site einrichten

Erstellen Sie eine neue Datei /etc/apache2/sites-available/new-default-ssl.conf mit folgendem Inhalt:

nano /etc/apache2/sites-available/new-default-ssl.conf
new-default-ssl.conf
<IfModule mod_ssl.c>
    <VirtualHost _default_:443>
        ServerName example.com
        ServerAdmin [email protected]

        DocumentRoot /var/www

        # Aktivieren Sie diese Option, wenn Sie ein offiziell siginiertes SSL-Zertifikat verwenden und Zugriffe ausschliesslich über SSL stattfinden.
        #Header always set Strict-Transport-Security "max-age=31556926; includeSubDomains"

        SSLEngine on
        SSLCompression Off
        SSLHonorCipherOrder on
        SSLProtocol -ALL +TLSv1.2 +TLSv1.3
        SSLCipherSuite EECDH+AESGCM:EECDH+CHACHA20:HIGH:!aNULL:!MD5:!3DES:!RC4:!SHA1:!CAMELLIA:!SEED:!EDH:!DSS
        SSLOpenSSLConfCmd Curves X25519:secp521r1:secp384r1:prime256v1

        SSLCertificateFile /etc/letsencrypt/live/mailserver.example.com/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/mailserver.example.com/privkey.pem

        LogLevel warn
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
    </VirtualHost>
</IfModule>
Anzupassende Parameter:
[...]
        ServerName example.com
        ServerAdmin [email protected]
[...]
        # Nur anpassen, wenn Sie ein anderes Zertifikat verwenden!
        SSLCertificateFile /etc/letsencrypt/live/mailserver.example.com/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/mailserver.example.com/privkey.pem
[...]


Apache härten

Editieren Sie die Datei /etc/apache2/conf-available/security.conf und ändern Sie folgende Parameter:

nano /etc/apache2/conf-available/security.conf
Anzupassende Parameter:
[...]
ServerTokens Prod
[...]
ServerSignature Off
[...]
oder verwenden Sie folgende Regex:

  • ServerTokens aktiv setzen oder anhängen, wenn nicht vorhanden

    grep -q '^ServerTokens' /etc/apache2/conf-available/security.conf && \
        sudo sed -i 's/^ServerTokens .*/ServerTokens Prod/' /etc/apache2/conf-available/security.conf || \
        echo 'ServerTokens Prod' | sudo tee -a /etc/apache2/conf-available/security.conf
    

  • Dasselbe für ServerSignature

    grep -q '^ServerSignature' /etc/apache2/conf-available/security.conf && \
        sudo sed -i 's/^ServerSignature .*/ServerSignature Off/' /etc/apache2/conf-available/security.conf || \
        echo 'ServerSignature Off' | sudo tee -a /etc/apache2/conf-available/security.conf
    


Aktivieren Sie die Module ssl und rewrite, die neuen Sites und starten Sie Apache neu:

a2enmod ssl rewrite
a2ensite new-default.conf new-default-ssl.conf
service apache2 restart


PostfixAdmin herunterladen und installieren

Laden Sie PostfixAdmin bei GitHub herunter und entpacken Sie das Archiv in den Ordner/usr/share/:

wget https://github.com/postfixadmin/postfixadmin/archive/refs/tags/postfixadmin-3.3.15.tar.gz
tar -xzf postfixadmin-3.3.15.tar.gz -C /usr/share/

Benennen Sie den entpackten Ordner postfixadmin-postfixadmin-3.3.15 in postfixadmin um:

 mv /usr/share/postfixadmin-postfixadmin-3.3.15/ /usr/share/postfixadmin


Erstellen Sie einen neuen Ordner /usr/share/postfixadmin/templates_c und vergeben Sie die entsprechenden Zugriffsrechte:

mkdir /usr/share/postfixadmin/templates_c
chown -R www-data:www-data /usr/share/postfixadmin/templates_c

Erstellen Sie eine Verknüpfung im Ordner /var/www:
ln -s /usr/share/postfixadmin/public /var/www/postfixadmin


Datenbank für Postfix einrichten

Verbinden Sie sich mit dem MySQL-Server:

mysql -u root -p

Erstellen Sie eine Datenbank postfix und einen Benutzer postfix. Räumen Sie dem Benutzer die benötigten Rechte ein.
Ersetzen Sie SicheresPasswortVerwenden! durch ein eigenes Passwort.
CREATE DATABASE postfix;
CREATE USER 'postfix'@'localhost' IDENTIFIED BY 'SicheresPasswortVerwenden!';
GRANT ALL PRIVILEGES ON `postfix` . * TO 'postfix'@'localhost';
FLUSH PRIVILEGES;
QUIT;

Skripte für gelöschte Mailboxen anlegen

Info

Damit gelöschte Mailboxen bzw. Domains nicht nur aus der Datenbank sondern auch aus der Verzeichnis-Struktur entfernt werden, müssen nach dem Löschvorgang im Webinterface, zwei Skripte ausgeführt werden. Die Skripte werden von PostfixAdmin automatisch nach dem Löschvorgang aufgerufen.
Die Mailboxen bzw. die Domains werden durch die Skripte erstmal nicht gelöscht, sondern in das Verzeichnis /var/spool/mail/virtual/deleted-maildirs verschoben und mit einem Timestamp versehen. Ein Cron-Job sorgt dafür, dass die Mailboxen, 30 Tage nach Löschung, endgültig vom Dateisystem entfernt werden.

  • Skript postfixadmin-mailbox-postdeletion.sh sorgt dafür, dass gelöschte Mailboxen verschoben und mit einem Timestamp versehen werden.

  • Skript postfixadmin-domain-postdeletion.sh sorgt dafür, dass nach Löschung einer Domain, alle, zu dieser Domain gehörenden Mailboxen, verschoben und mit einem Timespamp versehen werden.

  • Skript postfixadmin-cleanup-deleted-maildirs wird als täglicher Cron-Job ausgeführt und sorgt dafür, dass gelöschte Mailboxen bzw. Domains, 30 Tage nach deren Löschung endgültig aus dem Dateisystem entfernt werden. Die Anzahl der Tage, die ein gelöschtes Objekt noch aufbewahrt werden soll, kann angepasst werden. Ändern Sie dazu den folgenden Parameter:

    # postfixadmin-cleanup-deleted-maildirs
    [...]
    # Days until deletion
    days='30'
    [...]
    



Kopieren Sie die Skripte postfixadmin-mailbox-postdeletion.sh und postfixadmin-domain-postdeletion.shin den Ordner /usr/local/bin.

cp /usr/share/postfixadmin/ADDITIONS/postfixadmin-mailbox-postdeletion.sh /usr/local/bin/
cp /usr/share/postfixadmin/ADDITIONS/postfixadmin-domain-postdeletion.sh /usr/local/bin/

Editieren Sie beide Dateien und ändernd Sie die Parameter basedir und trashbase.
nano /usr/local/bin/postfixadmin-mailbox-postdeletion.sh
[...]
basedir=/var/spool/mail/virtual
[...]
trashbase=/var/spool/mail/virtual/deleted-maildirs
[...]

nano /usr/local/bin/postfixadmin-domain-postdeletion.sh
[...]
basedir=/var/spool/mail/virtual
[...]
trashbase=/var/spool/mail/virtual/deleted-maildirs
[...]

Vergeben Sie die benötigte Berechtigung, damit die Datei ausgeführt werden kann:
chmod +x /usr/local/bin/postfixadmin-*


Info

Die Skripte werden über das Webinterface, also mit dem Benutzer www-data, aufgerufen. Da dieser Benutzer zum einen keine Schreibrechte im Ordner /var/spool/mail/virtual und zum anderen keine Berechtigung zum Ausführen des Befehls sudo hat, müssen ihm entsprechende Rechte eingeräumt werden.
In der nachfolgenden Datei ermöglichen wir es dem Benutzer www-data, die beiden Skripte (und zwar nur diese Beiden!) als Benutzer vmailer auszuführen.
(sudo -u vmailer SKRIPT.sh)


Erstellen Sie die Datei /etc/sudoers.d/postfixadmin mit folgendem Inhalt:

nano /etc/sudoers.d/postfixadmin
www-data ALL=(vmailer) NOPASSWD: /usr/local/bin/postfixadmin-domain-postdeletion.sh
#end (Zeile unbedingt mitkopieren! Sonst funktioniert die Datei nicht.)

Schränken Sie die Zugriffsrechte auf die Datei ein:
chmod 440 /etc/sudoers.d/postfixadmin


Erstellen Sie die Datei /etc/cron.daily/postfixadmin-cleanup-deleted-maildirs mit folgendem Inhalt:
nano /etc/cron.daily/postfixadmin-cleanup-deleted-maildirs
postfixadmin-cleanup-deleted-maildirs
#!/bin/sh
#
#            ___________       .__.__  .__       .__     __
#            \__    ___/_  _  _|__|  | |__| ____ |  |___/  |_
#              |    |  \ \/ \/ /  |  | |  |/ ___\|  |  \   __\
#              |    |   \     /|  |  |_|  / /_/  >   Y  \  |
#              |____|    \/\_/ |__|____/__\___  /|___|  /__|
#                                        /_____/      \/
#
#  Twilight-Networks ∙ est. 2k1 ∙ fxp ∙ h4x ∙ nfo ∙ scene ∙ legacy lives
#  Keep it lean, keep it silent. Code like it's 2002.
#
#########################################################################
# Script Name   : postfixadmin-cleanup-deleted-maildirs
# Description   : Removes deleted-maildirs from Filesystem after X days
#                 Runs automatically by a Cron-Job
#
# Version       : 1.01
# Last Update   : 05.04.2025
# Author        : Twilight
# Contact       : [email protected]
# Web:          : https://www.twilight-networks.com
#
# Tested with   : Ubuntu 24.04 LTS
#
#########################################################################


# Config

# Deleted-Maildirs-Folder
dir='/var/spool/mail/virtual/deleted-maildirs'
# Days until deletion
days='30'


# Below this line: scene code. You break it, you bought it.
#########################################################################

find $dir -type d -name "*[0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9]*" -exec sh -c 'days='$days' fdate=$(basename ${1%\_*\_*});\
 [ "$fdate" "<" "$(date +%F -d "$days days ago")" ] && rm -R "$1"' find-sh {} > /dev/null 2>&1 \;

exit 0
#end

Vergeben Sie die benötigte Berechtigung, damit die Datei ausgeführt werden kann:
chmod +x /etc/cron.daily/postfixadmin-cleanup-deleted-maildirs


PostfixAdmin konfigurieren

Info

Die Konfiguration von PostfixAdmin wird in der Datei config.inc.php festgelegt. In dieser Datei sind alle möglichen Parameter enthalten und kommentiert.
Nach einem Update von PostfixAdmin wird diese Datei allerdings überschrieben und die Konfiguration muss neu erstellt werden. Einstellungen, die in der Datei config.local.php definiert werden, haben Vorang gegenüber der config.inc.php. Wir nutzen daher für unsere Konfiguration eine config.local.php.


Erstellen Sie die Datei /usr/share/postfixadmin/config.local.php mit folgendem Inhalt:

nano /usr/share/postfixadmin/config.local.php
config.local.php
<?php
# Datenbank-Verbindung
$CONF['database_type'] = 'mysqli';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'postfix';
$CONF['database_password'] = 'SicheresPasswortVerwenden!';
$CONF['database_name'] = 'postfix';

# Pflicht-Aliase nach RFC 2142 und RFC 2821
$CONF['default_aliases'] = array (
'abuse' => '[email protected]',
'hostmaster' => '[email protected]',
'postmaster' => '[email protected]',
'webmaster' => '[email protected]'
);

# Quota in Mbyte
$CONF['quota'] = 'YES';
$CONF['used_quotas'] = 'YES';
$CONF['aliases'] = '10';
$CONF['mailboxes'] = '10';
$CONF['maxquota'] = '10';
$CONF['domain_quota_default'] = '2048';

# Sonstiges
$CONF['configured'] = true;
$CONF['show_footer_text'] = 'NO';

$CONF['mailbox_postdeletion_script']='sudo -u vmailer /usr/local/bin/postfixadmin-mailbox-postdeletion.sh';
$CONF['domain_postdeletion_script'] = 'sudo -u vmailer /usr/local/bin/postfixadmin-domain-postdeletion.sh';
?>
Anzupassende Parameter:
[...]
$CONF['database_password'] = 'SicheresPasswortVerwenden!';
[...]
# Geben Sie hier den Empfänger der Pflicht-Aliase an.
$CONF['default_aliases'] = array (
    'abuse' => '[email protected]',
    'hostmaster' => '[email protected]',
    'postmaster' => '[email protected]',
    'webmaster' => '[email protected]'
[...]
# Default-Werte pro Domain. Quota in Mbyte.
$CONF['aliases'] = '10';
$CONF['mailboxes'] = '10';
$CONF['maxquota'] = '10';
$CONF['domain_quota_default'] = '2048';
[...]

Starten Sie den Dienst Apache neu:
service apache2 restart

  • Rufen Sie das Setup von PostfixAdmin im Webinterface auf und kontrollieren Sie, ob alle Tests erfolgreich verliefen.
    Generieren Sie den Passwort-Hash, indem Sie ein neues Setup-Passwort vergeben und auf Generate setup_password hash klicken:
    https://mailserver.example.com/postfixadmin/setup.php
    
    PostfixAdmin Setup


  • Kopieren Sie die Zeile $CONF['setup_password'] = '$2y$12$PfBwe5SHq[...]pOW3uHgIhZ1bNdnO'; und fügen Sie diese in die Datei /usr/share/postfixadmin/config.local.php ein und aktualisieren Sie anschließend die Webseite mit F5.
    nano /usr/share/postfixadmin/config.local.php
    
    config.local.php
    <?php
    [...]
    $CONF['setup_password'] = '$2y$12$PfBwe5SHq[...]pOW3uHgIhZ1bNdnO';
    ?>
    

    PostfixAdmin Setup


  • Melden Sie sich mit dem setup_passwordan:

    PostfixAdmin Setup


  • Erstellen Sie einen Superadmin-Account:

    PostfixAdmin Setup


  • Sie erhalten eine Bestätigung:

    PostfixAdmin Setup


  • Prüfen Sie, ob Sie sich mit dem neuen Admin einloggen können:
    https://mailserver.example.com/postfixadmin/login.php
    
    PostfixAdmin Login


Postfix MySQL-Dateien anlegen

Info

Postfix muss wissen, in welchen Tabellen und Spalten der Postfix-Datenbank, die Informationen zu den verwendeten Domain(s) und Postfächern zu finden sind. Für jede Abfrage muss eine eigene Datei erstellt werden.
Möchte Postfix z.B. wissen für welche Domain(s) er zuständig ist, führt er die Abfrage in der Datei mysql_virtual_domains_maps.cf aus.

Die Standard-SQL-Dateien können mit einem mitgelieferten Skript von PostfixAdmin generiert werden.
Für unser Setup benötigen wir aber zusätzlich noch das Sender-Login-Mapping. Diese Datei erstellen wir manuell.


Generieren Sie die MySQL-Dateien für Postfix mit dem Script POSTFIX_CONF.txt.
Ersetzen Sie SicheresPasswortVerwenden! durch das von Ihnen gewählte Passwort.

sh /usr/share/postfixadmin/DOCUMENTS/POSTFIX_CONF.txt
    /tmp/postfixadmin-I5MG0h
    Database host? (often localhost)
    localhost
    Database name?
    postfix
    Database user?
    postfix
    Database password?
    SicheresPasswortVerwenden!
    Config files have been written to /tmp/postfixadmin-I5MG0h. Please check their content and move them to /etc/postfix/sql/.
    Do not forget to edit /etc/postfix/main.cf as described in /usr/share/postfixadmin/DOCUMENTS/POSTFIX_CONF.txt.

Achtung!

Achten Sie auf die Ausgabe von POSTFIX_CONF.txt (Config files have been written to /tmp/postfixadmin-I5MG0h**). Der temporäre Ort der Dateien kann von dieser Dokumentation abweichen.
In dem Fall muss der Befehl mv /tmp/postfixadmin-I5MG0h/mysql_virtual_* /etc/postfix/sql/ entsprechend angepasst werden.


Erstellen Sie einen neuen Ordner /etc/postfix/sql und verschieben Sie die MySQL-Dateien dorthin:

mkdir /etc/postfix/sql
mv /tmp/postfixadmin-I5MG0h/mysql_virtual_* /etc/postfix/sql/

Erstellen Sie die Datei /etc/postfix/sql/mysql_sender_login_maps.cf mit folgendem Inhalt:
nano /etc/postfix/sql/mysql_sender_login_maps.cf
mysql_sender_login_maps.cf
user = postfix
password = SicheresPasswortVerwenden!
hosts = localhost
dbname = postfix
query = SELECT username AS allowedUser FROM mailbox WHERE username="%s" AND active = 1 UNION SELECT goto FROM alias WHERE address="%s" AND active = 1
Anzupassende Parameter:
[...]
password = SicheresPasswortVerwenden!
[...]

Passen Sie die Zugriffsrechte auf die Dateien an:
chown root:postfix /etc/postfix/sql/*.cf
chmod 640 /etc/postfix/sql/*.cf


Postfix konfigurieren

master.cf anlegen

Info

In der Datei master.cf wird der sogennannte Master-Prozess konfiguriert. Der Master-Prozess ist die oberste Ebene der Postfix-Architektur und legt fest, wie andere, untergeordnete Prozesse (z.B. der smtpd-daemon) zu starten sind. Er ist die erste Anlaufstelle für eingehende Postfix-Aufgaben und delegiert diese an andere Prozesse weiter. Bei mehreren gleichartigen Aufgaben kann der Master-Prozess auch weitere Instanzen eines Prozesses starten.

Die Datei master.cf enthält nicht sehr viel Konfiguration und muss in den meisten Fällen auch nicht in grösserem Umfang angepasst werden.

Wir konfigurieren für unser Setup den smtpd-daemon mit dem Dienst submission. Das ist unser Dienst zum authentifizierten Versenden von E-Mails zu entfernten Mailservern (relaying). pipe-daemon mit dem Dienst dovecot als Schnittstelle zu unserem Dovecot-IMAP-Server. *cleanup-daemon mit dem Dienst submission-header_checks zur Bereinigung des E-Mail-Headers von ausgehenden E-Mails.



Benennen Sie zunächst die /etc/postfix/master.cf um, damit Sie eine Sicherheitskopie der Original-Datei haben:

mv /etc/postfix/master.cf /etc/postfix/master.cf.bak

Erstellen Sie eine neue Datei /etc/postfix/master.cf mit folgendem Inhalt:
nano /etc/postfix/master.cf
master.cf
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================
smtp      inet  n       -       n       -       -       smtpd

submission inet  n       -       n       -       -       smtpd
        -o smtpd_tls_security_level=encrypt
        -o smtpd_sasl_auth_enable=yes
        -o smtpd_client_restrictions=permit_sasl_authenticated,reject
        -o smtpd_helo_restrictions=permit_sasl_authenticated,reject
        -o smtpd_sender_restrictions=reject_sender_login_mismatch,permit_sasl_authenticated,reject
        -o smtpd_relay_restrictions=permit_sasl_authenticated,reject_unauth_destination
        -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
        -o cleanup_service_name=submission-header_checks

dovecot   unix  -       n       n       -       -       pipe
    flags=DRhu user=vmailer:vmailer argv=/usr/lib/dovecot/dovecot-lda -f ${sender} -d ${recipient}

submission-header_checks unix n - n    -       0       cleanup
        -o header_checks=pcre:${config_directory}/header_checks


pickup    unix  n       -       n       60      1       pickup
cleanup   unix  n       -       n       -       0       cleanup
qmgr      unix  n       -       n       300     1       qmgr
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
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

#
# ====================================================================


main.cf anlegen

Info

Die Datei main.cf ist die zentrale Konfigurations-Datei von Postfix. Sie enthält fast die gesamte Server-Konfiguration und kann sehr umfangreich werden. Es ist daher von grosser Bedeutung, die Datei übersichtlich zu gestalten.
Es würde den Umfang dieser Dokumentation sprengen, wenn ich auf die gesamte Konfiguration der main.cf eingehen würde. Alle Konfigurations-Parameter finden Sie auf der offiziellen Seite von Postfix.
Wir gehen aber auf die wichtigsten Parameter ein:

Abschnitt Host Configuration

In diesem Abschnitt definieren wir die globalen Parameter des Servers.

  • myhostname = mailserver.example.com
    Als Hostname geben wir den FQDN unseres Mailservers an. Über diesen Hostname wird der Server aus dem Internet zu erreichen sein.

  • mydomain = example.com
    Hier geben wir die Domain unseres Mailservers an. Wir geben die gleiche Domain an, die wir bereits bei myhostname verwenden. Die hier angebenen Domain muss nicht zwingend unsere Maildomain sein. Diese wird später an anderer Stelle definiert.

  • mailbox_size_limit = 0
    Der Parameter definiert die maximale Grösse einer einzelnen Mailbox. Also der Speicherplatz, der einem einzelnen Benutzer für sein Postfach zur Verfügung steht. In unserem Setup möchten wir die Quotierung über das Webinterface von PostfixAdmin steuern. Daher setzen wir den Wert auf 0 = unbegrenzt.

  • message_size_limit = 52428800
    Hier definieren wir die maximale Grösse einer einzelnen E-Mail (inkl. Anhang). Dieser Parameter kann nicht über PostfixAdmin gesteuert werden und wird deshalb fest vergeben. Wir lassen eine maximale Grösse von 50 MByte (52428800 Byte) zu. Natürlich können Sie diesen Wert auch anpassen. Die Formel für die Umrechnung von Mbyte in Byte lautet Mbyte * 1024 * 1024 = Byte.

Virtual Configuration

Die gesamte Benutzerverwaltung unseres Mailservers soll über die SQL-Datenbank von PostfixAdmin gesteuert werden. Wir möchten also keine lokalen Unix-Benutzer auf dem Mailserver anlegen, sondern mit virtuellen Benutzern arbeiten.
In diesem Abschnitt teilen wir Postfix mit, wie eingehende E-Mails zuzustellen sind und wo eingerichtete Benutzer, Aliase, usw. in der SQL-Datenbank zu finden sind.

  • virtual_transport = dovecot
    Eingehende E-Mails werden dem IMAP-Server zugestellt. Wir transportieren eingehende E-Mails also über den pipe-daemon dovecot, den wir in der Datei /etc/postfix/master.cf eingerichtet haben.

SMTPD Configuration

Der SMTPD-Daemon ist für eingehende E-Mails zuständig und wird in diesem Abschnitt konfiguriert.

  • smtpd_banner = $myhostname ESMTP Service Ready
    Bei Kontaktaufnahme antwortet der Mailserver zunächst mit einer sogenannten Opening- bzw. Welcome-Message, dem SMTP-Banner. Gemäß RFC 5321 muss der SMTP-Banner nur den Reply Code 220 und den Hostnamen enthalten. Der Reply Code wird von Postfix automatisch vorangestellt und muss daher nicht angegeben werden. Weitere Angaben sind optional. Standardmässig generiert Postfix einen SMTP-Banner, der nicht nur den Reply Code und den Hostnamen enthält, sondern Postfix gibt sich auch als solchen zu erkennen. Da wir einem möglichen Angreifer keinerlei Informationen über die von uns verwendete Software mitteilen möchten, passen wir den Parameter entsprechend an.

  • smtpd_delay_reject = yes
    Dieser Parameter sagt aus, dass eine E-Mail erst nach dem Kommando RCPT TO abgewiesen (reject) wird. Wenn also bei einer eingehenden E-Mail z.B. bereits das Kommando HELO zum Abweisen führen würde, wartet Postfix die nachfolgenden Kommandos erstmal ab. Wir können also im Fehlerfall nachvollziehen, an welchen Empfänger diese E-Mail adressiert war.

  • smtpd_recipient_limit = 16
    Hier definieren wir die maximale Anzahl an Empfängern, die eine eingehende E-Mail enthalten darf.
    Spammer versenden eine E-Mail oft gleichzeitig an unzählige Empfänger. Durch diesen Parameter setzen wir ein Limit. Natürlich können Sie auch diesen Wert entsprechend anpassen.

  • disable_vrfy_command = yes
    Über das Kommando SMTP VRFY kann ein sendender Mailserver feststellen, ob ein Empfänger auf dem empfangenden Mailserver existiert. Dieses Kommando wird von Spammern of dafür genutzt, gültige E-Mail-Adressen zu sammeln (E-Mail-Adress-Harvesting). Daher deaktivieren wir dieses Kommando.

  • smtpd_sender_login_maps = mysql:[...]
    Wir möchten, dass ein Benutzer unseres Mailservers nur die ihm zugeteilte E-Mail-Adresse (oder Alias) als Absender-Adresse verwenden darf. Hier geben wir den Ort der entprechenden SQL-Abfrage an.

SMTPD Restrictions

Der wichtigste Teil der Konfiguration sind die sogenannten SMTPD Restrictions. Diese regeln die Kommunikation zwischen Mailclient und Mailserver und legen fest, nach welchten Kriterien eine E-Mail anzunehmen oder abzulehnen oder ist.
Unser Mailserver läuft, so weit es für die Praxis Sinn macht, RFC-konform. Wir nehmen also nur E-Mails an, die den Kriterien der RFC 5321 entsprechen und versenden selber natürlich genauso.

Auch das Relay-Recht, also die Zustellung einer E-Mail an einen externen Mailserver wird innerhalb der SMTPD Restrictions geregelt.

smtpd_relay_restrictions =
    check_sender_access regexp:${config_directory}/add_x_envelope_from
    permit_mynetworks
    reject_unauth_destination
    reject_unauth_pipelining

TLS

Wir bieten STARTTLS mit sicherer Cipher Suite an. Klassischer Diffie-Hellman-Schlüsselaustausch wird ausschließlich zur Abwärtskompatibilität mit älteren Mailservern unterstützt.

  • smtp_tls_security_level = may
    Eingehende E-Mails können über STARTTLS verschlüsselt werden, müssen allerdings nicht. Das ist dem Umstand geschuldet, dass leider immer noch nicht alle Mailserver STARTTLS unterstützen. Würden wir STARTTLS grundsätzlich fordern, würden wir einige, legitime Mailserver ausschliessen. Das macht in der Praxis keinen Sinn.

  • smtpd_tls_auth_only = yes
    Die Authentifizierung muss in unserem Setup mit STARTTLS verschlüsselt sein. Wir übertragen keine Benutzernamen und Kennwörter im Klartext.

SASL Authentication

In unserem Setup deligieren wir die Benutzer-Authentifizierung an Dovecot. Dieser Abschnitt enthält daher wenig Konfiguration.

  • smtpd_sasl_type = dovecot
    Für die Benutzer-Authentifizierung wird Dovecot als SASL-Provider verwendet.

  • broken_sasl_auth_clients = yes
    Mit diesem Parameter aktivieren wir den Kompatiblitätsmodus für das Kommando SMTP AUTH, da manche Mailserver und E-Mail-Clients eine alte Version des Kommandos verwenden (z.B. Microsoft Outlook Express 4 und Microsoft Exchange 5.0).

Queue

In diesem Abschnitt konfigurieren wir die E-Mail-Warteschlange (Queue). Sie dient zur Zwischenspeicherung von E-Mails, bevor diese weiterverarbeitet werden. E-Mails verbleiben nicht ewig in der Warteschlange. Nach einer definierten Zeit, werden sie aus der Warteschlange entfernt und der Absender erhält eine entsprechende Bounce-Nachricht.

  • queue_run_delay = 300s
    Dieser Parameter gibt an, nach welcher Zeit die Warteschlange erneut nach nicht zustellbaren E-Mails durchsucht wird.

  • maximal_queue_lifetime = 7d
    E-Mails in der Warteschlange haben in unserem Setup eine Lebensdauer von 7 Tagen. Danach werden sie verworfen und der Absender informiert.

  • bounce_queue_lifetime = 5d
    Bounce-Nachrichten haben in unserem Setup eine Lebensdauer von 5 Tagen.

  • minimal_backoff_time = 300s
    Dieser Parameter gibt die Zeit an, die mindestens verstreichen muss, bis ein erneuter Zustellversuch für eine E-Mail durchgeführt wird.

  • maximal_backoff_time = 4000s
    Dieser Parameter gibt die Zeit an, die maximal verstreichen darf, bis ein erneuter Zustellversuch für eine E-Mail durchgeführt wird.


Löschen Sie die Datei /etc/postfix/main.cf:

rm /etc/postfix/main.cf

Erstellen Sie die Datei /etc/postfix/main.cf mit folgendem Inhalt:
nano /etc/postfix/main.cf
/etc/postfix/main.cf
# HOST CONFIGURATION
#########################################################################

myhostname                              = mailserver.example.com
mydomain                                = example.com
myorigin                                = $mydomain
mynetworks_style                        = host
inet_interfaces                         = all
inet_protocols                          = ipv4
mail_owner                              = postfix
setgid_group                            = postdrop
delay_warning_time                      = 4h
alias_maps                              = hash:/etc/aliases
alias_database                          = $alias_maps
local_transport                         = dovecot
local_recipient_maps                    = $virtual_mailbox_maps
config_directory                        = /etc/postfix
compatibility_level                     = 3.6

# maximale Mailboxgrösse in Byte (Wird durch PostfixAdmin-Quota geregelt, 0 = unbegrenzt)
mailbox_size_limit                      = 0
# maximale Nachrichtengrösse in Byte (50 MByte)
message_size_limit                      = 52428800


# VIRTUAL CONFIGURATION
#########################################################################

virtual_transport                       = dovecot

virtual_mailbox_domains                 = proxy:mysql:${config_directory}/sql/mysql_virtual_domains_maps.cf
virtual_alias_maps =
   proxy:mysql:${config_directory}/sql/mysql_virtual_alias_maps.cf,
   proxy:mysql:${config_directory}/sql/mysql_virtual_alias_domain_maps.cf,
   proxy:mysql:${config_directory}/sql/mysql_virtual_alias_domain_catchall_maps.cf
virtual_mailbox_maps =
   proxy:mysql:${config_directory}/sql/mysql_virtual_mailbox_maps.cf,
   proxy:mysql:${config_directory}/sql/mysql_virtual_alias_domain_mailbox_maps.cf


# SMTPD CONFIGURATION
#########################################################################

smtpd_banner                            = $myhostname ESMTP Service Ready
smtpd_helo_required                     = yes
smtpd_delay_reject                      = yes
smtpd_error_sleep_time                  = 1s
smtpd_soft_error_limit                  = 10
smtpd_hard_error_limit                  = 20
smtpd_recipient_limit                   = 16
smtpd_client_message_rate_limit         = 30
smtpd_client_connection_count_limit     = 100
smtpd_client_connection_rate_limit      = 100

smtp_helo_timeout                       = 60s

soft_bounce                             = no
disable_vrfy_command                    = yes
mime_header_checks                      = regexp:${config_directory}/mime_header_checks.regexp

smtpd_sender_login_maps                 = mysql:${config_directory}/sql/mysql_sender_login_maps.cf


#SMTPD Restrictions
#########################################################################

# Client
smtpd_client_restrictions =
    permit_mynetworks
    reject_unknown_client_hostname
    reject_unknown_reverse_client_hostname
    reject_unauth_pipelining

# HELO
smtpd_helo_restrictions =
    permit_mynetworks
    check_recipient_access hash:${config_directory}/roleaccount_exceptions
    reject_invalid_helo_hostname
    reject_unknown_helo_hostname
    reject_non_fqdn_helo_hostname
    check_helo_access pcre:/etc/postfix/helo_checks
    reject_unauth_pipelining

# MAIL FROM:<...>
smtpd_sender_restrictions =
    permit_mynetworks
    reject_non_fqdn_sender
    reject_unknown_sender_domain
    reject_unauth_pipelining

# RCPT TO:<...>
smtpd_relay_restrictions =
    check_sender_access regexp:${config_directory}/add_x_envelope_from
    permit_mynetworks
    reject_unauth_destination
    reject_unauth_pipelining

smtpd_recipient_restrictions =
    reject_unlisted_recipient
    check_policy_service unix:private/quota-status
    permit_mynetworks
    reject_unauth_pipelining

# DATA
smtpd_data_restrictions =
    reject_multi_recipient_bounce
    reject_unauth_pipelining


#TLS
#########################################################################

tls_eecdh_strong_curve                  = prime256v1
tls_eecdh_ultra_curve                   = secp384r1
tls_random_source                       = dev:/dev/urandom
tls_preempt_cipherlist                  = yes
tls_high_cipherlist                     = EECDH+AESGCM:EDH+AESGCM:EECDH+AES:EDH+AES
tls_medium_cipherlist                   = EECDH+AESGCM:EDH+AESGCM:EECDH+AES:EDH+AES
tls_low_cipherlist                      = EECDH+AESGCM:EDH+AESGCM:EECDH+AES:EDH+AES

smtp_tls_mandatory_protocols            = >=TLSv1.2
smtp_tls_protocols                      = >=TLSv1.2
smtp_tls_note_starttls_offer            = yes
smtp_tls_security_level                 = may

smtp_tls_session_cache_timeout          = 3600
smtp_tls_session_cache_database         = btree:/var/lib/postfix/smtp_scache

smtpd_tls_mandatory_protocols           = >=TLSv1.2
smtpd_tls_protocols                     = >=TLSv1.2
smtpd_tls_security_level                = may
smtpd_tls_auth_only                     = yes
smtpd_tls_received_header               = yes
smtpd_tls_mandatory_ciphers             = high
smtpd_tls_ciphers                       = high
smtpd_tls_eecdh_grade                   = strong
smtpd_tls_dh1024_param_file             = /etc/ssl/private/dh4096.pem

smtpd_client_new_tls_session_rate_limit = 60
smtpd_tls_session_cache_timeout         = 3600s
smtpd_tls_session_cache_database        = btree:/var/lib/postfix/smtpd_scache

smtpd_tls_key_file                      = /etc/letsencrypt/live/mailserver.example.com/privkey.pem
smtpd_tls_cert_file                     = /etc/letsencrypt/live/mailserver.example.com/fullchain.pem


#SASL Authentication
#########################################################################

smtpd_sasl_type                         = dovecot
smtpd_sasl_path                         = private/auth
smtpd_sasl_security_options             = noanonymous
smtpd_sasl_authenticated_header         = yes
broken_sasl_auth_clients                = yes


# Queue
#########################################################################

queue_run_delay                         = 300s
maximal_queue_lifetime                  = 7d
bounce_queue_lifetime                   = 5d
minimal_backoff_time                    = 300s
maximal_backoff_time                    = 4000s
qmgr_message_active_limit               = 10000
qmgr_message_recipient_limit            = 10000


# DEBUG CONFIGURATION
#########################################################################

smtp_tls_loglevel                       = 1
smtpd_tls_loglevel                      = 1
debug_peer_level                        = 2
Anzupassende Parameter:
myhostname      = mailserver.example.com
mydomain        = example.com
[...]
# Nur anpassen, wenn Sie ein anderes Zertifikat verwenden!
smtpd_tls_key_file      = /etc/letsencrypt/live/mailserver.example.com/privkey.pem
smtpd_tls_cert_file     = /etc/letsencrypt/live/mailserver.example.com/fullchain.pem
[...]


(Optional) IPv6-Unterstützung einrichten

Info

Wenn Ihr Server, zusätzlich zu IPv4, über einen IPv6-Uplink verfügt (Dual-Stack), spricht nichts dagegen, IPv6 auch mit Postfix zu nutzen.


Editieren Sie die Datei /etc/postfix/main.cf und passen Sie die folgenden Parameter an:

nano /etc/postfix/main.cf
Anzupassende Parameter:
[...]
mynetworks          = 127.0.0.0/8, [::1/128]
[...]
inet_protocols      = ipv4, ipv6
[...]


Falsche HELO-Hostnamen erkennen

Info

Um zu verhindern, dass Spam-Versender den Hostnamen Ihres Mailservers als ihren eigenen Hostnamen verwenden, erstellen wir eine Regel, die mittels Regular-Expressions den eigenen Hostnamen bzw. die eigene IP-Adresse in einer HELO-Angabe erkennt.
Den entsprechenden Parameter finden Sie in der Datei /etc/postfix/main.cf:

smtpd_helo_restrictions =
    [...]
    reject_invalid_helo_hostname
    reject_unknown_helo_hostname
    reject_non_fqdn_helo_hostname
    check_helo_access pcre:/etc/postfix/helo_checks

Erstellen Sie eine neue Datei /etc/postfix/helo_checks nach folgendem Syntax:

nano /etc/postfix/helo_checks
helo_checks
/^mailserver\.example\.com$/        550 That's not your hostname
/^example\.com$/                    550 That's not your domain
/^192\.0\.2\.42$/                   550 That's not your IP-Address


Pflicht-Empfänger definieren

Info

Für den Betrieb eines RFC-konformen Mailservers muss sichergestellt sein, dass zwei Empfänger als administrative Anlaufstellen immer erreichbar sein müssen. Die Qualität der Nachricht darf dabei keine Rolle spielen. Die Nachrichten müssen demnach angenommen werden, bevor diese durch einen evtl. falschen oder ungültigen HELO Hostnamen abgelehnt würden. Hierfür muss eine Ausnahme für diese zwei Empfänger definiert werden.

  • postmaster Definiert in RFC 2821 als zentraler Ansprechpartner für E-Mail-bezogene Fragen.

  • abuse Definiert in RFC 2142 als zentraler Ansprechpartner für missbräuchliche Verwendung des Mailservers.

    Ebenso wie für einen Mailserver definiert der RFC 2142 auch zwei Empfänger für den Betrieb eines Webservers. Nachrichten an diese zwei Empfänger sollten nach den gleichen Kriterien angenommen werden, müssen aber nicht. Falls Sie also einen Webserver betreiben, können Sie die Ausnahme auch für diese Empfänger definieren.

  • webmaster Zentraler Ansprechpartner für Fragen zu Ihrer Webseite.
  • hostmaster Zentraler Ansprechpartner für Fragen zum DNS-Server bzw. der DNS-Zone.


Den entsprechenden Parameter finden Sie in der Datei /etc/postfix/main.cf:

main.cf
smtpd_helo_restrictions =
    [...]
    check_recipient_access hash:${config_directory}/roleaccount_exceptions
    reject_invalid_helo_hostname
    reject_unknown_helo_hostname
    reject_non_fqdn_helo_hostname
    check_helo_access pcre:/etc/postfix/helo_checks
    [...]

Erstellen Sie die Datei /etc/postfix/roleaccount_exceptions mit folgendem Inhalt:

nano /etc/postfix/roleaccount_exceptions
postmaster@     OK
abuse@          OK
hostmaster@     OK
webmaster@      OK


Erstellen Sie die Roleaccount-ExceptionsDatenbank für Postfix:

postmap hash:/etc/postfix/roleaccount_exceptions


Anonymisierung des E-Mail-Headers

Info

Im Header einer E-Mail stehen viele Informationen, die unter anderem Angaben enthalten, die einem möglichen Angreifer in die Karten spielen. Diese Informationen können z.B. die IP-Adresse Ihres internen Mailservers, die IP-Adresse und die Version des verwendeten E-Mails-Clients, usw. sein. Unser Mailserver soll nur die Informationen preisgeben, die zum eigentlichen Mail-Versand benötigt werden.

Die Datei /etc/postfix/header_checks enhält Regular Expressions, die von einem Postfix-Cleanup-Job in der Datei /etc/postfix/master.cf ausgewertet werden. Übereinstimmende Einträge werden vor dem E-Mail-Versand aus dem E-Mail-Header entfernt.

master.cf
[...]
submission inet  n       -       n       -       -       smtpd
    [...]
    # Hier wird angegeben, dass der Cleanup-Job "submission-header_checks" ausgeführt werden soll
    -o cleanup_service_name=submission-header_checks
[...]
# Cleanup-Job "submission-header_checks"
submission-header_checks unix n - n    -       0       cleanup
    -o header_checks=pcre:${config_directory}/header_checks
[...]


Erstellen Sie die Datei /etc/postfix/header_checks mit folgendem Inhalt:

nano /etc/postfix/header_checks
header_checks
# SPAM-Agent
/^X-Spam-Checker-Version:/      IGNORE
/^X-Sanitizer:/                 IGNORE

# Mail-Client
/^Received:/                    IGNORE
/^User-Agent:/                  IGNORE
/^X-Forward:/                   IGNORE
/^X-Mailer:/                    IGNORE
/^X-MimeOLE:/                   IGNORE
/^X-Originating-IP:/            IGNORE
/^X-MSMail-Priority:/           IGNORE


Blockieren gefährlicher Dateinamenerweiterungen

Info

E-Mails können bekanntlich potenziell gefährliche Anhänge transportieren. Unser Mailserver soll E-Mails, die einen Anhang mit einer potenziell gefährlichen Dateinamenerweiterung enthalten, ablehnen, bevor dieser Anhang unser internes Netzwerk erreicht. Hierzu wertet Postfix den Mime-Header einer eingehenden E-Mails aus und vergleicht diesen mit der, hier verwendeten, Regular Expression. Es wird nur der Dateinname ausgewertet und es erfolgt keine Inhaltsprüfung. Diese Option ersetzt also keinen Virenschutz!
Schickt Ihnen jemand einen hier aufgeführten Anhang, erhält er folgende Hinweismeldung und wird somit über die Nichtzustellung seiner E-Mail informiert.
Attachment type not allowed. File <DATEI> has the unacceptable extension <ERWEITERUNG>

Den entsprechenden Parameter finden Sie in der Datei /etc/postfix/main.cf:

main.cf
[...]
mime_header_checks = regexp:${config_directory}/mime_header_checks.regexp
[...]


Erstellen Sie die Datei /etc/postfix/mime_header_checks.regexp mit folgendem Inhalt:

nano /etc/postfix/mime_header_checks.regexp
mime_header_checks.regexp
/^\s*Content-(Disposition|Type).*name\s*=\s*"?(.+\.(lnk|asd|hlp|ocx|reg|bat|dat|c[ho]m|cmd|exe|dll|vxd|pif|scr|hta|jse?|sh[mbs]|vb[esx]|ws[fh]|mov|wmf|xl))"?\s*$/
   REJECT Attachment type not allowed. File "$2" has the unacceptable extension "$3"


X-Envelope-From dem Header hinzufügen

Info

Die Header-Information X-Envelope-From ist keine Pflichangabe nach RFC 5322. Es handelt sich um eine optionale Angabe, die grundsätzlich zum Mail-Versand nicht erforderlich ist. Dennoch wird diese Information von einigen E-Mail-Clients ausgewertet. Ohne diese Angabe kann es passieren, dass ein E-Mail-Client den Absender nicht korrekt darstellt. Um usereren Mailserver möglichst kompatibel zu betreiben, fügen wir diese Option dem Header hinzu.
Den entsprechenden Paramater finden Sie in der Datei /etc/postfix/main.cf:

main.cf
[...]
smtpd_relay_restrictions =
    [...]
    check_sender_access regexp:${config_directory}/add_x_envelope_from
    [...]
[...]


Erstellen Sie die Datei /etc/postfix/add_x_envelope_from mit folgendem Inhalt:

nano /etc/postfix/add_x_envelope_from
add_x_envelope_from
/^<>$/ PREPEND X-Envelope-From: <>
/^(.*)$/  PREPEND X-Envelope-From: <$1>



(Optional) Postfix an Relayhost (Smarthost) anbinden

Info

Es können einige Gründe dafür sprechen, den Mailserver nicht direkt am Internet zu betreiben:

  • Ein Mailserver kann nicht sinnvoll an einem Internet-Anschluss mit dynamischer (wechselnder) IP-Adresse betrieben werden. Die meisten Mailserver lehnen dynamische Adressräume ab bzw. deklarieren sie von vorneherein als Spam.

  • Ihr interner Mailserver wird durch einen Relayhost geschützt. Der interne Mailserver enthält die eigentlichen Nutzdaten (E-Mails, Adressbücher, usw.) und muss nicht mehr komplett aus dem Internet erreichbar sein. Somit bieten Sie, durch den Einsatz eines Relayhosts, deutlich weniger Angriffsfläche für Hacker.

  • Ein Relayhost kann eigenständig unerwünschte Absender filtern. Dadurch wird der interne Mailserver entlastet.

  • Sollte Ihr interner Mailserver ausfallen oder aufgrund einer Wartung vorübergehend nicht erreichbar sein, werden eingehende E-Mails auf einem Relayhost gepuffert und zugestellt, sobald der interne Mailserver wieder erreichbar ist. Damit erhöhen Sie Ausfallsicherheit und die Verfügbarkeit Ihres Mailsystems.

Sie können Ihren eigenen Relayhost aufsetzen. Wie das funktioniert, habe ich in der Dokumentation Postfix als Relayhost (Smarthost) beschrieben.
Alternativ kann man einen Relayhost auch mieten. Da ich schon immer einen eigenen Relayhost betreibe, habe ich allerdings keine Erfahrung, welche Provider infrage kommen. Fragen Sie am besten Ihren Domain-Hoster. Eventuell bietet dieser so etwas an.

Wenn Sie auf die Vorteile eines Relayhosts verzichten möchten, Ihren Mailserver aber an einem Internet-Anschluss mit dynamischer IP-Adresse betreiben wollen, können Sie auch den E-Mail-Dienst Ihres Domain-Hosters verwenden. Die meisten Domain-Hoster erlauben das Relaying der eigenen Domain. Ihre E-Mails würden in diesem Fall über den Relayhost Ihres Domain-Hosters versendet. Eingehende E-Mails würden Ihrem Mailserver direkt zugestellt werden.
Vom Einsatz sogenannter POP3-Collectoren, wie z.B. Fetchmail, rate ich ab. Diese Dienste funktionieren grundsätzlich zwar gut und es gibt durchaus Anwendungsfälle dafür, dennoch sind sie nicht für den Betrieb eines echten Mailservers geeignet. Das gesamte Konstrukt wird durch den Einsatz anfällig für Fehler.



Relayhost ohne Authentifizierung

Wenn Sie einen Relayhost verwenden der keine Authentifizierung erfordet, müssen Sie lediglich die IP-Adresse oder den FQDN und den verwendendeten Port des Relayhosts der Datei /etc/postfix/main.cf hinzufügen:

main.cf
[...]
RELAY-HOST CONFIGURATION
#########################################################################

Relayhost ohne Authentifizierung
relayhost              = mailserver.example.com:587
[...]
Anzupassende Parameter:
[...]
relayhost   = mailserver.example.com:587
[...]

Starten Sie Postfix neu, damit die Konfiguration angewendet wird:
service postfix restart


Relayhost mit Authentifizierung

Erfordert der Relayhost eine Authentifizierung, müssen Sie Postfix zunächst die Authentifizierungs-Informationen bekanntgeben.
Erstellen Sie die Datei /etc/postfix/sasl_relayhost_passwd nach folgendem Syntax:
RELAYHOST BENUTZERNAME:PASSWORT

sasl_relayhost_passwd
nano /etc/postfix/sasl_relayhost_passwd
mailserver.example.com [email protected]:SicheresPasswortVerwenden!
Erstellen Sie die Passwort-Datenbank für Postfix:
postmap hash:/etc/postfix/sasl_relayhost_passwd
Passen Sie die Zugriffsrechte an:
chmod 600 /etc/postfix/sasl_relayhost*

Fügen Sie der Datei /etc/postfix/main.cf folgendes hinzu:
nano /etc/postfix/main.cf
main.cf
[...]
RELAY-HOST CONFIGURATION
#########################################################################

Relayhost mit Authentifizierung
relayhost                   = [mailserver.example.com]:587
smtp_use_tls                = yes
smtp_sasl_auth_enable       = yes
smtp_sasl_password_maps     = hash:${config_directory}/sasl_relayhost_passwd
smtp_sasl_security_options  = noanonymous
[...]
Anzupassende Parameter:
[...]
relayhost   = [mailserver.example.com]:587
[...]

Starten Sie Postfix neu, damit die Konfiguration angewendet wird:
service postfix restart


Dovecot konfigurieren

Dovecot MySQL-Dateien anlegen

Info

Dovecot benötigt für den Betrieb drei SQL-Dateien um die notwendigen Informationen aus der Postfix-Datenbank abzurufen.

  • Die Datei dovecot-sql.conf beinhaltet SQL-Abfragen für den Benutzernamen und das dazugehörige Kennwort.

  • Die Datei dovecot-dict-sql-user.conf beinhaltet SQL-Abfragen für die User-Quota. Damit ist die Begrenzung des Speicherplatzes für ein Benutzer-Postfach gemeint.

  • Die Datei dovecot-dict-sql-domain.conf beinhaltet SQL-Abfragen für die Domain-Quota. Damit ist die Begrenzung des Speicherplatzes für eine Domain gemeint. Also der maximale Speicherplatz den alle Benutzer-Postfächer einer Domain zusammen, belegen dürfen.

Erstellen Sie die Datei /etc/dovecot/dovecot-sql.conf mit folgendem Inhalt:

nano /etc/dovecot/dovecot-sql.conf
/etc/dovecot/dovecot-sql.conf (UserDB)
driver = mysql
connect = host=localhost dbname=postfix user=postfix password=SicheresPasswortVerwenden!
default_pass_scheme = MD5

user_query = SELECT CONCAT('/var/spool/mail/virtual/',maildir) as home, \
             CONCAT('*:bytes=', \
             IF(mailbox.quota = 0, domain.maxquota*1024000, mailbox.quota)) \
             as quota_rule \
             FROM mailbox, domain \
             WHERE username = '%u' AND mailbox.active = '1' AND \
             domain.domain = '%d' AND domain.active = '1'

password_query = SELECT username as user, password, \
                 CONCAT('/var/spool/mail/virtual/',maildir) AS userdb_home \
                 FROM mailbox WHERE username = '%u' AND active = '1'

iterate_query = SELECT local_part AS username, domain FROM mailbox
Anzupassende Parameter:
[...]
connect = [...] password=SicheresPasswortVerwenden!
[...]

Erstellen Sie die Datei /etc/dovecot/dovecot-dict-sql-user.conf mit folgendem Inhalt:
nano /etc/dovecot/dovecot-dict-sql-user.conf
dovecot-dict-sql-user.conf (User Quota)
connect = host=localhost dbname=postfix user=postfix password=SicheresPasswortVerwenden!

map {
    pattern = priv/quota/storage
    table = quota2
    username_field = username
    value_field = bytes
}

map {
    pattern = priv/quota/messages
    table = quota2
    username_field = username
    value_field = messages
}
Anzupassende Parameter:
connect = [...] password=SicheresPasswortVerwenden!
[...]

Erstellen Sie die Datei /etc/dovecot/dovecot-dict-sql-domain.conf mit folgendem Inhalt:
nano /etc/dovecot/dovecot-dict-sql-domain.conf
dovecot-dict-sql-domain.conf (Domain Quota)
connect = host=localhost dbname=postfix user=postfix password=SicheresPasswortVerwenden!

map {
    pattern = priv/quota/storage
    table = domain
    username_field = domain
    value_field = quota
}

map {
    pattern = priv/quota/messages
    table = quota2
    username_field = username
    value_field = messages
}
Anzupassende Parameter:
connect = [...] password=SicheresPasswortVerwenden!
[...]


dovecot.conf anlegen

Info

Anders als bei Postfix, besteht die Dovecot-Konfiguration aus einer Hauptdatei /etc/dovecot/dovecot.conf und sämtlichen Dateien des Unterordners /etc/dovecot/conf.d/*.conf.
Der Ordner /etc/dovecot/conf.d/ enthält Konfigurations-Dateien für einzelne Funktionen, Dienste und Protokolle. Möchte man z.B. eine SSL-Konfiguration erstellen, editiert man dazu die Datei /etc/dovecot/conf.d/10-ssl.conf.
Was auf den ersten Blick sinnvoll erscheint, endet in der Praxis aber eher mit der Verwendung des Befehls grep -r -i "SUCHSTRING" ./ (Dateien nach Inhalt durchsuchen), da man einen zu konfigurienden Paramater nicht immer in der Datei findet wo man ihn erwartet.
Durch Verwendung dieser Struktur können auch Probleme nach einem Update entstehen. Normalerweise werden Konfigurations-Dateien, die bereits von einem Administrator verändert wurden, bei einem Update nicht überschrieben, sondern die neue Datei wird als *.confnew oder ähnlich abgelegt. Bei Dateien, die nicht konfiguriert wurden, ist das aber oft anders. Da nicht alle Konfigurations-Dateien von uns editiert werden müssen, ist diese Struktur anfällig für Fehler.
Für unser Setup erstellen wir also, genau wie auch bei Postfix, nur eine zentrale Konfigurations-Datei, die alle nötigen Parameter enthält und entsprechend übersichtlich gestaltet ist.

Wie auch bei Postfix habe ich die Dovevot-Konfiguration in mehrere Abschnitte aufgteilt.
Auf die wichtigsten Parameter gehen wir ein:

Abschnitt Host Configuration

In diesem Abschnitt definieren wir die globalen Parameter des Servers.

  • protocols = imap sieve
    Wir erstellen einen IMAP-Server mit Sieve-Unterstützung. (Auf Sieve gehen wir gleich noch genauer ein)

  • postmaster_address = [email protected]
    Die Absender-Adresse für Bounce-E-Mails.

  • mail_location = maildir:~/maildir:LAYOUT=fs:UTF-8
    Wir verwendet das Maildir-Format mit UTF-8-Kodierung. Das ist wichtig, wenn wir Ordner mit Umlauten erstellen möchten (z.B. "Gelöschte Objekte")

  • mail_plugins = quota acl
    Zusätzliche Plugins, auf deren Funktion wir in den Abschnitten Quota und Folder-Sharing noch genau eingehen werden.

Abschnitt TLS

Da wir unseren Benutzernamen und das Kennwort nicht im Klartext übertragen wollen, richten wir auch hier die TLS-Verschlüsselung ein.

  • auth_mechanisms = plain login
    Als Authentifizierungs-Verfahren für die Anmeldung am IMAP-Server wählen wir plain und login. Zwar sind das Verfahren, bei denen der Benutzername und das Kennwort unverschlüsselt übertragen werden, da wir aber strikte TLS-Verschlüsselung fordern, stellt das kein Problem dar.
    Das Verfahren plain ist im RFC 4616 festgelegt.

  • ssl = required
    Wir lassen keine unverschlüsselten Verbindungen zu.

  • ssl_min_protocol = TLSv1.2
    Wir verlangen mindestens TLSv1.2.

Abschnitt User Mapping

In diesem Abschnitt finden wir die erste SQL-Datei wieder. Die Parameter userdb und passdb geben den Ort der Datei an. Sie stellen die User-Datenbank und die dazugehörende Passwort-Datenbank dar.

Abschnitt Quota

Als Quota wird in unserem Fall die Speicherplatz-Begrenzung eines E-Mail-Postfachs bezeichnet. Überschreitet ein Benutzer den Postfach-Speicherplatz, können keine weiteren E-Mails empfangen werden. Der Absender erhält die RFC 1893-konforme Fehlermeldung der Klasse 5 (Permanent Failure) mit dem Inhalt 5.2.2 Mailbox is over quota.

dovecot.conf
plugin {
    [...]
    quota_status_overquota = "552 5.2.2 Mailbox is over quota"
}

Postfix ruft den Quota-Status im Rahmen der SMTPD-Restrictions ab.
Den entsprechenden Parameter finden Sie in der Datei /etc/postfix/main.cf:
main.cf
smtpd_recipient_restrictions =
    [...]
    check_policy_service unix:private/quota-status
    [...]

Ab einer Speicherplatz-Auslastung von 80% erhält der Benutzer die erste Warnmeldung. Die Zweite wird bei 90% und die Dritte bei 100% Speicherplatz-Auslastung versendet. Die Schwellwerte können angepasst werden. Ändern Sie einfach die folgenden Werte:
dovecot.conf
plugin {
[...]
    quota_warning = storage=80%% quota-warning 80 %u
    quota_warning2 = storage=95%% quota-warning 95 %u
    quota_warning3 = storage=100%% quota-warning 100 %u
}

Die Warnmeldungen werden mit dem Skript /usr/local/bin/quota-warning.sh generiert. Das Skript erstellen wir später und natürlich können die Texte der Warnmeldungen ebenfalls angepasst werden.

Abschnitt Sieve

Die Skriptsprache Sieve ist eine Sprache zum Konfigurieren von Mailregeln im E-Mail-Client. Die Spezifikation ist im RFC 5228 definiert.
Viele Web-Clients (E-Mail-Webinterface), wie z.B. Roundcube, unterstützen Sieve. Der Dienst service managesieve-login kann über den Port 4190 angesprochen werden.

Beispiel:

Abschnitt Default-Folders

In diesem Abschnitt wird festgelegt, welche Ordner bei der Erstellung eines neuen Postfachs automatisch angelegt werden und welche Funktion sie haben.

Dem Ordner Gesendete Elemente wird z.B. die Special-Use Mailbox \Sent zugewiesen. Dadurch weiss ein E-Mail-Client, dass eine gesendete E-Mail in diesem Ordner abzulegen ist. Die Verwendung dieser Special-Use Mailboxes wird in RFC 6154 geregelt.
Natürlich können Sie die Namen der Ordner anpassen.

Weitere Informationen finden Sie in der Dovecot-Wiki, unter Dovecot.org/MailboxSettings.

Abschnitt Folder-Sharing

E-Mail-Ordner können mit Benutzern des gleichen Mailservers geteilt werden. Wir können also anderen Benutzern innerhalb unserer Organisation, bestimmte Rechte auf unser Postfach oder einzelenen Ordnern einräumen. Dafür ist das Dovecot-Plugin acl zuständig.

Weitere Informationen finden Sie in der Wiki von Dovecot-Wiki, unter Dovecot.org/SharedMailboxes.

Abschnitt IMAP

In diesem Abschnitt wird der IMAP-Dienst konfiguriert. Unser IMAP-Dienst ist auf dem Standard-Port 143 zu erreichen.

  • imap_idle_notify_interval = 29 mins
    Dovecot prüft periodisch, ob ein verbundener Client noch erreichbar ist. Hierzu wird eine Benachrichtgung an den Client gesendet ("I'm still here"). Sendet der Client keine Antwort, wird die Verbindung getrennt.
    Der Wert ist nicht ohne Grund auf 29 Minuten gesetzt. Nutzt man als Client z.B. ein Smartphone, reagiert die entsprechende E-Mail-App auf jede dieser Benachrichtigungen und verbraucht damit unnötig Strom. Gemäß RFC 2060 muss ein Client-Idle-Timout mindestens 30 Minuten betragen. Wenn wir also nach 29 Minuten beim Client nachfragen, bleiben wir immer darunter.

  • mail_max_userip_connections = 20
    Dieser Parameter gibt an, dass 20 gleichzeitige Verbindungen von einem Benutzer pro IP-Adresse zum Server hergestellt werden dürfen.

Abschnitt Master

Im Abschnitt Master werden, ähnlich wie in der Postfix-Datei master.cf untergeordnete Prozesse gesteuert.
Der Prozess dict ist für den Verzeichnis-Zugriff, in unserem Fall die SQL-Datenbank, zuständig. Der Prozess auth ist für die Authentifizierung Zuständig. Da wir in der Postfix-Konfiguration festgelegt haben, die SASL-Authentifizierung an Dovecot zu deligieren, muss ein entsprechender UNIX-Socket für Postfix bereitgestellt werden.

Den entsprechenden Parameter finden Sie in der Datei /etc/postfix/main.cf:

main.cf
[...]
#SASL Authentication
######################################

smtpd_sasl_type    = dovecot
smtpd_sasl_path    = private/auth
[...]

Benennen Sie zunächst die /etc/dovecot/dovecot.conf um, damit Sie eine Sicherheitskopie der Original-Datei haben:

mv /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.bak

Erstellen Sie eine neue Datei /etc/dovecot/dovecot.conf mit folgendem Inhalt:
nano /etc/dovecot/dovecot.conf
dovecot.conf
# Host Configuration
#########################################################################

listen                          = *
protocols                       = imap sieve
postmaster_address              = [email protected]

mail_location                   = maildir:~/maildir:LAYOUT=fs:UTF-8
mail_plugins                    = quota acl
mail_uid                        = 5000
mail_gid                        = 5000
last_valid_uid                  = 5000
first_valid_uid                 = 5000
mail_debug                      = no


# TLS
#########################################################################

auth_mechanisms                 = plain login
disable_plaintext_auth          = yes
auth_verbose                    = yes

ssl                             = required
ssl_min_protocol                = TLSv1.2
ssl_cipher_list                 = EECDH+AESGCM:EECDH+AES
ssl_prefer_server_ciphers       = yes
ssl_cert                        = </etc/letsencrypt/live/mailserver.example.com/fullchain.pem
ssl_key                         = </etc/letsencrypt/live/mailserver.example.com/privkey.pem

# User Mapping
#########################################################################

userdb {
  args                          = /etc/dovecot/dovecot-sql.conf
  driver                        = sql
}

passdb {
  args                          = /etc/dovecot/dovecot-sql.conf
  driver                        = sql
}


# Quota
#########################################################################

dict {
  sqldomainquota                = mysql:/etc/dovecot/dovecot-dict-sql-domain.conf
  sqluserquota                  = mysql:/etc/dovecot/dovecot-dict-sql-user.conf
}

plugin {
  quota                         = dict:User Quota::proxy::sqluserquota
  quota_grace                   = 10%%
  quota_rule2                   = Trash:storage=+10%%
  quota_status_nouser           = DUNNO
  quota_status_overquota        = 552 5.2.2 Mailbox is over quota
  quota_status_success          = DUNNO
  quota_warning                 = storage=80%% quota-warning 80 %u
  quota_warning2                = storage=95%% quota-warning 95 %u
  quota_warning3                = storage=100%% quota-warning 100 %u
}

service quota-status {
  client_limit                  = 1
  executable                    = quota-status -p postfix

  unix_listener /var/spool/postfix/private/quota-status {
    user                        = postfix
    group                       = postfix
    mode                        = 0660
  }
}

service quota-warning {
  user                          = vmailer
  executable                    = script /usr/local/bin/quota-warning.sh

  unix_listener quota-warning {
    group                       = vmailer
    mode                        = 0660
    user                        = vmailer
  }
}

protocol lda {
  quota_full_tempfail           = yes
}


# Sieve
#########################################################################

service managesieve-login {
  inet_listener sieve {
    address                     = *
    port                        = 4190
  }
}

plugin {
  sieve                         = ~/.dovecot.sieve
  sieve_dir                     = ~/sieve
  sieve_before                  = /etc/dovecot/sieve/global.sieve
}

protocol lda {
  mail_plugins                  = $mail_plugins sieve
}


# Default-Folders
#########################################################################

namespace inbox {
  type                          = private
  prefix                        =
  location                      =
  inbox                         = yes

  mailbox "Gesendete Elemente" {
    auto                        = subscribe
    special_use                 = \Sent
  }

  mailbox Entwürfe {
    auto                        = subscribe
    special_use                 = \Drafts
  }

  mailbox Junk-E-Mail {
    auto                        = subscribe
    special_use                 = \Junk
  }

  mailbox "Gelöschte Elemente" {
    auto                        = subscribe
    special_use                 = \Trash
  }

  mailbox Archiv {
    auto                        = no
    special_use                 = \Archive
  }
}


# Folder-Sharing
#########################################################################

namespace {
  type                          = shared
  separator                     = /
  prefix                        = shared/%%u/
  location                      = maildir:%%h/maildir:INDEX=~/shared/%%u:INDEXPVT=~/shared/%%u
  subscriptions                 = yes
  list                          = children
  inbox                         = no
  hidden                        = no
  ignore_on_failure             = no
}

plugin {
  acl                           = vfile
  acl_shared_dict               = file:/var/spool/mail/virtual/shared-mailboxes.db
}


# IMAP
#########################################################################

imap_idle_notify_interval       = 29 mins

service imap-login {
  inet_listener imap {
    address                     = *
    port                        = 143
  }
}

protocol imap {
  mail_max_userip_connections   = 20
  mail_plugins                  = $mail_plugins imap_quota imap_acl
}


# Master
#########################################################################

service auth {
  unix_listener /var/spool/postfix/private/auth {
    user                        = postfix
    group                       = postfix
    mode                        = 0660
  }

  unix_listener auth-userdb {
    user                        = vmailer
    group                       = vmailer
    mode                        = 0777
  }
}

service dict {
  unix_listener dict {
    user                        = vmailer
    mode                        = 0600
  }
}


# Stats
#########################################################################

service stats {
  unix_listener stats-reader {
    user = vmailer
    group = vmailer
    mode = 0600
  }
  unix_listener stats-writer {
    user = vmailer
    group = vmailer
    mode = 0660
  }
}
Anzupassende Parameter:
# Host Configuration
#########################################################################
[...]
postmaster_address = [email protected]
[...]
# TLS
#########################################################################
[...]
# Nur anpassen, wenn Sie ein anderes Zertifikat verwenden!
ssl_cert = </etc/letsencrypt/live/mailserver.example.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mailserver.example.com/privkey.pem
[...]


(Optional) IPv6-Unterstützung einrichten

Info

Wenn Ihr Server, zusätzlich zu IPv4, über einen IPv6-Uplink verfügt (Dual-Stack), spricht nichts dagegen, IPv6 auch mit Dovecot zu nutzen.


Editieren Sie die Datei /etc/dovecot/dovecot.conf und passen Sie den folgenden Parameter an:

nano /etc/dovecot/dovecot.conf
Anzupassende Parameter:
[...]
listen      = * ::
[...]


Skript für Quota-Warnmeldungen erstellen

Info

Das Skript quota-warning.sh generiert Warnmeldungen, die bei Überschreitung des Postfachspeichers an den entsprechenden Benutzer versendet werden.
Die Texte können natürlich auch angepasst werden.


Erstellen Sie die Datei /usr/local/bin/quota-warning.sh mit folgendem Inhalt:

nano /usr/local/bin/quota-warning.sh
quota-warning.sh
#!/bin/sh
#
#            ___________       .__.__  .__       .__     __
#            \__    ___/_  _  _|__|  | |__| ____ |  |___/  |_
#              |    |  \ \/ \/ /  |  | |  |/ ___\|  |  \   __\
#              |    |   \     /|  |  |_|  / /_/  >   Y  \  |
#              |____|    \/\_/ |__|____/__\___  /|___|  /__|
#                                        /_____/      \/
#
#  Twilight-Networks ∙ est. 2k1 ∙ fxp ∙ h4x ∙ nfo ∙ scene ∙ legacy lives
#  Keep it lean, keep it silent. Code like it's 2002.
#
#########################################################################
# Script Name   : quota-warning.sh
# Description   : Generates Quota-Warning-Messages for Dovecot
#
# Version       : 1.01
# Last Update   : 02.04.2025
# Author        : Twilight
# Contact       : [email protected]
# Web:          : https://www.twilight-networks.com
#
# Tested with   : Ubuntu 24.04 LTS
#                 Dovecot 2.3.21
#########################################################################


# Config
FROM='[email protected]'


# Below this line: scene code. You break it, you bought it.
#########################################################################

PERCENT=$1
USER=$2

if [ "$PERCENT" -eq 100 ] ; then
  (
  echo "X-Priority: 1"
  echo "Content-Type: text/plain; charset=UTF-8"
  echo "To: $USER"
  echo "MIME-Version: 1.0"
  echo "Subject: Mail-Quota Warnung! Ihr Postfach ist voll!"
  echo "From: $FROM"
  echo
  echo "Hallo $USER,"
  echo
  echo "der Speicherplatz Ihres Postfachs ist derzeit zu $PERCENT% ausgelastet."
  echo "Bitte löschen Sie einige E-Mails."
  echo
  echo "Derzeit ist KEIN weiterer E-Mail-Empfang möglich!"
  echo
  ) | /usr/lib/dovecot/dovecot-lda -d "$USER"
  exit 0

else

  (
  echo "X-Priority: 1"
  echo "Content-Type: text/plain; charset=UTF-8"
  echo "To: $USER"
  echo "MIME-Version: 1.0"
  echo "Subject: Mail-Quota Warnung!"
  echo "From: $FROM"
  echo
  echo "Hallo $USER,"
  echo
  echo "der Speicherplatz Ihres Postfachs ist derzeit zu $PERCENT% ausgelastet."
  echo "Bitte löschen Sie einige E-Mails."
  echo
  ) | /usr/lib/dovecot/dovecot-lda -d "$USER"
  exit 0

fi
#end
Anzupassende Parameter
[...]
FROM='[email protected]'
[...]

Vergeben Sie die benötigte Berechtigung, damit die Datei ausgeführt werden kann:
chmod +x /usr/local/bin/quota-warning.sh


Globales Sieve-Skript erstellen

Info

Der Inhalt der Datei global.sieve ist eine globale Mailregel, die unabhängig der von Benutzern erstellten Mailregeln für alle Benutzer des Mailservers gilt. In unserem Setup wird sie aussagen, dass alle E-Mails, deren Header X-Spam-Flag: YES enthalten, dem Ordner Junk zugestellt werden.

Das X-Spam-Flag wird von Spam-Filtern, wie z.B. Spamassassin, dem Header einer E-Mail hinzugefügt.
Den entsprechenden Parameter finden Sie in der Datei /etc/dovecot/dovecot.conf:

dovecot.conf
plugin {
    [...]
    sieve_before = /etc/dovecot/sieve/global.sieve
}

Erstellen Sie einen Ordner /etc/dovecot/sieve:

mkdir /etc/dovecot/sieve

Erstellen Sie die Datei /etc/dovecot/sieve/global.sieve mit folgendem Inhalt:
nano /etc/dovecot/sieve/global.sieve
global.sieve
require "fileinto";

if header :contains "X-Spam-Flag" ["YES"] {
        fileinto "Junk";
        stop;
}

Passen Sie die Zugriffsrechte an:
chown -R vmailer:vmailer /etc/dovecot/sieve


Brute-Force-Schutz einrichten

Fail2Ban konfigurieren

Info

Der Dienst fail2ban wertet in Echtzeit entsprechende Log-Dateien des Mailservers aus und sperrt nach Überschreiten einer festgelegten Schwelle von Falscheingaben, die IP-Adresse des Angreifers für eine festgelegte Zeit und informiert den Administrator über die Sperre per E-Mail (destemail = [email protected]). Diese E-Mail enthält ausführliche Informationen zu der gesperrten IP-Adresse.

In diesem Beispiel wird die IP-Adresse eines Angreifers nach 5-maliger Falscheingabe (maxretry = 5) für 24 Stunden (bantime = 24h Sekunden) gesperrt.


Erstellen Sie die Datei /etc/fail2ban/jail.local mit folgendem Inhalt:

nano /etc/fail2ban/jail.local
jail.local
[DEFAULT]
destemail   = [email protected]
sender      = [email protected]

ignorself   = true
ignoreip    = 127.0.0.1/8 192.0.2.42

bantime     = 24h
maxretry    = 5

[postfix]
enabled     = true
mode        = aggressive
logpath     = /var/log/mail.log
action      = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
              %(mta)s-whois[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]

[dovecot]
enabled     = true
action      = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
              %(mta)s-whois[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]

[sshd]
enabled     = true
port        = 22
mode        = aggressive
logpath     = /var/log/auth.log
action      = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
              %(mta)s-whois[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]

Anzupassende Parameter:
[...]
destemail   = [email protected]
sender      = [email protected]

ignoreip    = 192.0.2.42
[...]


Starten Sie den Dienst fail2ban:

service fail2ban restart


DNS-Zone konfigurieren

Host-A-Eintrag setzen

Info

Damit der Mailserver aus dem Internet erreichbar ist, muss der Hostname und die zugehörige IP-Adresse veröffentlich werden. Dafür wird auf dem zuständigen DNS-Server ein Host-A-Eintrag gesetzt. Dieser enthält die notwendigen Informationen.


Erstellen Sie auf dem DNS-Server, der für Ihre Domain zuständig ist, einen Host-A-Eintrag nach folgendem Syntax:

  • Hostname hier geben Sie den Namen des Mailservers an.
  • Typ hier geben Sie den Typ des DNS-Eintrags an. In unserem Fall muss es ein Host-A-Eintrag sein.
  • Ziel hier geben Sie die öffentliche IP-Adresse des Mailservers an.


IPv4
Host-A-Eintrag für die Domain example.com

Hostname Typ Ziel
relayhost A 192.0.2.42


IPv6 Host-AAAA-Eintrag für die Domain example.com:

Hostname Typ Ziel
relayhost AAAA 2001:db8:0:8d3:0:8a2e:70:7344


MX-Eintrag setzen

Info

Damit der Mailserver eines Absenders weiß, welchem Mailserver er E-Mails für Ihre Domain zustellen soll, muss diese Information veröffentlicht werden. Hierzu wertet der sendende Mailserver den MX-Eintrag für Ihre DNS-Zone aus und sendet die E-Mail an den, im MX-Eintrag hinterlegten, Mailserver.
Ein MX-Eintrag kann mehrere Mailserver enthalten. Sollte ein Mailserver nicht erreichbar sein, wird der sendende Mailserver die Zustellung, gemäß des MX-Eintrags, auf weitere Mailserver versuchen. Die Reihenfolge wird über die angegebene Priorität festgelegt. Ein niedriger Wert bedeutet eine höhere Priorität.

Hinweis

Das Einrichten des MX-Eintrags ist nur erforderlich, wenn Sie Ihren Mailserver direkt am Internet betreiben bzw. zum direkten Empfang von E-Mails verwenden.
Ist ein Relayhost für den Empfang und das Versenden von E-Mails zuständig, sind nur die Abschnitte Host-A-Eintrag setzen und PTR-Eintrag setzen relevant.


Erstellen Sie auf dem DNS-Server, der für Ihre Domain zuständig ist, einen MX-Eintrag nach folgendem Syntax:

  • TYP hier geben Sie den Typ des DNS-Eintrags an. In unserem Fall muss es ein MX-Eintrag sein.
  • Priorität hier geben Sie Priorität an. Ein niedriger Wert bedeutet eine höhere Priorität.
  • Ziel hier geben Sie den FQDN des Mailservers an.

MX-Eintrag für die DNS-Zone example.com

Typ Priorität Ziel
MX 10 mailserver.example.com



PTR-Eintrag setzen

Info

Bei der Spam-Erkennung wird in der Regel geprüft, ob die IP-Adresse des sendenden Mailservers über DNS auflösbar ist (Reverse-DNS-Looup) und mit dem angegebenen Namen des sendenden Mailservers übereinstimmt.

Ein PTR-Eintrag (Reverse-DNS-Eintrag) ist das Gegenteil eines "normalen" DNS-Eintrags. Im Gegensatz zum "normalen" DNS-Eintrag, mit dem für einen bekannten Hostnamen eine unbekannte IP-Adresse ermittelt wird, wird beim PTR-Eintrag zu einer bekannten IP-Adresse ein unbekannter Hostname ermittelt.

Der PTR-Eintrag wird daher auf dem DNS-Server gesetzt, der für die IP-Adresse Ihres Mailservers zuständig ist. Das ist normalerweise der Provider, bei dem Sie den Root-Server oder vHost gemietet haben. Den PTR-Eintrag können Sie fast immer eigenständig über die Web-Oberfläche des Providers setzen.

Beispiel IONOS:

PTR Ionos


Erstellen Sie auf dem DNS-Server, der für die öffentliche IP-Adresse Ihres Mailservers zuständig ist, einen PTR-Eintrag nach folgendem Syntax:

  • IP-Adresse hier geben Sie die zu verwaltende IP-Adresse an.
  • TYP hier geben Sie den Typ des DNS-Eintrags an. In unserem Fall muss es ein PTR-Eintrag sein.
  • Ziel hier geben Sie den FQDN des Mailservers an.


IPv4
PTR-Eintrag für die öffentliche IP-Adresse 192.0.2.42

IP-Adresse Typ Ziel
192.0.2.42 PTR mailserver.example.com


IPv6 PTR-Eintrag für die öffentliche IP-Adresse 2001:db8:0:8d3:0:8a2e:70:7344:

IP-Adresse Typ Ziel
2001:db8:0:8d3:0:8a2e:70:7344 PTR mailserver.example.com


Maildomain und Postfach einrichten

Da wir den Mailserver komplett mit PostfixAdmin verwalten, ist die Einrichtung der Maildomain und des ersten Postfachs sehr bequem und einfach durchzuführen.

  • Rufen Sie das Webinterface von PostfixAdmin auf und melden Sie sich mit dem Superadmin-Account an:
    https://mailserver.example.com/postfixadmin
    
    PostfixAdmin Login


Maildomain einrichten

  • Klicken Sie auf Domain Liste und anschließend auf Neue Domain.

    PostfixAdmin Setup


  • Tragen Sie die neue Maildomain ein.
    Passen Sie ggf. die Anzahl der maximalen Aliase bzw. Mailboxen und die maximalen Quota-Werte für die Domain an. Klicken Sie anschließend auf Domain hinzufügen.

    PostfixAdmin Setup


Postfach einrichten

  • Klicken Sie auf Virtual Liste und anschließend auf Mailbox hinzufügen.

    PostfixAdmin Setup


  • Vergeben Sie einen Benutzernamen, ein Passwort und einen vollständigen Namen.
    Passen Sie ggf. den maximalen Quota-Wert für das Postfach an. Klicken Sie anschließend auf Mailbox hinzufügen.

    PostfixAdmin Setup



Inbetriebnahme und Test

Hinweis!

Führen Sie die Tests nicht auf der Kommandozeile des Mailservers durch. Der Mailserver verfügt über wesentlich mehr Rechte als ein externer Client. Die Ergebnisse wären nicht repräsentativ.
Verwenden Sie für die Tests einen Client mit gültigem Host-A- und PTR-Eintrag, da ansonsten der Hostname- und der Reverse-DNS-Check fehlschlägt.

Auf der Seite MX-Toolbox können Sie Ihren Mailserver auch online testen lassen. Der Mailserver muss alle Tests bestehen, um als Produktiv-System genutzt werden zu können.

Relay_test.png

Postfix neustarten

Starten Sie zunächst Postfix neu und kontrollieren Sie, ob der Dienst ohne Fehlermeldungen startet:

service postfix restart
service postfix status
[...]
Jan 29 15:17:21 ubuntu-1604-server-amd64-template systemd[1]: Starting LSB: Postfix Mail Transport Agent...
Jan 29 15:17:21 ubuntu-1604-server-amd64-template postfix[13975]:  * Starting Postfix Mail Transport Agent postfix
Jan 29 15:17:21 ubuntu-1604-server-amd64-template postfix[13975]:    ...done.
Jan 29 15:17:21 ubuntu-1604-server-amd64-template systemd[1]: Started LSB: Postfix Mail Transport Agent.
Jan 29 15:17:21 ubuntu-1604-server-amd64-template postfix/master[14041]: daemon started -- version 3.1.0, configuration /etc/postfix

Open-Relay-Test

Achtung!

Ein Open-Relay ist ein Mailserver, der es beliebigen Absendern ermöglicht, E-Mails an beliebige Empfänger zu übermitteln, ohne das hierzu eine Authentifizierung erforderlich ist. Diese Mailserver werden gerne zum Versand von Spam-Nachrichten verwendet. Oftmals ist es nur ein kleiner Konfigurations-Fehler, der einen Mailserver zu einem Open-Relay macht. Daher ist dieser Test wichtig und unbedingt durchzuführen!

Prüfen Sie unbedingt, ob der Server sicher arbeitet und kein offenes Relay darstellt, bevor Sie den Mailserver produktiv nutzen.


Stellen Sie eine Telnet-Verbindung zum Mailserver auf Port 25 (SMTP) her und verwenden Sie die folgenden Kommandos für den Test.
(example.net ist eine gültige Domain und kann daher für den Test verwendet werden)

telnet mailserver.example.com 25
Trying 192.0.2.42...
Connected to mailserver.example.com.
Escape character is '^]'.
220 mailserver.example.com ESMTP Postfix
EHLO example.net
250-mailserver.example.com
250-PIPELINING
250-SIZE 26214400
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
MAIL FROM:<[email protected]>
250 2.1.0 Ok
RCPT TO:<[email protected]>
554 5.7.1 <[email protected]>: Relay access denied

Kontrollieren Sie die letzte Zeile. Wenn Sie die Meldung ...Relay access denied erhalten, ist der Test erfolgreich abgeschlossen.

E-Mail-Empfang testen

Info

Unser Mailserver wartet auf SMTP-Port 25 auf eingehende E-Mails. Die Übertragung von E-Mails kann unverschlüsselt oder mit STARTTLS durchgeführt werden.
Der E-Mail-Empfang kann ganz einfach über die Kommandozeile getestet werden. Alternativ können Sie natürlich auch sofort eine "echte" E-Mail an den Mailserver senden. Bei einer Fehlersuche ist der Test über die Kommandozeile allerdings besser.

Ohne STARTTLS

Stellen Sie eine Telnet-Verbindung zum Mailserver auf Port 25 (SMTP) her und verwenden Sie die folgenden Kommandos um eine eingehende E-Mail zu versenden.
Senden Sie die E-Mail an eine gültige, zu Ihrer Maildomain gehörenden E-Mail-Adresse (RCPT TO:<GÜLTIGE-E-MAIL-ADRESSE>).
(example.net ist eine gültige Domain und kann daher für den Test verwendet werden)

telnet mailserver.example.com 25
Trying mailserver.example.com...
Connected to mailserver.example.com.
Escape character is '^]'.
220 mailserver.example.com ESMTP Postfix
EHLO example.net
250-mailserver.example.com
250-PIPELINING
250-SIZE 26214400
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
MAIL FROM:<[email protected]>
250 2.1.0 Ok
RCPT TO:<GÜLTIGE-E-MAIL-ADRESSE>
250 2.1.5 Ok
DATA
354 End data with <CR><LF>.<CR><LF>
Subject: Testmail
Test E-Mail-Empfang.
.
250 2.0.0 Ok: queued as 1191727019
QUIT
221 2.0.0 Bye
Connection closed by foreign host.

Wenn Sie die Meldung 250 2.0.0 Ok: queued as... erhalten und die Test-E-Mail empfangen haben, ist der Test erfolgreich abgeschlossen.

Mit STARTTLS

Stellen Sie eine OpenSSL-Verbindung zum Mailserver auf Port 25 (SMTP) her und verwenden Sie die folgenden Kommandos um eine eingehende E-Mail zu versenden.
Senden Sie die E-Mail an eine gültige, zu Ihrer Maildomain gehörenden E-Mail-Adresse (rcpt to: GÜLTIGE-E-MAIL-ADRESSE).
(example.net ist eine gültige Domain und kann daher für den Test verwendet werden)

openssl s_client -starttls smtp -connect mailserver.example.com:25
[...]
Start Time: 1551023261
Timeout   : 300 (sec)
Verify return code: 18 (self signed certificate)
---
250 DSN
ehlo example.net
250-mailserver.example.com
250-PIPELINING
250-SIZE 26214400
250-ETRN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
mail from: [email protected]
250 2.1.0 Ok
rcpt to: GÜLTIGE-E-MAIL-ADRESSE
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
Subject: Testmail
Test E-Mail-Empfang mit STARTTLS.
.
250 2.0.0 Ok: queued as EC70C26FD8
quit
221 2.0.0 Bye
closed

Wenn Sie die Meldung 250 2.0.0 Ok: queued as... erhalten und die Test-E-Mail empfangen haben, ist der Test erfolgreich abgeschlossen.

E-Mail-Versand testen

Info

Über den Submission-Port 587 können E-Mails über den Mailserver versendet werden.
Der E-Mail-Versand (Relay-Access) steht ausschliesslich authentifizierten Benutzern zur Verfügung und verlangt STARTTLS.
Auch dieser Test kann ganz einfach über die Kommandozeile durchgeführt werden. Alternativ können Sie natürlich auch sofort eine "echte" E-Mail über Ihren Mail-Client versenden. Bei einer Fehlersuche ist auch hier der Test über die Kommandozeile besser.


Zunächst muss der Benutzername des Mailbox-Benutzers und das dazugehörige Kennwort Base64 codiert werden.
Benutzen Sie dazu folgendes Kommando und notieren Sie die Ausgabe:

echo -n '[email protected]' | openssl base64
dGVzdEBleGFtcGxlLmNvbQ==

echo -n 'SicheresPasswort' | openssl base64
U2ljaGVyZXNQYXNzd29ydA==

Stellen Sie eine OpenSSL-Verbindung zum Mailserver auf Port 587 (Submission) her und verwenden Sie die folgenden Kommandos um eine ausgehende E-Mail zu versenden.
Verwenden Sie eine, zu Ihrer Domain gehörenden, Absender-E-Mail-Adresse (mail from: [email protected])
und senden Sie die E-Mail an eine gültige, externe E-Mail-Adresse (
rcpt to: GÜLTIGE-E-MAIL-ADRESSE).
openssl s_client -starttls smtp -connect mailserver.example.com:587
[...]
Start Time: 1551012088
Timeout   : 300 (sec)
Verify return code: 18 (self signed certificate)
---
250 DSN
ehlo example.net
250-mailserver.example.com
250-PIPELINING
250-SIZE 26214400
250-ETRN
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
auth login
334 VXNlcm5hbWU6
dGVzdEBleGFtcGxlLmNvbQ== (base64-Benutzername)
334 UGFzc3dvcmQ6
U2ljaGVyZXNQYXNzd29ydA== (base64-Passwort)
235 2.7.0 Authentication successful
mail from: [email protected]
250 2.1.0 Ok
rcpt to: GÜLTIGE-E-MAIL-ADRESSE
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
Subject: Test
Test E-Mail-Versand.
.
250 2.0.0 Ok: queued as A4D7326FD8
quit
221 2.0.0 Bye
closed

Wenn Sie die Meldung 250 2.0.0 Ok: queued as... erhalten und die Test-E-Mail empfangen haben, ist der Test erfolgreich abgeschlossen.

IMAP-Zugang einrichten

Info

Der Zugang zu den E-Mail-Postfächern ist über IMAP-Port 143 (TLS) und IMAPS-Port 993 (SSL) möglich.
Wenn Sie einen Web-Client (E-Mail-Webinterface) verwenden möchten, der Sieve-Mailregeln unterstützt, kann der Sieve-Port 4190 angegeben werden.

Die Konfiguration unseres Mailservers hält sich an sämtliche Standards. Daher kann grundsätzlich jeder gängige E-Mail-Client für die Benutzung verwendet werden. Egal ob Mozilla Thunderbird, Microsoft Outlook oder auch mobile E-Mail-Clients auf Android oder iOS.

Da unser Mailserver einen Webserver und einen SQL-Server enthält, lassen sich auch Web-Clients, wie z.B. SnappyMail oder Roundcube, sehr einfach integrieren.

Abschluss

Wenn der Open-Relay-Test erfolgreich verlief, die versendeten E-Mails ihr Ziel erreicht haben und die Authentifizierung funktioniert, ist Ihr Mailserver einsatzbereit.



Nützliche Befehle

Die folgenden Befehle sollten Ihnen im täglichen Umgang mit Ihrem Mailserver helfen.
Im Gegensatz zu einem anderen, weit verbreiteten, Betriebssystem, lassen sich die Vorgänge auf einem Linux-System hervorragend darstellen. Für eine Fehlerdiagnose empfehle ich daher den Befehl tail -f /var/log/syslog. Damit können Sie die System-Log-Datei in Echtzeit auswerten und schnell feststellen, wo ein Fehler auftritt.

Postfix - Warteschlange anzeigen

Listet den Inhalt der Postfix Warteschlange auf.

postqueue -p

Postfix - Warteschlange flushen

Versucht den Inhalt der Warteschlange erneut zuzustellen.

postfix flush

Postfix - Warteschlange löschen

Löscht den Inhalt der Warteschlange.

postsuper -d ALL

Dovecot - alle Benutzer anzeigen

Listet alle Dovecot-Benutzer auf.

doveadm user *.*

Dovecot - Quota Index für alle Benutzer neu berechnen

Erstellt den Quota-Index für alle Dovecot-Benutzer neu.

doveadm quota recalc -A

Dovecot - Quota Index für eine Domain anzeigen

Zeigt den Quota-Index für die angegebene Domain an.

doveadm quota get -u *@example.com

Dovecot - Mailboxen für eine Domain anzeigen

Listet alle Dovecot-Mailboxen der angegebenen Domain auf.

doveadm mailbox list -u *@example.com