Infrastruktur
„250 OK“ heißt nicht zugestellt - warum eure Mails im Spam landen
Unser Server sagte „250 OK“. Der Empfänger bekam trotzdem nichts. Die ganze Spurensuche mit echten DNS-Records - und warum „angenommen“ nicht „zugestellt“ heißt.
Unser Mailserver hat sauber „250 OK“ geantwortet. Der Empfänger bekam trotzdem nichts. Kein Bounce, keine Fehlermeldung, kein Hinweis, die Mail war einfach weg. Hier ist die ganze Spurensuche, mit den echten DNS-Records, und am Ende eine Lehre, die fast jeden Betrieb betrifft, der automatisch Mails verschickt.
Wir haben neulich eine kleine Pipeline gebaut: Ein Programm erstellt einen PDF-Report und schickt ihn automatisch per E-Mail an den Empfänger. Nichts Wildes, sowas läuft im Hintergrund von tausend Firmen: Rechnungen, Mahnungen, Bestellbestätigungen, Reports. Erster Testlauf. Programm sagt: verschickt. Postfach des Empfängers: leer.
Kein Fehler im Log. Im Gegenteil, der Mailserver hatte die Annahme ausdrücklich quittiert. Genau das macht diese Sorte Bug so heimtückisch: Alles meldet Erfolg, und trotzdem kommt nichts an. Wer hier nicht weiß, wo er hinschauen muss, dreht stundenlang an der falschen Schraube.
Schritt 1: Was „250 OK“ wirklich bedeutet
Beim Versand über unseren Hetzner-Mailserver kam diese Antwort zurück:
250 OK id=1wZmrd-000Niu-2o
250 ist im SMTP-Protokoll der Erfolgs-Code. Klingt nach „erledigt“. Ist es aber nicht. Und das ist der erste und wichtigste Punkt:
250 OK heißt nur: „Ich, der Server, habe diese Mail angenommen.“ Es heißt nicht: „Die Mail liegt im Postfach des Empfängers.“ Zwischen Annahme und Zustellung liegt die ganze Reise, und auf dieser Reise kann die Mail noch verworfen, abgelehnt oder in die Quarantäne (= Spam) geschoben werden.
Das Gleiche gilt für jedes „erfolgreich gesendet“ in einer Software, jedes grüne Häkchen, jede API, die success: true zurückgibt. Der absendende Server bestätigt die Übergabe, nicht den Empfang. Wer Zustellung garantieren will, muss am echten Zielpostfach nachsehen, alles andere ist Hoffnung.
Also: Mail angenommen, aber nicht in der Inbox. Sie muss unterwegs aussortiert worden sein. Bleibt die Frage: warum?
Schritt 2: Die DNS-Records lesen
E-Mail-Zustellung wird zu einem überraschend großen Teil im DNS entschieden, in den öffentlichen Einträgen der Domain. Drei davon sind hier entscheidend. Schauen wir sie der Reihe nach an.
SPF legt fest, welche Server im Namen der Domain Mails verschicken dürfen:
v=spf1 a a:mail.your-server.de mx include:_spf.hetzner.com include:spf.koetting.io ~all
Lesart: Erlaubt sind unter anderem mail.your-server.de (das ist Hetzner) und alles unter _spf.hetzner.com. Heißt: Der Hetzner-Server, über den wir gesendet haben, ist per SPF ausdrücklich autorisiert. SPF besteht. Erste Spur, und sie führt scheinbar ins Leere, denn wenn SPF passt, müsste die Mail doch durchgehen. Tut sie aber nicht. Geduld.
MX sagt, wohin Mails für die Domain geliefert werden, also der Posteingang:
mail.koetting.io
Das ist ein Mailcow-Server. Wichtiges Detail für später: Eingang und Versand laufen hier über zwei verschiedene Systeme. Eingehende Post über Mailcow, der Test-Versand lief über Hetzner.
DKIM ist eine kryptografische Unterschrift. Der versendende Server signiert jede Mail mit einem privaten Schlüssel; der passende öffentliche Schlüssel steht im DNS, hier unter:
dkim._domainkey.koetting.io
Und jetzt kommt der erste echte Stolperstein: Dieser DKIM-Schlüssel gehört zu Mailcow. Mailcow hält den privaten Schlüssel und signiert damit. Hetzner hat diesen Schlüssel nicht. Wenn wir über Hetzner versenden, kann die Mail also gar nicht mit der gültigen koetting.io-Signatur unterschrieben werden.
DMARC ist die Klammer um das Ganze, die Regel, was passieren soll, wenn die Prüfung wackelt:
v=DMARC1; p=quarantine; sp=quarantine; pct=50; adkim=r; aspf=r
Übersetzt: p=quarantine heißt „wenn die Prüfung nicht besteht, schieb die Mail in die Quarantäne“, also in den Spam-Ordner, nicht in die Inbox. Die anderen Teile (adkim=r, aspf=r) erklären wir gleich, die sind der Schlüssel zur Auflösung.
Schritt 3: Der Denkfehler, „SPF besteht doch!“
Hier wäre fast Schluss gewesen. SPF besteht ja. Warum reicht das nicht?
Weil DMARC nicht fragt: „Hat irgendeine Prüfung bestanden?“ DMARC fragt: „Hat eine Prüfung bestanden, die auch zur sichtbaren Absender-Domain passt?“ Dieses „passt zur Absender-Domain“ hat einen Namen, und es ist der ganze Trick an der Geschichte: Alignment.
Was Alignment bedeutet
Eine E-Mail hat nämlich nicht eine Absender-Adresse, sondern technisch gesehen zwei:
- Das
From:, das ihr im Mailprogramm seht. Sagen wir:pia@koetting.io. - Den Envelope-Absender (
MAIL FROM), eine technische Adresse fürs Protokoll, die ihr nie zu Gesicht bekommt, und die auf einem fremden Relay schnell auf die Relay-Domain umgeschrieben wird (z. B. etwas mityour-server.de).
SPF prüft den Envelope-Absender. DKIM prüft die Domain in der Signatur. DMARC sagt nun: Eine bestandene Prüfung zählt nur dann, wenn die geprüfte Domain mit der From:-Domain übereinstimmt. Genau das ist Alignment.
Damit wird klar, warum „SPF besteht“ hier nichts wert war:
- DKIM-Alignment? Nein. Hetzner signiert nicht mit dem koetting.io-Schlüssel (der liegt auf Mailcow). Es gibt also gar keine ausgerichtete koetting.io-Signatur. Durchgefallen.
- SPF-Alignment? Wackelig. SPF an sich besteht, aber sobald der Envelope-Absender beim Versand über das fremde Relay auf eine
your-server.de-Adresse umgeschrieben wird, passt die geprüfte Domain nicht mehr zum sichtbarenkoetting.io, und das Alignment bricht.
DMARC besteht aber nur, wenn mindestens eine der beiden Prüfungen ausgerichtet besteht. DKIM: durchgefallen. SPF: nicht zuverlässig ausgerichtet. Ergebnis: DMARC fällt durch. Und p=quarantine sagt dann klipp und klar: ab in den Spam.
Da war er, der ganze Fall in einem Satz: Hetzner nimmt die Mail an (250 OK), aber weil die Mail keine ausgerichtete koetting.io-Signatur trägt, sortiert der Empfänger sie in die Quarantäne. Beides stimmt gleichzeitig. Genau deshalb sah „erfolgreich gesendet“ und „nichts angekommen“ wie ein Widerspruch aus, und war keiner.
Kurzer Einschub: relaxed vs. strict
Die r in adkim=r und aspf=r steht für relaxed. Im relaxed-Modus reicht es, wenn die organisatorische Domain übereinstimmt, mail.koetting.io gilt als ausgerichtet zu koetting.io, Subdomains sind also erlaubt. Im strict-Modus (s) müsste es exakt dieselbe Domain sein. Relaxed ist das Übliche und Vernünftige; es verzeiht Subdomains, aber eben keine fremde Domain. your-server.de ist und bleibt eine fremde Domain, auch relaxed rettet das nicht.
Schritt 4: Der Fix
Die Lösung folgt direkt aus der Diagnose und ist fast schon unspektakulär:
Versende über den Server, der deinen DKIM-Schlüssel hält.
Der Schlüssel liegt auf Mailcow. Der MX-Eintrag zeigt auf Mailcow. Also gehört auch der Versand auf Mailcow, nicht auf ein zweites, fremdes Relay. Wir haben den Versand von Hetzner auf mail.koetting.io:465 umgestellt. Mailcow signiert ausgehende Mails automatisch mit dem koetting.io-DKIM-Schlüssel. Damit:
- DKIM ist gültig und ausgerichtet (
koetting.iosigniert fürkoetting.io), - DMARC besteht,
- die Mail landet in der Inbox.
Verifiziert, nicht vermutet, der Testversand über Mailcow ergab:
250 2.0.0 Ok: queued
und diesmal lag die Mail tatsächlich im Postfach. Nicht im Spam. In der Inbox.
Die Lehre dahinter ist allgemeiner als unser konkreter Fall: Wenn MX und DKIM auf einem System liegen, ist es selten eine gute Idee, ausgehende Mail über ein anderes System zu schicken. Ein zweiter Versandweg ist ein zweiter Ort, an dem Alignment kaputtgehen kann.
Die drei Lehren, kurz und einprägsam
- „250 OK“ / „erfolgreich gesendet“ ist nicht zugestellt. Jede Erfolgsmeldung beim Versand bestätigt nur die Annahme, nicht das Ankommen im Postfach. Belegen lässt sich Zustellung nur am echten Zielpostfach.
- SPF zu bestehen reicht nicht. DMARC verlangt Alignment, eine bestandene Prüfung, deren Domain zur sichtbaren
From:-Adresse passt. „Irgendwo erlaubt“ ist nicht dasselbe wie „ausgerichtet bestanden“. - Sende über den Server, der deinen DKIM-Schlüssel hält. Liegen MX und DKIM auf einem System, gehört der Versand dorthin. Zweiter Relay = zweite Fehlerquelle.
So prüfst du es bei dir selbst
Du brauchst dafür keine Spezialsoftware. Drei Schritte:
1. Lies deine eigenen DNS-Records. Schau dir deinen DMARC-Eintrag an (_dmarc.deinedomain.de). Steht da p=quarantine oder p=reject, ist die Politik scharf, dann müssen deine Mails sauber ausgerichtet bestehen, sonst landen sie im Spam oder werden ganz abgewiesen. Steht da p=none, passiert erstmal nichts, aber dann weißt du auch nicht, ob deine Zustellung gesund ist. (p=none ist zum Beobachten gedacht, nicht als Dauerzustand.)
2. Schick dir selbst eine Testmail, an ein Gmail- oder GMX-Postfach, von genau dem System, das in echt deine Mails verschickt. In Gmail: Mail öffnen, die drei Punkte, „Original anzeigen“. Ganz oben steht dann:
SPF: PASS
DKIM: PASS
DMARC: PASS
Drei mal PASS heißt: Zustellung ist auf der sicheren Seite. Steht bei DKIM oder DMARC ein FAIL, hast du genau das Problem aus diesem Artikel, und jetzt weißt du, wo du suchen musst.
3. Für den schnellen Rundum-Blick gibt es Dienste wie mail-tester.com: Mail an eine generierte Adresse schicken, Punktzahl ablesen, im Detail sehen, welcher Mechanismus hakt. Praktisch als erster Check, die eigentliche Diagnose ist aber das, was wir oben gemacht haben: Records lesen, Alignment verstehen.
Warum wir das aufschreiben
Wir sind über diesen Fall gestolpert, weil wir beim Betrieb genau auf solche Dinge achten: SPF, DKIM, DMARC, ob die Mails eines Betriebs überhaupt sauber ankommen. Es ist erstaunlich, wie viele Firmen seit Jahren Rechnungen und Mahnungen verschicken, von denen ein guter Teil leise im Spam versickert, ohne dass es je jemand merkt. Kein Fehler im System, nur ein 250 OK, dem niemand widersprochen hat.
Wie wir Mail-Zustellung für einen Betrieb einrichten und laufend prüfen, steht auf koetting.io/de/betrieb/mail.
Wenn du wissen willst, wie es bei dir steht, schau uns über die Schulter: Unter koetting.io/de/kontakt sagen wir dir schwarz auf weiß, ob deine Mails ankommen.
So sorgen wir im Betrieb dafür, dass Mails wirklich ankommen und nicht nur angenommen werden: Mail im Betrieb