Kontaktformular 1 - Validierung
Wie du dein Formular validierst, hängt davon ab, welche Felder du verschickst, und welchen Zweck diese erfüllen sollen. Wichtig sind zwei Dinge, die du immer beachten solltest:
- Bereinigung (Sanitizing): die Daten müssen in korrektem Format bereitstehen und dürfen keinen Schadcode enhalten. Im Falle der Verarbeitung geht es hier vor allem um Input Sanitizing, also ankommende Daten zu bereinigen (im Gegensatz zu Output Sanitizing, bei dem Daten vor der Ausgabe bereinigt werden sollen). Die Technik ist in beiden Fällen jedoch die gleiche. Input Sanitizing soll so früh wie möglich im Prozess gemacht werden, und Output Sanitizing so spät wie möglich. Hierdurch ergibt sich die grösste Sicherheit.
- Datenprüfung (Validation): die Daten müssen in korrekter Form bereitstehen, sonst werden sie nicht verarbeitet.
Es emfpiehlt sich also vor dem Prüfen der Daten, diese zu bereinigen. Stelle dir vor, du prüfst, ob eine Nachricht leer ist, sie enthält aber nur HTML Code. Wird dieser bei der Bereinigung weggelöscht, kann der Wert als leer betrachtet werden, und wird bei der Prüfung danach auch so behandelt. Ausgaben der Felder machst du dann nur noch mit den bereinigten, Schadcode-freien Werten.
Manchmal können die beiden Schritte auch zusammengefasst werden, wie im Beispiel der E-Mail Validierung - passiert ein E-Mail String nicht den Validierungsfilter, ist sie ungültig, egal ob sie leer war oder inkorrekt, oder mit Schadcode behaftet (was auch inkorrekt ist).
Typische Bereinigungsmethoden
Schadcode (Tags) entfernen:
$message = strip_tags($message); // entfernt alle HTML Tags
Verwendest du einen WYSYWYG Editor, der HTML Formatierung wie bold oder Absätze erlaubt, kannst du diese auch passieren lassen:
$message = strip_tags($message, '<p><b><strong>'); // entfernt alle HTML Tags ausser Absätzen und Fett
Leerzeichen am Anfang und Ende weglöschen:
$message = trim($_POST["message"]);
E-Mail Format Filter (dies ist zugleich Prüfung und Bereinigung)
// E-Mail String durch den E-Mail Filter schicken. Vor dem Filtern noch leerschläge am Anfang und am Ende entfernen
$email = filter_var($_POST["email"], FILTER_VALIDATE_EMAIL);
Die Prüffunktionen können auch kombiniert werden, wenn man die Zeilen Code etwas reduzieren möchte:
// E-Mail String durch den E-Mail Filter schicken. Vor dem Filtern noch leerschläge am Anfang und am Ende entfernen
$email = filter_var(trim($_POST["email"]), FILTER_VALIDATE_EMAIL);
Typische Prüfmethoden
Prüfmethoden fragen immer nach einem zustand und haben als Rückgabewert immer einen boolean (TRUE oder FALSE).
Prüfen, ob ein Wert vorhanden ist (existiert=true)
if( isset($POST["name"]) ){
// true, wenn das Feld Name existiert
}
Prüfen auf leere Werte (leer oder nicht existierend=true)
if( empty($_POST["name"]) ){
// true, wenn der Wert name leer ist oder nicht existiert im Array
}
Länge eines Stings prüfen
if( strlen($_POST["name"])<3 ){
// true, wenn der Wert name weniger als 3 Zeichen hat
}
Prüfen auf einen bestimmten Typ
isset( $message ) // true, wenn $message existiert
is_int($alter) // true, wenn $alter eine Ganzzahl ist
is_numeric($preis) // true, wenn $preis ein numerischer Wert ist, Ganzzahl oder Kommazahl
is_array($hobbies) // true, wenn $hobbies ein Array ist
is_bool( $hasErrors ) // true, wenn $hasErrors ein boolescher Wert ist
Prüfen auf Zeichentyp:
ctype_alnum( $input ) // true, wenn rein alphanumerisch, z.B. username
ctype_alpha( $input ) // true, wenn rein alphabetisch
ctype_digit( $input ) // true, wenn nur Zahlen, z.B. Alter
ctype_xdigit( $input ) // true bei hexadezimalwerten, z.B. Farbcode
ctype_space( $input ) // true bei whitespace (leerzeichen)
ctype_upper( $input ) // true, wenn nur Grossbuchstaben
ctype_lower( $input ) // true, wenn nur Kleinbuchstaben
Weitere Prüfungen, z.B. auf bestimmte Zeichen, können mit einem regulären Ausdruck geprüft werden. Der Vorgang wird immer mit preg_match() ausgeführt, je nach Prüfung werden jedoch unterschiedliche Muster mitgegeben:
// prüfen ob $password mindestens einen Kleinbuchstaben enthält
if (!preg_match('/[a-z]/', $password)) {
$errors[] = "Passwort muss mindestens einen Kleinbuchstaben enthalten.";
}
// prüfen ob $password mindestens einen Grossbuchstaben enthält
if (!preg_match('/[A-Z]/', $password)) {
$errors[] = "Passwort muss mindestens einen Großbuchstaben enthalten.";
}
// prüfen ob $password mindestens eine Zahl enthält
if (!preg_match('/[0-9]/', $password)) {
$errors[] = "Passwort muss mindestens eine Zahl enthalten.";
}
// prüfen ob $password ein Leerzeichen enthält
if (preg_match('/\s/', $password)) {
$errors[] = "Passwort darf keine Leerzeichen enthalten.";
}
So geht's
Zur Vorbereitung kannst du dir als erstes das kontaktformular.zip herunterladen und es in deinem lokalen Testserver installieren.
- schaue dir das Formular im kontaktformular.php genau an. Wichtig, um mit der Verarbeitung zu beginnen, sind die Werte des Form attributs "action" und "method". Bei action steht "kontaktformular.php", die Datei, in der wir nun auch die Verarbeitung machen - es ist dieselbe Datei, was uns das Fehlerhandling sehr vereinfachen wird. bei "method" steht "POST", das heisst, wir müssen mit dem $_POST Array arbeiten.
- Öffne nun die Datei kontakt.php. Bevor du loslegst mit der Verarbeitung, bereite dein Script vor, um Fehler zu behandeln. Denn Fehler sind bei User Input vorprogrammiert! Die Status-Variable $hasError ermöglicht dabei am Schluss eine einfache Entscheidung - können die Daten verschickt werden oder nicht? Dieser Status ändert sich in jedem Fall, in dem ein Fehler gefunden wurde (wie viele es sind, ist am Schluss nicht wichtig für unsere Enscheidung). Für den Besucher, der das Formular ausfüllt, sollten im Falle eines Fehlers aber auch noch Meldungen erzeugt werden, was nicht korrekt ist.
$hasError = false; // Status Variable für Fehler $errorMessages[] = array(); // Sammelcontainer für Fehlermeldungen - Nun können folgende Schritte ausgeführt werden:
- Prüfung, ob Daten vorhanden sind (Das Script könnte ja auch direkt aufgerufen werden)
// wurden überhaupt Daten per POST Methode übermittelt? if ($_SERVER["REQUEST_METHOD"] == "POST") { // der gesamte weitere Code kommt hierher } - Validierung und Bereinigung (Die Daten könnten ja auch unnütz, falsch oder sogar gefährlich sein). Beginne mit der E-Mail Adresse. Diese darf einerseits nicht leer sein, andererseits sollte sie genau dem richtigen Format einer E-Mail Adresse entsprechen. Hierfür kann filter_var() genutzt werden.
if (empty($_POST["email"])) { // ist email leer? $hasError = true; // Fehlerstatus anpassen $errorMessages[] = "E-Mail ist erforderlich."; // Meldung in den Sammelcontainer } else { // E-Mail format prüfen $email = filter_var($_POST["email"], FILTER_VALIDATE_EMAIL); // Wenn das E-Mail Format nicht korrekt ist if ($email==false) { $hasError = true; // Fehlerstatus anpassen $errorMessages[] = "Ungültige E-Mail-Adresse."; // Meldung in den Sammelcontainer } }
Gehe nun ähnlich vor mit dem Nachrichtenfeld. Hier gilt: es darf nicht leer sein, und muss, bevor es weiterverarbeitet wird, bereinigt werden (sanitizing).
// zuerst bereinigen (script und html tags entfernen) $message = strip_tags($_POST["message"]); // Prüfen, ob die Nachricht nicht leer ist if (empty($message) || strlen($message)<10) { $hasError = true; // Fehlerstatus anpassen $errorMessages[] = "Nachricht ist erforderlich und sollte mindestens 10 Zeichen enthalten."; } - Fehlerhandling - bevor du die Daten endlich verarbeiten kannst, prüfe nun, ob in den Zeilen vorher ein Fehler entstanden ist oder nicht. Hast du alle möglichen Fälle abgedeckt, kasnnst du dich nun voll und ganz auf die Statusvariable $hasError verlassen:
if($hasError == false){ // hier kann nun das Mail verschickt werden }
Sollten nun Fehler auftauchen, können im HTML die Fehlermeldungen ausgegeben werden. Hier zahlt es sich aus, dass wir direkt in der Datei mit dem Formular auch die Verarbeitung machen.
<h3>Kontaktformular</h3> <?php // Prüfen, ob Fehler enstanden sind if($hasError == true){ // Sammelcontainer zu einem String zusammenhängen und ausgeben echo implode('<br>', $errorMessages); } ?> <form action="" method="POST">
- Prüfung, ob Daten vorhanden sind (Das Script könnte ja auch direkt aufgerufen werden)
- Ist nun alles korrekt ($hasErrors ist immer noch false), kann ein Mail verschickt werden. Hierfür werden vier Parameter gebraucht: empfänger, Betreff, Nachricht und Headers (in welchen du mindestens einen passenden Absender angeben solltest, damit die Nachricht nicht im Spam landet). Bereite daher zuerst die vier Variablen vor.
<?php $empfaenger =This email address is being protected from spambots. You need JavaScript enabled to view it. '; // Die Adresse, an die das E-Mail geschickt werden soll $betreff = 'Kontaktanfrage von deiner Webseite'; // Ein bezeichnender Betreff $body = $message; // die Nachricht vom Formular // Mailheader im Plain Text Format $headers = "From: " . $email . "\r\n" . "Reply-To: " . $email . "\r\n" . "X-Mailer: PHP/" . phpversion(); ?> - Zum Schluss kannst du die Mail mit den vier parametern verschicken, und eine Erfolgsmeldung ausgeben, wenn dies funktioniert hat. Dies erkennst du daran, ob die Funktion mail() true oder false zurückgibt.
$mailSent = mail($empfaenger, $betreff, $body, $headers); // Success Message im HTML if($mailSent == true){ echo '<div class="alert alert-success">Danke für deine Post!</div>'; }
Tips und Links
Form debugging – Formulardaten sichtbar machen
nutze print_r() für die Ausgabe der Formulardaten - das zu sehen hilft mehr als annehmen, dass etwas so oder so ankommt. Das <pre> HTML-Tag hilft dir bei diesem debugging output, das Array schön formatiert darzustellen (pre = preformatted).
<?php
// Formulardaten verarbeitendes Skript (POST daten)
echo '<pre>';
print_r($_POST); // zuerst Daten ausgeben
echo '</pre>';
?>
Wird meine E-Mail als Spam eingestuft?
Mails, die aus einem PHP Skript stammen, geben vor, von einer Mailbox geschickt zu werden, in wirklichkeit wurden sie vom Server selbst an das Mailkonto ausgeliefert. Dies und weitere Faktoren, können einen Spamfilter dazu bringen, deine Mail als Spam einzustufen. Eine gute Massnahme ist die Verwendung der Klasse PHPMailer, welche über eine SMTP Verbindung direkt an einen Postausgang verschickt, was vertrauenswürdiger wirkt. Weitere Massnahmen sind eine DKIM Signatur und DNS Einträge auf deinem Server, welche bestätigen, dass dieser Server Mails mit diesem Absender schicken darf (frage deinen Hosting Provider!). Diese Regeln verändern sich jedoch laufend, daher prüfe deine Mails in jedem Fall mit mail-tester.com. Dieser Dienst gibt dir ein Rating, genau wie der Spamfilter es macht, erklärt dir aber transparent, wie er zu diesem gekommen ist, und welche Massnahmen du ergreifen solltest. So lernst du die aktuellen Regeln von Spamfiltern kennen und hast am Schluss hoffentlich ein Mail, das jede Inbox erreicht.
Links zum Thema Sicherheit
https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
Verarbeite Daten aus einem Formular, um sie per E-Mail zu verschicken