116 lines
4.5 KiB
Markdown
116 lines
4.5 KiB
Markdown
# Zustellbarkeit ausgehender Mails
|
||
|
||
Die Anwendung setzt alle Kopfzeilen korrekt, aber ob eine Mail im Posteingang
|
||
oder im Spam landet, entscheidet sich überwiegend im DNS und beim Relay – nicht
|
||
im Anwendungscode. Diese Notiz trennt beides sauber.
|
||
|
||
## Was die Anwendung erledigt
|
||
|
||
| Kopfzeile | Warum |
|
||
|---|---|
|
||
| `Date` | Fehlt sie, werten praktisch alle Filter ab |
|
||
| `Message-ID` | Mit der Domain aus `SMTP_ENVELOPE_FROM`, damit sie zur DKIM-Signatur passt |
|
||
| `From` mit Anzeigename | RFC-konform kodiert über `email.headerregistry` |
|
||
| `Reply-To` | Optional, wenn Antworten woanders hin sollen |
|
||
| `Auto-Submitted: auto-generated` | RFC 3834 – unterdrückt Abwesenheitsschleifen |
|
||
| `X-Auto-Response-Suppress: All` | Dasselbe für Exchange/Outlook |
|
||
| EHLO-Hostname | Aus `SMTP_HELO_HOSTNAME` statt der Container-ID |
|
||
| Envelope-From getrennt vom `From` | SPF wird gegen den Envelope geprüft |
|
||
|
||
Der Versand wiederholt sich bei temporären Fehlern mit wachsendem Abstand
|
||
(2 s, 4 s, 8 s). Bei permanenter Ablehnung – Empfänger unbekannt, Absender
|
||
abgelehnt, Authentifizierung fehlgeschlagen – bricht er sofort ab, statt das
|
||
Relay weiter zu belasten.
|
||
|
||
## Was du im DNS einrichten musst
|
||
|
||
Ohne diese drei Einträge landen Mails auch bei perfektem Code im Spam. Alle
|
||
beziehen sich auf die Domain aus `SMTP_ENVELOPE_FROM`.
|
||
|
||
**SPF** – erlaubt deinem Relay, für die Domain zu senden:
|
||
|
||
```
|
||
example.de. IN TXT "v=spf1 mx a:mail.example.de -all"
|
||
```
|
||
|
||
`-all` (hard fail) ist strenger als `~all` und wird von Empfängern besser
|
||
bewertet. Setze es erst, wenn du sicher bist, dass alle legitimen Absender
|
||
erfasst sind.
|
||
|
||
**DKIM** – signiert ausgehende Mails. Die Signatur erzeugt das Relay, nicht
|
||
diese Anwendung. In Postfix über OpenDKIM oder rspamd, in mailcow ist es
|
||
eingebaut. Der öffentliche Schlüssel gehört ins DNS:
|
||
|
||
```
|
||
selector._domainkey.example.de. IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBg..."
|
||
```
|
||
|
||
Wichtig: Die signierende Domain (`d=` in der Signatur) muss zur Domain im
|
||
`From`-Header passen, sonst schlägt die DMARC-Ausrichtung fehl.
|
||
|
||
**DMARC** – sagt Empfängern, was bei Fehlschlägen passieren soll:
|
||
|
||
```
|
||
_dmarc.example.de. IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.de; adkim=s; aspf=s"
|
||
```
|
||
|
||
Fang mit `p=none` an und wertet die Reports ein paar Wochen aus, bevor du auf
|
||
`quarantine` oder `reject` gehst.
|
||
|
||
**PTR (Reverse DNS)** – die IP deines Relays muss auf einen Namen auflösen, der
|
||
vorwärts wieder auf dieselbe IP zeigt. Bei Hetzner setzt du das im
|
||
Cloud-Console-Interface bzw. im Robot. Fehlt der PTR, weisen einige große
|
||
Anbieter direkt beim `MAIL FROM` ab.
|
||
|
||
## Ausrichtung von From und Envelope-From
|
||
|
||
DMARC verlangt, dass mindestens eine der beiden Prüfungen *ausgerichtet* ist:
|
||
|
||
- **SPF-Ausrichtung:** Domain in `SMTP_ENVELOPE_FROM` = Domain in `SMTP_FROM`
|
||
- **DKIM-Ausrichtung:** signierende Domain = Domain in `SMTP_FROM`
|
||
|
||
Mit `adkim=s; aspf=s` im DMARC-Record verlangst du exakte Übereinstimmung
|
||
(nicht nur die Organisationsdomain). Das ist strenger und sicherer, bedeutet
|
||
aber: `bounces@example.de` und `einkaufsapp@example.de` sind ausgerichtet,
|
||
`bounces@bounce.example.de` wäre es nicht mehr.
|
||
|
||
## Testen
|
||
|
||
Vor dem ersten echten Versand:
|
||
|
||
```bash
|
||
# Verbindung zum Relay prüfen, ohne etwas zu senden
|
||
curl -s -b cookies.txt localhost:8000/api/admin/mail/check | jq
|
||
|
||
# Testnachricht auslösen
|
||
CSRF=$(grep ea_csrf cookies.txt | awk '{print $7}')
|
||
curl -s -b cookies.txt -H "X-CSRF-Token: $CSRF" \
|
||
-X POST localhost:8000/api/admin/mail/test \
|
||
-H 'Content-Type: application/json' \
|
||
-d '{"to":"dein-postfach@example.de"}'
|
||
|
||
docker compose logs --tail=20 api
|
||
```
|
||
|
||
Für eine unabhängige Bewertung eignet sich ein Dienst, der dir eine
|
||
Wegwerf-Adresse gibt und die eingehende Mail auf SPF, DKIM, DMARC, PTR und
|
||
Inhaltsmerkmale prüft – etwa `mail-tester.com`. Alles unterhalb von 8/10 lohnt
|
||
das Nachbessern.
|
||
|
||
Achte in der Auswertung besonders auf:
|
||
|
||
- `SPF: pass` mit der Envelope-Domain
|
||
- `DKIM: pass` mit `d=` gleich der From-Domain
|
||
- `DMARC: pass`
|
||
- kein Eintrag auf Spamhaus/Barracuda für deine Relay-IP
|
||
|
||
## Häufige Ursachen für Spam-Einstufung
|
||
|
||
| Symptom | Ursache |
|
||
|---|---|
|
||
| Landet bei Gmail im Spam, sonst nirgends | Fehlender oder falscher PTR-Eintrag |
|
||
| DKIM `pass`, DMARC `fail` | Signierende Domain weicht von der From-Domain ab |
|
||
| SPF `softfail` | Relay-IP nicht im SPF-Record der Envelope-Domain |
|
||
| Alles `pass`, trotzdem Spam | Neue Domain ohne Sendereputation – das gibt sich nach einigen Wochen regelmäßigen Versands |
|
||
| Outlook/Hotmail blockt | Microsoft verlangt oft eine Anmeldung beim SNDS-Programm |
|