Kategorien
Development

Laravel: Emails mit 8bit Content-Transfer-Encoding senden

Seit einigen Monaten verwende ich für ein paar PHP-Projekte das PHP-Framework Laravel.

Ich möchte hier nicht all zu viel zu diesem Framwork loswerden, außer dass es mir bisher sehr gefällt, es klar strukturiert und gut dokumentiert ist, und bisher das beste PHP Framework ist mit dem ich gearbeitet habe, auch wenn ich mit CakePHP auch ganz gut klargekommen bin.

Heute hat mich ein Kunde wegen eines Problems kontaktiert. Seine Kunden erhalten etwas kryptische Mails mit ganz vielen =09 usw. Ich habe ein wenig gebraucht bis ich hinter die Lösung gekommen bin. Es ist nicht, wie man im ersten Moment annehmen könnte das übliche UTF-8-Problem sondern hat mit dem Content-Transfer-Encoding und dem MIME-Standard zu tun.

Was hat es damit auf sich?

Heutzutage ist das versenden von Text eigentlich kein Problem. Mit 8bit lassen sich ziemlich alle Zeichen darstellen. Leider wurde der MIME-Standard ursprünglich für eine 7bit-Übertragung entwickelt und es man wohl auch heute noch vorkommen, dass einzelne Clients nicht mit 8bit-Zeichen klarkommen. Ich persönlich halte das im Jahre 2014 für relativ unwahrscheinlich.

Mit dem Content-Transfer-Encoding wird eine Zeichenkodierung für den Übertragungsweg festgelegt. Das heißt konkret: Die E-Mail wird beim senden codiert und vom Empfänger decodiert. Es gibt hierzu verschiedene Kodiermethoden:

[sh_blockquote ]Die Kodierung von Nicht-7-Bit-ASCII-Zeichen erfolgt häufig mittels Quoted-Printable-Kodierung, Binärdaten hingegen werden üblicherweise Base64-kodiert. Bei dieser Kodierungsweise erhöht sich die Gesamtgröße der angehängten Dateien um 33–36 % (Erklärung s. Base64). Aus 752 KiB werden 1 MiB (1024 KiB) und aus 1 MiB werden 1393 KiB. Alternativ ist es für Textdaten mittels Content-Transfer-Encoding: 8bit auch möglich, die nicht-ASCII-Zeichen direkt zu übertragen (die Kodierung muss dabei angegeben sein, z. B. UTF-8 oder ISO-8859-15 für deutsche Texte).

(Wikipedia)[/sh_blockquote]

Für E-Mails wird oft die Quoted-Printable-Kodierung verwendet:

[sh_blockquote ]Um trotzdem Zeichen aus dem Bereich 128–255 verwenden zu können, ohne dabei die Kompatibilität zu älteren Systemen zu gefährden, werden diese Zeichen zusätzlich kodiert. Dabei werden sämtliche Bytes außerhalb der dezimalen Bereiche 9, 32–60 und 62–126 durch ein =-Zeichen (ASCII-Wert 61), gefolgt vom Hexadezimalwert des Bytes, ersetzt.
Um die Länge der Zeilen auf 76 Zeichen zu begrenzen, wird bei längeren Zeilen nach meist 75 Zeichen ein = an das Zeilenende gesetzt und der Text in der nächsten Zeile fortgesetzt. Der auf diese Weise erzwungene Zeilenumbruch wird beim Dekodieren wieder entfernt.

(Wikipedia)[/sh_blockquote]

Wie sieht das konkret aus? Wikipedia (das ich eher selten zitiere, aber hier einfach gute Erklärungen bietet) gibt ein schönes Beispiel:

[plain]Hätten Hüte ein ß im Namen, wären sie möglicherweise keine Hüte mehr, sondern Hüße.[/plain]

Dies wird mit Quoted-Printable zu:

[plain]H=E4tten H=FCte ein =DF im Namen, w=E4ren sie m=F6glicherweise keine H=FCte=

mehr, sondern H=FC=DFe.[/plain]

Die Lösung

Nun, in den meisten Fällen sollte das alles kein Problem sein. Wenn es allerdings wie in meinem Fall doch zu Beschwerden kommt ist ein Umstieg auf die 8bit-Kodierung eine Lösung. Zusammen mit einem Zeichensatz (Charset; zB utf-8) werden hierbei die Zeichen komplett mit 8bit übertragen, was in den allermeisten Fällen keinerlei Probleme verursachen sollte.

Man muss als „nur“ den Mail-Header verändern und die Mail natürlich auch entsprechend schicken:

Content-Transfer-Encoding: 8bit

Umsetzung in Laravel

Einen Header zu setzen ist in Laravel schon mal gar nicht so leicht, da Laravel für seine Email auf den SwiftMailer zurückgreift und somit nicht jede Funktion sofort ersichtlich ist.

Einen einfachen Mail-Header kann man wie folgt setzen:

Mail::send('emails.welcome', $data, function($message)
{
    $message->getHeaders()->addTextHeader('Content-Transfer-Encoding', '8bit');

});

Leider überschreibt Laravel diesen Header. Man muss etwas tiefer greifen um tatsächlich das Encoding zu ändern. Dazu setzen wir den Entsprechenden Swift-Encoder direkt beim Swift-Objekt:

$message->getSwiftMessage()->setEncoder(Swift_Encoding::get8BitEncoding());

Nun werden die Nachrichten korrekt mit 8bit kodiert und der richtige Header wird auch gleich mitgeschickt.

Eine Stufe weiter: Plain-Text und HTML senden

Wer eine Stufe weiter gehen will kann auch sowohl eine HTML-Mail als auch eine Plain-Text-Mail versenden:

Mail::send(array('email.html_blade','email.text_blade'), $data, function($message)
{
    $message->getSwiftMessage()->setEncoder(Swift_Encoding::get8BitEncoding());
});

Bei dieser Methode sendet Laravel den Plain-Text als quoted-printable und den HTML-Code als 8bit.

Ich hoffe das hilft euch weiter :) Falls jemand dazu noch Tipps und/oder Anmerkungen hat bin ich dafür sehr dankbar.

 

Quellen:

Seite „Multipurpose Internet Mail Extensions“. In: Wikipedia, Die freie Enzyklopädie. Bearbeitungsstand: 31. Januar 2014, 00:45 UTC. URL: http://de.wikipedia.org/w/index.php?title=Multipurpose_Internet_Mail_Extensions&oldid=127047929(Abgerufen: 25. März 2014, 19:37 UTC)

Seite „Quoted-printable“. In: Wikipedia, Die freie Enzyklopädie. Bearbeitungsstand: 29. Oktober 2013, 19:22 UTC. URL: http://de.wikipedia.org/w/index.php?title=Quoted-printable&oldid=123943514 (Abgerufen: 25. März 2014, 19:48 UTC)

Content-Transfer-Encoding: quoted-printable, Microsoft Office Dev Center, http://msdn.microsoft.com/en-us/library/office/aa579632(v=exchg.140).aspx

5 The Content-Transfer-Encoding Header Field, w3c.org, http://www.w3.org/Protocols/rfc1341/5_Content-Transfer-Encoding.html

Von Luke

Blogautor, Webdesigner, Programmierer, Tontechniker, Kameramann, Musiker, Christ, und vieles mehr

4 Antworten auf „Laravel: Emails mit 8bit Content-Transfer-Encoding senden“

Schreibe einen Kommentar zu Luke Antworten abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht.