Benutzer:TS/Grundlagen und Entwicklungsschritte für Formmailer

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Module des Mailsystems[Bearbeiten]

Um eMails zu versenden, bedient sich PHP der eingerichteten Mailsysteme auf dem Host, auf dem PHP läuft. Diese unterscheiden sich an der PHP-Schnittstelle zur API des OS prinzipiell nur danach, ob der Auftrag per Skript-Environnment (Linux) oder direkt per Port (25, Windows) übergeben wird. Die mail()-Funktion von PHP regelt die Schnittstellenart i.d.R. eigenständig.

smtps[Bearbeiten]

Den Mailversand übernimmt stets ein "Simple Mail Transprort Protocol Server" oder eine vergleichbare Funktion.

Dieser Server ist gleichzeitig auch ein Client. Das bedeutet, dass er von anderen SMTPS übermittelte Daten annehmen und ggf. auch an weitere SMTPS weiterleiten kann. Moderne SMTPS beherrschen komplexe Methoden, um feststellen zu können, von wem sie in Anspruch genommen werden wollen und dürfen.

Sendet ein Client eine eMail, wird diese in eine Warteschlange des SMTP-Servers eingestellt. Dort verbleibt sie solange, bis die Weiterleitung an das Ziel erfolgreich war, oder der Zustellversuch aufgrund von Fehlern oder Regeln abgelehnt/abgebrochen werden musste.

postoffice[Bearbeiten]

Nach Annahme einer eMail durch den SMTPS reicht dieser die Nachricht an das *Postoffice* des angesprochenen Clients weiter. Das Postoffice, das seinerseits wieder aus mehreren Softwaremodulen bestehen kann, lehnt die Annahme entweder ab, oder nimmt die Nachricht an und verteilt sie intern, um sie schlussendlich im Postfach des Client abzulegen.

imaps[Bearbeiten]

Mit Hilfe eines IMAP-Servers (Internet Mail Access Protocol Server) kann ein IMAP-Client seine eMails auf dem Server lesen. Dazu wird immer nur eine Kopie der angeforderten eMail zum Client transportiert. Die eMail selbst bleibt auf dem IMAP-Server gespeichert und ist so auch durch weitere berechtigte IMAP-Clients lesbar. Ein entsprechend berechtigter IMAP-Client kann die eMail auch auf dem Server verschieben oder löschen lassen. Viele IMAP-Clients nutzen aber die vielen Remote-Funktionen des IMAP-Servers leider gar nicht, sodass der Unterschied zu POP3 nicht immer auffällt.

pop3s[Bearbeiten]

Der Post Office Protocol Server der Version 3 (POP3-Server) ermöglicht es dem passenden Client nur, seine eMails abzuholen (eine Kopie herunterzuladen) und diese dann zu löschen. Auch wenn das Abholen und Löschen in den meisten Clients durch Voreinstellung wie ein geschlossener Vorgang aussieht, handelt es sich doch um zwei getrennte Schritte. Es wäre also auch hier durchaus möglich, die neuen eMails von verschiedenen Stellen aus mit mehreren Clients zu lesen. Löscht aber ein Client die eMail auf dem Server, ist sie tatsächlich verschwunden. Auch das Einsortieren in "gelesene eMails" muss hier jeder Client für sich alleine lokal durchführen. Auf dem Mailserver gibt es außer dem Posteingang keine gemeinsamen Verzeichnisse.

Mail-Client[Bearbeiten]

Der Mail-Client ist das Programm auf dem Arbeitsplatz oder Mobildevice. Er nimmt zum Senden von eMails Kontakt mit dem SMTP-Server auf und zum Abholen von eMails mit dem Postoffice. Dort ist heute das IMAP/s (secure Internet Message Access Protocol) üblich. Es gibt aber auch noch viele Postoffices, die mit POP3/s (secure Post Office Protocol 3) arbeiten. Man sollte immer darauf achten, dass die Kontaktaufnahme und die Übermittlung von Daten zwischen Server und Client verschlüsselt (TLS, Transport Layer Security) stattfinden.

Analog wollen wir unsere Formmailer nur noch über HTTP/s betreiben. Der Webserver benötigt hierfür eine entsprechende SSL/TLS-Einrichtung mit gültigem Zertifikat.

Aufbau einer eMail[Bearbeiten]

Plain-Text-Mail[Bearbeiten]

Eine Klartext-eMail besteht aus mehreren Mailheadern und einem Mailbody. Diese stehen in einer gemeinsamen Datei, die an das Mailsystem übergeben wird. EMailversand bedeutet also, Dateien mittels eines speziellen Server-Programms aufgrund der in den Headern enthaltenen Anweisungen an Gegenstellen zu versenden. Hierzu durchläuft der Versandprozess mehrere Stufen.

Mailheader[Bearbeiten]

Mailbody[Bearbeiten]

[Beispiel eMail-Datei]

Die Header enden nach der ersten Leerzeile.

Der Body endet, wenn als einziges Zeichen nur ein Punkt (0x2E) in der Zeile steht.


PHP mail()-funktion[Bearbeiten]

bool mail (

 string $to, 
 string $subject, 
 string $message, 

)

MIME-Mail[Bearbeiten]

Mailheader (Multipart)[Bearbeiten]

Mailbody (Multipart)[Bearbeiten]

Attachements[Bearbeiten]

PHP mail()-funktion[Bearbeiten]

bool mail (

 string $to, 
 string $subject, 
 string $message, 
 string $additional_headers, 
 string $additional_parameters 

)

Kodierungs-Kette[Bearbeiten]

Grundsätzlich stammt die Technik des eMail-Versandes noch aus einer Zeit, in der die Übertragung mit 7-Bit-Wortlänge durchgeführt wurde. Dies passte zur ASCII-Zeichenkodierung, die bekanntermaßen ja nur 7 Bit benötigte.


Mail-Body[Bearbeiten]

Kodierung[Bearbeiten]

Inzwischen ist aber davon auszugehen, dass eine 8-Bit-Übertragung für den täglichen Mailverkehr überall eingeführt wird. Da die UTF-8-Kodierung sich vollständig in die 8-Bit-Übertragung einbettet (bitte nicht Wortlänge und Zeichenlänge verwechseln), können auch Texte, die in UTF-8 kodiert sind, also ohne grundlegende Probleme übertragen werden. Der Client muss nur die Möglichkeit kennen, die Zeichen(de)kodierung passend einzustellen.

Wenn wir also davon ausgehen, dass unsere Webseite, auf der sich das Formular unseres Formmailers befindet, in UTF-8 kodiert ist, müssen wir im zugehörigen PHP-Skript für den Text unserer eMail also nichts mehr umkodieren. Wir teilen aber dem Client mit, was ihn erwartet:

   $header .= "\r\nMIME-Version: 1.0";
   $header .= "\r\nContent-Type: text/plain; charset=utf-8";  
   $header .= "\r\nContent-Transfer-Encoding: 8bit";  

Umbruch[Bearbeiten]

Bei Plain Text eMails sollten die Zeilen inklusive Zeilenumbruchzeichen (CR/LF) 80 Bytes Länge nicht überschreiten. Üblicherweise wird eine Länge von 75 Bytes voreingetellt, was bei Linux-Systemen auch nach dem Durchlaufen der Sendmail-Funktion immer noch zu 76 Bytes Länge führen kann, weil hier "\n" gegen "\r\n" ausgetauscht wird.

Dies macht dann aber bei multibyte-kodierten Texten Probleme mit der wordwrap()-Funktion von PHP, da man nicht einfach mitten in eine Bytesequenz für ein Zeichen aus mehreren Bytes einen Umbruch einbauen darf. Die Bytesequenz könnte dann nicht mehr ordentlich dekodiert werden.

Es bedarf also einer passenden mb_wordwrap()-Funktion. Einen Vorschlag zumindest für utf8_wordwrap() finden wir in den UCN der PHP-Manualseite von wordwrap().

 <?php
 function utf8_wordwrap($string, $width=75, $break="\n", $cut=false)
 {
     if($cut) 
     {
         // Match anything 1 to $width chars long followed by whitespace or EOS,
         // otherwise match anything $width chars long
         $search = '/(.{1,'.$width.'})(?:\s|$)|(.{'.$width.'})/uS';
         $replace = '$1$2'.$break;
     } 
     else 
     {
         // Anchor the beginning of the pattern with a lookahead
         // to avoid crazy backtracking when words are longer than $width
         $pattern = '/(?=\s)(.{1,'.$width.'})(?:\s|$)/uS';
         $replace = '$1'.$break;
     }
     return preg_replace($search, $replace, $string);
 }
 ### Of course don't forget to use preg_quote on the $width and $break parameters 
 ### if they come from untrusted input.
 ?>  

Daten in den Mail-Headern[Bearbeiten]

Um trotzdem der Forderung aus RFC 2047 noch nachzukommen, und für alle Daten in den Mail-Headern eine 7-Bit-Übertragung zu ermöglichen, stellt PHP eine Funktion zur Verfügung:

 -> https://de.wikipedia.org/wiki/Multipurpose_Internet_Mail_Extensions#message  
 -> http://us2.php.net/manual/en/function.mb-encode-mimeheader.php  

   mb_encode_mimeheader()  

Konfigurationsmöglichkeiten und nützliche Header[Bearbeiten]

PHP und der Mailserver fügen in die Mail-Header meistens automatisch einige Informationen ein, die uns ggf. stören könnten, bzw. unsere Sicherheit beeinträchtigen könnten.

"X-PHP-Originating-Script"-Header[Bearbeiten]

Den X-PHP-Originating-Script Header kann man in der Konfiguration der Mail-Domain, also derjenigen, in der das Mail-Skript aufgerufen wird, ausschalten. Dies kann in der Haupt-Server-Konfiguration, der Virtual-Host-Konfiguration oder auch in der temporären Verzeichnis-Konfiguratuion (.htaccess-Datei) stattfinden.

php_flag mail.add_x_header 0

Wenn man nicht wünscht, dass dieser Header in der .htaccess-Datei verändert werden kann, setze man ihn in der Server-Konfiguration oder der Virtual-Host-Konfiguration auf den gewünschten Wert:

## Header festschreiben: für ? bitte 0 oder 1 einsetzen: 
php_admin_flag mail.add_x_header ?

"Return-Path:"-Header[Bearbeiten]

Der "Return-Path:"-Header lässt sich bei LINUX-Systemen, die das Sendmail-Script verwenden, über das Funktionsargument "$additional_parameters" der mail()-Funktion steuern.

$parameters = " -f <postmaster@bitworks.de>";

Er gibt das Rückmelde-Ziel für den Fall an, dass keine transpaente SMTP/s-Verbindung zwischen Quelle und Senke aufgebaut werden konnte. Bei verschlüsselter Übertragung kann dies durchaus mehrere Zwischenstationen beinhalten:

Q - H - H - H - S
  • Q = Quelle
  • H = Hop, vermittelnder SMTP-Server
  • S = Senke

"Reply-To:"-Header[Bearbeiten]

Ein "Reply-To:"-Header ist sinnvoll für Common Mail Platforms, bei denen der Absender der eMail im Auftrag eines Teilnehmers handelt, und eine "One Click Answer" aus dem Mailclient des Empfängers nicht an den Absender, sondern an den Auftraggeber der eMail gehen soll. Ein Beispiel hierfür ist die Tourismusplattform "http://harz.de", die für alle ihre Teilnehmer Anfragen entgegen nimmt und diese dann gleichberechtigt an alle zutreffenden Anbieter weiterleitet. Hier möchte nicht der Kontakt-Service die Antwort haben, sondern der Kontaktsuchende. Dieser wird dann im "Reply-To:"-Header angegeben.

Den Header setz man im Funktionsargument "$additional_headers".

Beispiel:

$header .= "\r\nDate: Thu, 21 Dec 2000 10:00:00 +0200";
$header .= "\r\nFrom: booking-service@harz.de";
$header .= "\r\nReply-To: unterkunftsuchender@example.org";

"Date: "-Header[Bearbeiten]

der Date-Header suggeriert die Absendung der eMail zu einem bestimmten Datum. Er wird einfach beim Absender eingesetzt. Der "Date: "-Header wird von den wenigsten SMTP-Servern überschrieben, was dann manchmal beim Empfänger zu etwas Verwirrung führen kann.

In vielen eMail-Clients werden neu empfangene Mails nach genau diesem Header sortiert angezeigt. Damit rutscht die eMail in der Sortierung eventuell soweit nach unten, dass man sie (auf den ersten Blick) als "übersehen" einstufen könnte und ein schlechtes Gewissen bekommt.

Weitere Header in der eMail zeigen aber mehr Informationen über das Eintreffen beim eigenen Postoffice. Wenn man also eMails zur Unterstützung der Glaubwürdigkeit verwenden will, sollte man immer die komplette eMail, also auch alle Header sichern! Außerdem sollte man in wichtigen Fällen seinen Mailprovider bitten, das Maillog zu sichern. Dieses ist sonst nach wenigen Tagen bereits verloren.

Mailversand unter Windows und unter LinUX[Bearbeiten]

Unter Linux wird i.d.R. das "sendmail"-Skript für den Mailversand benutzt. Es veranlasst dann alle weiteren Maßnahmen, egal, welcher SMTP-Server (SEndmail, Exim, Postfix, ...) installiert ist. Dem Skript muss eine Datei übergeben werden, die den Konventionen für Maildateien entspricht.

Unter Windows wird i.d.R. die Datei direkt über den Port 25 übergeben. Bei verschlüsseltenm eMail-Verkehr kommen auch xxx und xxx in Frage.

wichtige Konventionen[Bearbeiten]

Formularaufbau[Bearbeiten]

Ein Affenformular[Bearbeiten]

Zwischenspeicherung von Anhängen[Bearbeiten]

Seriöse Bestätigungsseite[Bearbeiten]

Quellen[Bearbeiten]

RFCs[Bearbeiten]

RFC Betrifft Verweise
822 Beispiel Beispiel
2045 Beispiel Beispiel
2046 Beispiel Beispiel
2047 Beispiel Beispiel
2048 Beispiel Beispiel
2049 Beispiel Beispiel

PHP-Manual[Bearbeiten]

Wikipedia[Bearbeiten]

forum.selfHTML.org[Bearbeiten]