Der Martin: Mailversand mit Anhang

Beitrag lesen

Hallo Rainer,

habe einiges geändert _aber_ jetzt habe ich teile des headers und den Anhang in der Email als Text.

naja, jetzt hast du vieles korrigiert, aber ein paar Kleinigkeiten falsch gemacht, die vorher richtig waren ...
Schauen wir uns mal die Header zuerst an.

$headers = "FROM: RT test@example.org\n";
$headers .= "Content-Type: application/octet-stream;\nname=$pdfname\n";
$headers .= "Content-Transfer-Encoding: base64\n";
$headers .= "Content-Disposition: attachment;\nfilename=$pdfname\n\n";

Okay, mit den \n am Ende anstatt am Zeilenanfang sieht es doch übersichtlicher aus, findest du nicht auch?
Die Header-Identifier werden üblicherweise nicht durchgehend groß geschrieben - also "From:" anstatt "FROM:". Das hat aber AFAIK keine negativen Auswirkungen, ist nur eine Konvention.

Falsch ist aber, dass du nun den *gesamten* Mail-Inhalt als application/octet-stream deklarieren willst. Im ersten Ansatz hattest du da noch multipart/mixed, was richtig war. Die Angabe der Content-Types der einzelnen Teile erfolgt dann in den Headern *innerhalb* dieser Teile.
Für den globalen Header haben wir dann also:

$headers  = "From: RT test@example.org\n";
$headers .= "MIME-Version: 1.0\n";
$headers .= "Content-Type: multipart/mixed; boundary=$grenze\n";

Achte darauf, dass $grenze vorher schon definiert sein muss!
Das war's hier. Alles weitere ist -technisch betrachtet- der Mail-Body (also das, was die Funktion mail() als $message betrachtet). Dass dieser Mail-Body selbst aus mehreren Abschnitten besteht, die jeder wieder einen eigenen Header und Body haben, ist gar nicht so wild, wenn man das Konzept mal verstanden hat.

$msg="";
$msg .="\n\n--$grenze\n\n";

Hier ist es unnötig, mit zwei Zeilenumbrüchen anzufangen; es schadet aber auch nicht. Ich würde sie trotzdem weglassen. Hinter der Boundary-Zeile kommt aber nur *ein* Zeilenumbruch!
Allerdings fehlen nun die lokalen Header für diesen Abschnitt:

$msg  = "--$grenze\n";
$msg .= "Content-Type: text/plain; charset=ISO-8859-1\n";
$msg .= "Content-Transfer-Encoding: quoted-printable\n\n";

Beachte den doppelten Zeilenumbruch am Ende: Die lokalen Headerzeilen werden wieder mit einer Leerzeile vom nachfolgenden Nutzinhalt getrennt. Lassen wir also den angekündigten Nutzinhalt vom Typ text/plain folgen:

$msg .= "Das ist ein Testtext \nmit Zeilenumbruch\n\n";

Am Ende des Nutzinhalts folgt dann -mit einer Leerzeile, also zwei Zeilenumbrüchen abgetrennt- wieder eine Boundary-Zeile:

$msg  = "--$grenze\n";

Und jetzt erst bist du dran mit deinem MIME-Typ application/octet-stream. ;-)
Aber nicht ganz so, wie du diese Hederzeilen formuliert hattest; die Fortsetzungszeilen ("name=" oder "filename=") dürfen nicht am Zeilenanfang stehen, sondern müssen mit einem Leerzeichen eingerückt sein - sonst würden sie als eigenständige Headerzeilen interpretiert.

$msg .= "Content-Type: application/octet-stream;\n name=$pdfname\n";
$msg .= "Content-Transfer-Encoding: base64\n";
$msg .= "Content-Disposition: attachment;\n filename=$pdfname\n\n";

Wieder der doppelte Zeilenumbruch zur Abtrennung vom Nutzinhalt, der dann sofort folgt:

$zeiger_auf_datei=@fopen($datei,"rb");
$inhalt_der_datei=@fread($zeiger_auf_datei,filesize($datei));
@fclose($zeiger_auf_datei);
$inhalt_der_datei=chunk_split(base64_encode($inhalt_der_datei));
$msg .= $inhalt_der_datei;
$msg .= "\n\n";
$msg .= "--$grenze--";

Vergiss nicht, dass die letzte Boundary-Zeile mit einem zusätzlichen '--' endet.
Mir wird außerdem nicht ganz klar, warum du bei fopen(), fread() und fclose() den Fehlerunterdrückungs-Operator '@' benutzt, anstatt die Fehlerbedingungen direkt auszuwerten (z.B. dass fopen() im Fehlerfall false liefert).

Ich hoffe, dass du nun allmählich zu einem funktionsfähigen Beispiel kommst und auch noch verstanden hast, *warum* einzelne Teile wie gewünscht funktionieren oder eben nicht.

Wenn dir noch etwas unklar ist: Schau dir in deinem Mailclient einfach mal eine korrekt empfangene Mail mit Anhang im Quelltext an, und versuche, die Strukturen wiederzuerkennen, die wir besprochen haben!

So long,
 Martin

--
Rizinus hat sich angeblich als sehr gutes Mittel gegen Husten bewährt.