Warum ein eigenes Mailrelay?
In vielen Infrastrukturen gibt es Systeme, die E-Mails versenden müssen, aber
keinen eigenen Mailserver betreiben sollen oder dürfen:
- Monitoring & Alerting (Checkmk, Prometheus, …)
- Applikationen, die nur SMTP sprechen
- Legacy-Systeme
- Containerisierte Workloads ohne Mail-Stack
Ein klassischer SMTP-Relay-Server löst genau dieses Problem:
lokal annehmen, zentral weiterleiten, sauber kontrollieren.
Was ist Mailrelay?
Mailrelay ist ein schlanker, containerisierter SMTP-Relay auf Basis von Postfix.
Er nimmt E-Mails intern auf Port 25 entgegen und leitet sie
authentifiziert und verschlüsselt an einen Upstream-Mailserver (Smarthost) weiter.
Wichtig: Mailrelay ist bewusst kein vollständiger Mailserver
(keine Postfächer, kein Spamfilter, kein IMAP/POP3).
Er ist dafür gedacht, E-Mails aus internen Systemen zuverlässig an einen Smarthost weiterzuleiten.
Zentrale Eigenschaften
- 📦 Docker-Container (multi-arch: amd64 & arm64)
- 🔒 TLS-gesicherte Weiterleitung
- 🔑 SMTP-AUTH (SASL) via Docker Secrets
- 📤 Fixe Absenderadresse erzwingbar (Rewrite, verhindert Rejections)
- 📜 Vollständige Logs über
docker logs - 🚫 Kein Open Relay (sichere Defaults)
- 🧱 Für interne Netze gedacht (Mynetworks)
- 🚨 Alerting bei Zustell- und Identitätsfehlern (optional)
- 🎟 Optional: Alerts als Zammad-Tickets statt Alert-Mails
Installation mit Docker Compose
Docker Hub: onesystems/mailrelay
Verzeichnisstruktur
mailrelay/
├── docker-compose.yml
└── secrets/
├── relay_sasl_pass.txt
└── zammad_token.txt
docker-compose.yml
services:
mailrelay:
image: onesystems/mailrelay:latest
container_name: mailrelay
restart: unless-stopped
# ⚠️ Port 25 nur intern/vertrauenswürdig exponieren (Firewall!)
ports:
- "25:25"
environment:
HOSTNAME_FQDN: "mailrelay.example.local"
# Upstream relay
RELAY_HOST: "smtp.example.com"
RELAY_PORT: "587"
RELAY_TLS: "required"
# Sender handling (verhindert "Sender address rejected")
DEFAULT_FROM: "noreply@example.com"
FORCE_DEFAULT_FROM: "1"
# Allowed source networks (kein Open Relay)
MYNETWORKS: "127.0.0.0/8,10.0.0.0/8,192.168.0.0/16"
# SASL auth
RELAY_SASL_USER: "smtp-user@example.com"
RELAY_SASL_PASS_FILE: "/run/secrets/relay_sasl_pass"
# Alerting (optional)
ALERT_ENABLED: "1"
ALERT_MATCH: "invalid_user,sendas_denied,postfix_bounced,postfix_deferred"
# Zammad ticketing (optional, statt Alert-Mails)
ALERT_ZAMMAD_ENABLED: "1"
ZAMMAD_BASE_URL: "https://zammad.example.com"
ZAMMAD_TOKEN_FILE: "/run/secrets/zammad_token"
ZAMMAD_GROUP: "Support"
ZAMMAD_STATE: "new"
ZAMMAD_PRIORITY_ID: "2" # 1=low, 2=normal, 3=high
ZAMMAD_CUSTOMER_EMAIL: "mailrelay@example.local"
ZAMMAD_TAGS: "mailrelay,postfix,alert"
# Debugging
DEBUG: "0"
secrets:
- relay_sasl_pass
- zammad_token
volumes:
- postfix_spool:/var/spool/postfix
- postfix_state:/var/lib/postfix
- /etc/ssl/certs:/etc/ssl/certs:ro
secrets:
relay_sasl_pass:
file: ./secrets/relay_sasl_pass.txt
zammad_token:
file: ./secrets/zammad_token.txt
volumes:
postfix_spool:
postfix_state:
Secrets anlegen
SMTP-Passwort (Secret) (nur das Passwort, kein Username)
echo "SMTP_PASSWORD_HERE" > secrets/relay_sasl_pass.txt chmod 600 secrets/relay_sasl_pass.txt
Zammad API Token (Secret) (Token mit Berechtigung Tickets zu erstellen)
echo "ZAMMAD_API_TOKEN_HERE" > secrets/zammad_token.txt chmod 600 secrets/zammad_token.txt
Starten
docker compose up -d
Logs prüfen:
docker logs -f mailrelay
Beim erfolgreichen Start steht z.B.:
MAILRELAY: started (relayhost=[smtp.example.com]:587, sasl=yes)
Verwendung
SMTP-Ziel für Applikationen
Alle internen Systeme senden an:
Server: mailrelay.example.local Port: 25 TLS: nein AUTH: nein
Mailrelay übernimmt zentral:
- Authentifizierung am Smarthost
- TLS (verschlüsselte Weiterleitung)
- Absenderkontrolle (Rewrite, optional erzwungen)
- Sauberes Logging
Test-Mail senden (Beispiel)
echo "Test Mail" | mail -s "Mailrelay Test" user@example.com
Architekturübersicht
[ App / Monitoring / Host ]
|
| SMTP (25, intern)
v
[ Mailrelay ]
|
| SMTP + TLS + AUTH (Upstream)
v
[ Mailserver / Smarthost ]
Vorteile gegenüber direktem SMTP-Versand
| Problem | Lösung durch Mailrelay |
|---|---|
| SMTP-Credentials überall verteilt | Zentral im Container (Secrets) |
| Unterschiedliche Mail-Setups | Einheitlicher Versand über einen Relay-Endpunkt |
| Fehlende Logs / schwierige Fehlersuche | Zentrale, vollständige Logs via docker logs |
| Absender nicht kontrollierbar | Rewrite/Forced From verhindert Spoofing & Upstream-Rejections |
| OAuth nicht möglich / Passwort-Handling unbequem | Vorbereitung für Teil 2: Mailrelay + SMTP OAuth Relay: SMTP ohne Passwort, bereit für Microsoft 365 |
Sender Handling (wichtig)
Viele Smarthosts lehnen E-Mails ab, wenn der Absender nicht zur authentifizierten Identität passt.
Typische Fehlermeldung:
553 5.7.1 Sender address rejected: not owned by user
Mailrelay kann das abfangen:
- Wenn
DEFAULT_FROMgesetzt ist, werden lokale/technische Absender (z.B.root,daemon) auf diese Adresse umgeschrieben. - Falls nicht gesetzt, wird (je nach Setup) sinnvoll auf
RELAY_SASL_USERzurückgefallen. - Mit
FORCE_DEFAULT_FROM=1kann das Verhalten erzwungen werden, um Upstream-Rejections zu vermeiden.
Alerting & Monitoring (neu)
Ein Relay, das Mails stillschweigend nicht zustellt, ist im Betrieb genau so nützlich wie ein Rauchmelder ohne Batterie.
Darum bringt Mailrelay optional ein internes Alerting mit:
Es überwacht kontinuierlich den Postfix-Logstream und erkennt actionable Failures.
Welche Fehler werden erkannt?
- invalid_user – Zieladresse/Identität existiert upstream nicht
- sendas_denied – Absender darf nicht als diese Adresse senden (häufig bei Microsoft 365)
- postfix_bounced – Zustellung dauerhaft fehlgeschlagen
- postfix_deferred – Temporärer Fehler (Greylisting, Upstream-Problem, Timeout, …)
Die Erkennung ist regex-basiert und läuft direkt im Container. Alerts werden zusätzlich
throttled, damit bei Serienfehlern nicht alles eskaliert.
Alert-Flow
Postfix Logeintrag
↓
Interner Log-Watcher
↓
Fehler erkannt & klassifiziert
↓
Alert / Ticket
Optional: Zammad-Integration (Tickets statt Alert-Mails)
Statt Alerts per E-Mail zu verschicken (und dann wieder per E-Mail zu überwachen), kann Mailrelay
direkt Tickets in Zammad erstellen.
Das ist vor allem in produktiven Umgebungen angenehm, weil Fehler dort landen, wo sie hingehören:
im Support-Workflow.
Zammad Ticket Details
Jedes Ticket enthält (best effort):
- Fehlertyp (z.B.
postfix_bounced,invalid_user) - Queue-ID
- Absender und Empfänger
- Originale Postfix-Fehlermeldung
- Relevanten Log-Kontext
- Fix-Hinweise für bekannte Identitätsprobleme
Das macht Mailrelay geeignet für produktiven Einsatz, ohne dass Zustellprobleme “leise” bleiben.
Sicherheit & Kontrolle
- Versand nur aus definierten Netzwerken (
MYNETWORKS) - Kein offenes Relaying (Safe Defaults)
- TLS erzwingbar (
RELAY_TLS=required) - Absender-Rewriting verhindert Spoofing & Upstream-Rejections
- Debug-Modus für Fehleranalyse (
DEBUG=1)
Hinweis: Mailrelay sollte ausschliesslich in internen oder abgeschotteten Netzsegmenten betrieben werden.
Port 25 nicht ungefiltert ins Internet exponieren.
Wann Mailrelay nicht passt
- Wenn Benutzer Postfächer benötigen (IMAP/POP3)
- Wenn eingehende E-Mails direkt aus dem Internet angenommen werden sollen
- Wenn ein kompletter Mailstack (Spamfilter, DKIM/DMARC-Signing, etc.) benötigt wird


[…] Dieser Beitrag ist Teil 2 der Mailrelay-Serie und baut direkt auf Teil 1 auf. Installation, Grundkonfiguration und Sicherheitsaspekte von Mailrelay werden dort erklärt: Teil 1: Ein schlanker SMTP-Relay-Container für moderne Infrastrukturen […]