Edgar Ehritt: Mail versenden in HTML und Normal Formatiert

Beitrag lesen

Teil 2:
---
Das kommt dabei raus, wenn man nicht schlafen kann: Lauter Fehler. ;(
Ein paar sind zwar immer gut, um zu testen, ob der OP mitdenkt. Das aber sind zu gravierende Fehler gewesen. Wenn die, hiermit angerufene, heilige Inquisition der Moderation den zweiten Teil vom 20.09.2009, 04:24 Uhr nebst diesem Textblock löscht, würde mich das freuen. :)

In Berichtigung:
---

Damit ein Mailprogramm dort durchsieht, regelt RFC 2045, wie genau die Formatierung zu erfolgen hat. Gucken wir uns am besten mal die letzte Werbung von gmx an. Ich werde zum Oktoberfest verladen - äh, aha:

#####################################################

Return-Path: mailings@gmx-gmbh.de
Date: Fri, 18 Sep 2009 17:17:03 GMT
From: GMX Magazin mailings@gmx-gmbh.de
To: Alle Mitglieder von GMX members@gmx.net
Subject: Einladung zum Oktoberfest!
Message-ID: 20090920004540.28344abod0@mmail04.gmx.net

MIME-Version: 1.0
   Content-Type: multipart/alternative; boundary="gmxboundary=-1253407540-28344-top"

--gmxboundary=-1253407540-28344-top
   Content-Type: text/plain; charset="iso-8859-1"
   Content-Transfer-Encoding: quoted-printable

bla bla bla...

--gmxboundary=-1253407540-28344-top
   Content-Type: text/html; charset="iso-8859-1"
   Content-Transfer-Encoding: quoted-printable

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.=
   w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   <html xmlns=3D"http://www.w3.org/1999/xhtml" xml:lang=3D"de" lang=3D"de">
    <!-- Inhalt -->

--gmxboundary=-1253407540-28344-top--
#####################################################

Nochmals ganz kurz abgerissen, was Du da siehst: Return-Path-, From- und To-Header hatten wir oben ja schon kurz erwähnt (RFC 5322; 3.6). Date-Header wird durch Abschnitt 3.6.1 i. V. m. Abschnitt 3.3 bestimmt (der versierte PHPler nutzt dafür date('r') - fertig). Subject wird durch Abschnitt 3.6.5, Message-ID durch Abschnitt 3.6.4 definiert.

Damit sind wir beim eigentlichen Inhalt. Der hat wiederum Header. Diesmal aber zur Formatierung nach MIME. MIME-Version muss immer angegeben werden. Es handelt sich dabei um eine Angabe ähnlich der Prozessoranweisung von XML (<?xml version="x.y"?>). Derzeit gibt es nur die Version 1.0. Nachzulesen ist das dann in der RFC 2045; 4. Content-Type-Header wird seinerseits durch Abschnitt 5 festgelegt. Der Mediatyp ist "multipart/alternative". Diese Angabe legt fest, dass alternative Inhaltsteile zur Anzeige bereitstehen. In der selben Zeile, getrennt vom Semikolon findet man boundary="gmxboundary=-1253407540-28344-top". Das ist der Grenzwert, der die einzelnen Teile, also in Deiner Frage Text und HTML, separiert. Dazu wird jeder Teil mit dem Wert vom Parameter boundary und dem Prefix "--" unterteil. RFC 2045 hat zwar die alter RFC 1521 abgelöst. Leider geht sie auf diesen Punkt weiter nicht mehr ein. Genauer beschrieben ist es in RFC 1521; 7.2.3.

Es ergibt sich also folgende Inhaltsstruktur:

Nachricht in multipart/alternative
    |
    |- Teil in text/plain
    |
    `- Teil in text/html

Ein Mailprogramm bring daraufhin je nach Konfiguration oder Möglichkeit den jeweiligen Teil der Nachricht zur Anzeige. Es ist ebenso möglich, dass man noch andere oder mehrere Mediatypen alternativ anbietet. Man ist zahlenmäßig an keine Obergrenze gebunden. So könnte man neben Text und HTML zusätzlich PDF, XML, Office-Dokumente, ... als Alternativen in einer einzigen Nachricht anbietenn.

Die zweite Frage ist die, wie binde ich Bilder, z.B. ein Logo, in die Mail ein, dass die Mail auch offline sauber aussieht?

Neben dem Mediasubtyp "alternative" gibt es noch andere. Um Bilder inline mitzusenden nimmt man den Subtyp "related":

#####################################################

[IMF-Header]

MIME-Version: 1.0
   Content-Type: multipart/related; boundary="gmxboundary=-1253407540-28344-top"

--gmxboundary=-1253407540-28344-top
   Content-Type: text/html; charset="iso-8859-1"
   Content-Transfer-Encoding: quoted-printable

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.=
   w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   <html xmlns=3D"http://www.w3.org/1999/xhtml" xml:lang=3D"de" lang=3D"de">
    <!-- Inhalt -->
    <img src=3D"cid:image"/>
    <!-- immer noch Inhalt -->

--gmxboundary=-1253407540-28344-top
   Content-ID: <image>
   Content-Type: image/gif
   Content-Transfer-Encoding: base64
   Content-Disposition: inline; filename="service145.gif"

R0lGODlhkQAPALMAABxEm+Xl6/7+/vf3+fT09uzs7/39/fHx9Pv7+////9/g5gAAAAAAAAAA
   AAAAAAAAACH5BAAAAAAALAAAAACRAA8AAATaUMlJq7046827/6CWjGRpnmiqrmzrvnCMSklo
   33iu71QSAMCAcEgsGo/IpHLJbDqfUCGtAAQUrtisdsvter/gsHhMLl9ph+phzW673/C4fE6v
   2+/4/JpGqBL+gIGCg4SFhoeIiYqLjI1/NANVA5OUlZaXmJmam5ydnp+goZM0CFUIp6ipqqus
   ra6vsLGys7S1p6Smtrq7vL2+vDQGVQbExcbHyMnKy8zNzs/Q0dLENAJVAtjZ2tvc3d7f4OHi
   4+Tl5tg0CVUy7O3u7/Dv6fH09fb3MTz6+/z9IBEAOw==

--gmxboundary=-1253407540-28344-top--
#####################################################

Auf die einzelnen RFC-Abschnitte gehe ich jetzt nicht mehr weiter ein. ich bitte dies selbständig nachzuvollziehen! Zu beachten ist jetzt die Angabe der Source im <img>-Element "cid:image". Diese korrespondiert mit dem Wert des Content-ID-Headers, hier <image>. Wäre der Wert von Content-ID "<bla>", stünde als Referenz "cid:bla" im Attribut src. Die eigentliche Datei "service145.gif" wird wie im Beispiel oben Text und HTML einfach in der Nachricht abgelegt. Dazu ist sie base64-Kodiert. Das macht die PHP-Funktion base64_encode() freundlicher weise für den Programmierer.

Weiterhin tauch der Header Content-Disposition auf. Er wird in der RFC 2183 behandelt. Als Werte des Headers sind "inline" und "attachment" vordefiniert. (Ich denke, die jeweilige Bedeutung ist augenfällig.) Da es hier ja um Relationen geht, wir haben schließlich den Mediatypen multipart/related zu tun, macht nur "inline" Sinn. Der durch Semikolon abgetrennte Parameter filename hat auch Geschwister, die leider seltenst zum Zuge kommen, aber sehr Sinnvoll sind: creation-date, modification-date, read-date und size. Allesamt sind sie hier aber nur erwähnt. Sie haben für Deine Frage keinerlei Relevanz.

Auch hier wieder ergibt sich eine Unterteilte Inhaltsstruktur:

Nachricht in multipart/related
   |
   |- Teil in text/html
   |
   `- Teil in image/gif

Wie zu sehen ist, kann man jeden Mediatypen in einer Nachricht ablegen. Das ist ganz nützlich. Was nutzt einem nämlich entweder Text und HTML oder HTML und Bild zu haben?

#####################################################

[IMF-Header]

MIME-Version: 1.0
   Content-Type: multipart/alternative; boundary="gmxboundary=-1253407540-28344-top"

--gmxboundary=-1253407540-28344-top
   Content-Type: text/plain; charset="iso-8859-1"
   Content-Transfer-Encoding: quoted-printable

bla bla bla...

--gmxboundary=-1253407540-28344-top
   Content-Type: multipart/related; boundary="gmxboundary=-1253407540-28344-sub"

--gmxboundary=-1253407540-28344-sub
   Content-Type: text/html; charset="iso-8859-1"
   Content-Transfer-Encoding: quoted-printable

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.=
   w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   <html xmlns=3D"http://www.w3.org/1999/xhtml" xml:lang=3D"de" lang=3D"de">
    <!-- Inhalt -->
    <img src=3D"cid:image"/>
    <!-- immer noch Inhalt -->

--gmxboundary=-1253407540-28344-sub
   Content-ID: <image>
   Content-Type: image/gif
   Content-Transfer-Encoding: base64
   Content-Disposition: inline; filename="service145.gif"

R0lGODlhkQAPALMAABxEm+Xl6/7+/vf3+fT09uzs7/39/fHx9Pv7+////9/g5gAAAAAAAAAA
   AAAAAAAAACH5BAAAAAAALAAAAACRAA8AAATaUMlJq7046827/6CWjGRpnmiqrmzrvnCMSklo
   33iu71QSAMCAcEgsGo/IpHLJbDqfUCGtAAQUrtisdsvter/gsHhMLl9ph+phzW673/C4fE6v
   2+/4/JpGqBL+gIGCg4SFhoeIiYqLjI1/NANVA5OUlZaXmJmam5ydnp+goZM0CFUIp6ipqqus
   ra6vsLGys7S1p6Smtrq7vL2+vDQGVQbExcbHyMnKy8zNzs/Q0dLENAJVAtjZ2tvc3d7f4OHi
   4+Tl5tg0CVUy7O3u7/Dv6fH09fb3MTz6+/z9IBEAOw==

--gmxboundary=-1253407540-28344-sub--
   --gmxboundary=-1253407540-28344-top--
#####################################################

Es ergibt sich nunmehr folgende Inhaltsstruktur:

Nachricht in multipart/alternative
   |
   |- Teil in text/plain
   |
   - Teil in multipart/related       |       |- Unterteil in text/html       |       - Unterteil in image/gif

So, jetzt kannst Du Deine Liebesbriefe elektronisch verschicken.

Gruß aus Berlin!
eddi

--
Was haben wir denn heute? "Kampf der Titanen" - Aha! Es treten an 0 und 1.