Wieder einmal versuche ich aus einem Fehler schlau zu werden und lerne allerlei Kram, den ich nie glaubte, wissen zu müssen. Aber von Anfang an: Auf einem Server bei all-inkl.com liegen in einem Account zwei Websites. Die beiden Websites gehören zwar zur gleichen Kette, aber von zwei unterschiedlichen Betreibern. Nun beschwerte sich der Kunde A, dass er Mails von Kunde B bekommt. Bei näherer Betrachtung der Mails waren das aber ausschließlich Rückläufer, also Fehlermeldungen des Mailservers. Also machte ich mich auf die Suche, was hier schiefgelaufen ist. Was das Ganze mit WordPress, PHPMailer und dem Hoster zu tun hat, erfahrt ihr im folgenden Artikel.
Zuerst müssen wir das Mail-Format verstehen. Es ist ziemlich simpel, hat aber einige Fallstricke. Die Grundstruktur ist eigentlich ganz einfach: Nur Textzeilen, jede Zeile ist eine Konfiguration, dann eine Leerzeile, dann der Inhalt.
Nun gibt es aber einige sehr wichtige Details, die nicht unbedingt jeder kennt. Im Header kann neben den bekannten „To:“, „From:“, „CC:“ und „BCC:“ auch noch mehr definiert werden, zum Beispiel an wen die Rückläufer gehen („Return Path“) oder wer der technische Absender ist („Sender“).
Erinnerung: To: und From: sind nur zur Anzeige gedacht. Technisch werden sie nicht genutzt, dafür gibt es Envelope To/Envelope Sender.
Da ja nur die Rückläufer falsch ankamen, schaute ich mir den Quelltext der Mails an und stellte fest, dass der Return-Path tatsächlich an die falsche Domain ging. Aber wieso? Im Kontaktformular war nirgendwo die falsche Domain drin. Da es sich um einen Klon der ersten Website handelte, checkte ich auch nochmal die gesamte Datenbank, aber auch hier kein Fund der falschen Domain. Irgendetwas in der Kette fügte also den falschen Return-Path hinzu. Das Kontaktformular war es nicht, also ging ich das Ganze etwas strukturierter an:
Schritt 1: Health-Check installieren
In der Werkzeuge-Sektion gibt es die Möglichkeit eine Testmail zu versenden. Damit konnte ich prüfen, ob das Ganze ein Problem des Kontaktformular-Plugins war oder generell galt. Und siehe da: das Problem war immer noch da.
Schritt 2: Was passiert, wenn WordPress eine Mail sendet?
Da Schritt 1 gezeigt hat, dass das Problem auch dann auftritt, wenn nur WordPress beteiligt ist, muss das Problem also weiter „hinten“ in der Kette stattfinden. WordPress nutzt dazu seine wp_mail()-Funktion, was wiederum eine Helfer-Funktion ist, um die PHPMailer-Komponente zu nutzen.
Schritt 3: Bin ich der einzige mit dem Problem?
Wahrscheinlich hatten andere das Problem auch schon, also suchte ich mal im Ticket-System. Meine Vermutung war, dass der Return-Path automatisch hinzugefügt wird, aber aus irgendeinem Grund passierte das nicht korrekt. Ich hatte den Verdacht, dass der technische Absender nicht gesetzt wird, aber gesetzt werden müsste. Und ich wurde fündig: In Ticket Nummer 37736 wurde berichtet, dass es Probleme bei manchen Hostern gibt, wenn der Sender (ungleich „From“!) automatisch gefüllt wird. Der dazugehörige Changeset setzt dann den Parameter vom PHPMailer auf false
, damit dies nicht mehr passiert.
Interessant ist die Erklärung im Unit Test des Patch:
Correctly setting the Sender requires knowledge that is not available to Core. An incorrect value will often lead to messages being rejected by the receiving MTA, so it’s the admin’s responsibility to set it correctly.
Der Core kann nicht wissen, was gesetzt werden müsste und tut es daher lieber nicht. Das erklärt, warum der Wert nicht gesetzt wird. Aber wer setzt ihn dann? Kann ja nur noch der MTA (Mail Transfer Agent) sein, also fragen wir mal den Hoster-Support, was etwas zäh war, weil die Gegenseite ständig davon sprach, dass sie alles richtig machen würden und wenn wir (WordPress, PHPMailer) das auch tun würden, alles klappen würde. Auf meine konkrete Frage, ob ein Trennen der Websites in zwei Konten helfen würde, antworteten sie erst ganz am Ende …
Hier mal die Essenz der Antworten:
Der Server setzt lediglich einen eigenen Return-Path wenn dieser in der generierten Mail nicht richtig gesetzt ist. Dies tut er zum „Selbstschutz“ um eventuelle Bounce-Mails loswerden zu können.
Okay. Aber was bedeutet „richtig“ in diesem Kontext? Eine direkte Konfiguration bietet PHPMailer gar nicht an. Und indirekt über den Sender-Wert ist durch WordPress nicht umgesetzt. Und nun?
wenn der Return Pfad abweicht und info@ hinterlegt ist so hat der Server diesen Standardmäßig gesetzt, weil in Ihrem Script kein korrektes From hinterlegt wurde.
Hier wurde ich dann richtig sauer, ich mir viel Mühe gemacht hatte alles zu erklären und inklusive Links zu Github und Trac zu untermauern. Traurig, dass dann nur so ein zusammenhangloser Mist zurückkam.
der Server nimmt eine Domain aus dem KAS Account und stellt ein info@ voran. Das ist aber nur der Fall, wenn das Mailscript nicht korrekt konfiguriert ist. Der Return Pfad und oder das From muss in diesem gesetzt werden. Es empfiehlt sich auch als Methode SMTP zu verwenden da sonst sehr viele E-Mails im SPAM Ordner der Empfänger landen werden.
Implizit kann man hier schließen, dass das Trennen der Accounts wohl helfen würde. Alternativ können wir auch den Sender-Wert entsprechend dem From-Wert setzen und zwar über den phpmailer_init-Filter – eine direkte Möglichkeit für den Return-Path gibt es wie gesagt in PHPMailer nicht (mehr):
/** * Add Sender like from to PHPMailer object * * @param [object] $phpmailer Altered PHPMailer object. */ function tl_add_phpmailer_sender( $phpmailer ) { $phpmailer->Sender = $phpmailer->From; } add_action( 'phpmailer_init', 'tl_add_phpmailer_sender', 99 );
Die PHPMailer-Komponente hat das mal als Standard versucht, aber sowohl in WordPress als auch PHPMailer wurden sofort die Probleme berichtet, die das mit sich brachte.
Die Änderung in PHPMailer wurde dann wieder reverted.
Aber die Frage taucht immer mal wieder auf. Zuletzt hier: Ticket #49687
Interessant auch, was der Wikipedia-Eintrag zum technischen Absender schreibt:
Das Sender-Feld enthält eine einzelne Absenderadresse und gibt damit die für die tatsächliche Übertragung der E-Mail verantwortliche Mailbox an. Enthält das From-Feld mehrere Adressen, so muss das Sender-Feld angegeben werden. Ansonsten ist es optional und kann verwendet werden, um einen, vom Urheber der Mail abweichenden technischen Absender anzugeben. Beispiel: Die E-Mail-Adresse eines Sekretärs, der eine E-Mail nach Diktat des Chefs verschickt, könnte ins Sender-Feld, die E-Mail-Adresse des Chefs ins From-Feld eingetragen werden. Manche Issue-Tracking-Systeme oder Mailinglistenprogramme verwenden das Sender-Feld, um den technischen Absender anzugeben. Sind Verfasser einer E-Mail und technischer Absender identisch, soll das Sender-Feld nicht verwendet werden.
So langsam ergibt sich also ein stimmiges Bild. Der „Sender“ ist nur gedacht für den Fall, dass es einen Unterschied zur From-Adresse gibt. Oder mehrere „From“-Adressen existieren. Standardmäßig sollte es leer gelassen werden, da optional. Wird es befüllt, obwohl die Bedingungen nicht passen, kann dies dazu führen, dass gar keine Mails versendet werden.
Warum ist das nötig? Damit etwaige Rückläufer auch bei der richtigen Person ankommen. Nämlich beim technischen Versender. Das deckt sich dann auch mit der Doku vom PHPMailer zum Sender:
This will usually be turned into a Return-Path header by the receiver, and is the address that bounces will be sent to. If not empty, will be passed via -f to sendmail or as the ‚MAIL FROM‘ value over SMTP.
Da meine Mails technisch gesehen also korrekt waren (From-Adresse genutzt) und der „Sender“ bei nur einem Absender nicht gesetzt werden muss, stellt sich mir nun die Frage, was jetzt wirklich die Erklärung bzw. beste Lösung ist.
Den „Sender“ trotzdem setzen (entweder konkret oder einfach auf den From-Wert) sorgt für das korrekte Verhalten, zumindest bei all-inkl.com, scheint aber nicht der technisch korrekte Weg zu sein. Auch wenn der Return-Path jetzt korrekt im Quelltext der Mail ist. Ein Trennen der Accounts könnte wohl auch helfen, da all-inkl.com standardmäßig eine Domain aus dem Account nimmt – wenn nur eine da ist, kann ja nur die richtige genutzt werden. Allerdings muss dann auch eine Adresse mit info@ genutzt werden, was nirgendwo dokumentiert ist.
Und zuletzt hier beim Schreiben des Artikels stellt sich mir die Frage, ob der Supporter vom Hoster mir die ganze Zeit mitteilen wollte, dass der From-Wert deshalb nicht korrekt gesetzt ist, weil die Adresse wordpress@, die sowohl das Kontaktformular, als auch das Health-Check-Plugin als Absender nutzen, nicht als Adresse angelegt ist. Aber nach einem schnellen Test kann ich auch das ausschließen. Auch mit existierender wordpress@-Adresse wird der Return-Path nicht korrekt gesetzt.
Das ist ja auch datenschutztechnisch relevant, weil die Mails in den Rückläufern komplett zitiert werden und somit gegebenenfalls Daten via Rückläufer-Mail an den falschen Empfänger gehen. Falls ihr also mehrere Kunden/Websites in einem Account habt, die von unterschiedlichen Betreibern genutzt werden, solltet ihtr euch das wohl mal ansehen.
Sollte also wirklich all-inkl.com wirklich so falsch liegen in ihrer Konfiguration oder habe ich irgendwo einen Denkfehler gemacht? Ich freue mich über eure Hinweise in den Kommentaren!
Vielen Dank für den interessanten Beitrag. Mir ist jedoch noch nicht ganz klar ob die Problematik nur in Zusammenhang mit dem PHPMailer auftritt, oder auch wenn man ein Plugin wie WP Mail SMTP verwendet?
Das wäre zu testen. Generell ist das Nutzen eines expliziten Mailservers (via SMTP) immer dem Zweckentfremden eines Webservers vorzuziehen – aber wer macht das bei jedem kleinen WordPress-Projekt? Damit sollte nach meinem Verständnis auch die Kommunikation von Envelope Sender/Envelope To korrekt über das SMTP-Protokoll stattfinden und den Return-Path korrekt setzen. Ob der MTA bei Nicht-Existieren eines Postfaches vielleicht auch Probleme macht oder es noch andere Gründe gibt, übersteigt mein Wissen. Das verlässt dann schon deutlich den Bereich WordPress/PHP und ist eher eine Frage für die DevOps/Server-Fraktion.
Wenn du es testest, dann berichte gerne hier über deine Erfahrungen!