Da sich hier im Forum einige User für das Thema interessieren, schreibe ich mal ein kleines PHP Tutorial. Allgemeines Verständnis in Sachen Programmieren solltet ihr für dieses Tutorial mitbringen. Ansonsten richtet es sich speziell an PHP Anfänger.
Weil sich die Formularauswertung an diesem Beispiel gut erklären lässt, habe ich mich für ein Kontaktformular entschieden.
Der HTML Code
Als Erstes benötigen wir ein einfaches Formular, in dass der Benutzer die Daten eingeben kann.
<form method="POST" action="form.php">
<p>Name:<br /><input type="text" name="user" /></p>
<p>Emailadresse:<br /><input type="text" name="email" /></p>
<p>Nachricht: <br /><textarea name="message"></textarea></p>
<p><input type="submit" name="submit" /></p>
</form>
Erklärung:
Fangen wir beim "Form-Tag" an, das Attribut method legt die HTTP-Methode fest, über die die Daten versendet werden. In diesem Fall senden wir die Daten per HTTP POST. Das Attribut "action" legt fest, an welche Datei/URL die Daten gesendet werden. Die einzelnen Formularelemente sind mit dem Attribut "name" versehen. So können wir die Daten später in PHP auseinander halten.
Um den Dateipfad manuell einzusetzen, kann wahlweise auch "$_SERVER['PHP_SELF']" verwendet werden. Dabei ist allerdings zu beachten dass dieser String leicht manipuliert werden und so eine XSS Lücke entstehen kann. Verhindert werden kann das mit "htmlspecialchars".
<form method="POST" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>">
In PHP stehen sie uns anschließend als Array "$_POST" zur Verfügung. Das Feld mit dem Usernamen könnten wir in PHP also mit "echo $_POST['user'];" ausgeben.
Daten überprüfen
Fangen wir mit dem PHP Code an, als Erstes sollten wir natürlich überprüfen, ob alle Felder korrekt ausgefüllt wurden. Dazu basteln wir uns jetzt eine Funktion an die wir den kompletten $_POST Array übergeben können, anschließend soll die Funktion im Fehlerfall einen Array mit den einzelnen Fehlermeldungen zurückliefern.
function check_data($array)
{
$retval = array();
$error = array( "Bitte geben sie ihren Namen ein",
"Ihr Name enthält ungültige Zeichen",
"Ihr Name muss mindestens 5 Zeichen lang sein",
"Ihr Name darf maximal 15 Zeichen lang sein",
"Bitte geben sie ihre Emailadresse ein",
"Ihre Emailadresse ist ungültig",
"Bitte geben sie eine Nachricht ein" );
Wir haben hier 2 Arrays, der Array "Error" enthält alle möglichen Fehlermeldungen. Die einzelnen Fehlermeldungen können wir mit beispielsweise "echo $error[0]" für "Bitte geben sie ihren Namen ein" ausgeben. Den Array "Retval" werden wir mit den eingetroffenen Fehlern aus dem Array "Error" befüllen.
Überprüfen wir zuerst das Feld mit dem Namen:
if(empty($array['user']))
{
array_push($retval, $error[0]);
}
else
{
if(!ctype_alnum($array['user']))
{
array_push($retval, $error[1]);
}
$len = strlen($array['user']);
switch($len)
{
case($len <= 5):
{
array_push($retval, $error[2]);
break;
}
case($len >= 15):
{
array_push($retval, $error[3]);
break;
}
}
}
Erklärung:
In der ersten If Abfrage überprüfen wir, ob das Feld ausgefüllt wurde, falls es nicht leer ist, fügen wir mit der Funktion "array_push" den Inhalt von$error[0] als neues Arrayelement in den retval Array ein. Falls das Feld ausgefüllt wurde, wird der Code in der else Anweisung ausgeführt.
Mit der Funktion "ctype_alnum" überprüfen wir den Namen auf ungültige Zeichen, diese Funktion ist "true" wenn der an sie übergebene String ausschließlich die Ziffern A-Z a-z und 0-9 enthält. Wer beispielsweise Umlaute erlauben will, muss sich für die Überprüfung hier etwas anderes einfallen lassen.
Jetzt ermitteln wir mit der Funktion "strlen" wie lang der Name enthält und prüfen anschließend mit einer Switch Anweisung, ob er eventuell zu lang oder zu kurz ist.
if(empty($array['email']))
{
array_push($retval, $error[4]);
}
else if(!ereg('^[A-Za-z0-9]+([-_.]?[A-Za-z0-9])+@[A-Za-z0-9]+([-_.]?[A-Za-z0-9])+.[A-Za-z]', $array['email']))
{
array_push($retval, $error[5]);
}
if(empty($array['message']))
{
array_push($retval, $error[6]);
}
Ähnlich verfahren wir mit dem Feld dass die Emailadresse enthält. Im Fehlerfall schreiben wir den passenden Error in den Retval Array.
Mit der Funktion ereg prüfen wir den Syntax der Emailadresse anhand eines Regulären Ausdrucks. Das garantiert uns zwar noch lange nicht dass die Emailadresse auch existiert, bietet trotzdem eine gewisse Sicherheit beispielsweise bei Tippfehlern. Auf die Regulären Ausdrücke will ich mal nicht weiter eingehen, im Grunde genommen ist es aber ganz einfach.
Wer sich genauer mit der Existenz der Emailadresse beschäftigen will kann sich die Funktion "getmxrr" ansehen, die nach passenden MX Einträgen zu einem Hostname im DNS sucht.
Im Grunde genommen ist unsere Funktion jetzt fertig, ihr könnt sie natürlich nach Belieben erweitern. Eins fehlt aber noch, die Funktion soll den Array mit den eingetroffenen Fehlern zurückgeben, falls es welche gab. Mit der Funktion "count" können wir die Arrayelemente zählen.
if(count($retval) == 0)
{
return false;
}
else
{
return $retval;
}
Daten an die Funktion übergeben
Unsere Funktion zur Überprüfung der eingegeben Daten haben wir, jetzt müssen wir sie nur noch einsetzen und dem Benutzer die jeweiligen Fehlermeldungen ausgeben.
if(isset($_POST['submit']))
{
$error = check_data($_POST);
if(!$error)
{
if(send_mail($_POST))
{
echo "Vielen Dank für ihre Anfrage, wir werden uns schnellst möglich mit ihnen in Verbindung setzen.";
}
else
{
echo "Beim versenden der Email ist leider ein Fehler aufgetreten";
}
}
else if(is_array($error))
{
echo "Folgende Fehler sind aufgetreten:\n";
echo "<ul>";
for($i=0; $i<count($error); $i++)
{
echo sprintf("<li>%s</li>\n", $error[$i]);
}
echo "</ul>";
}
}
Wie ihr vielleicht schon an der If Abfrage gesehen habt, wird dieser Code ausgeführt falls der Submit Button geklickt wurde. Zuerst übergeben wir den $_POST Array an die Funktion check_data die wir zuvor geschrieben haben, und speichern die Rückgabe in der Variable Error.
"if(!$error)" tritt in Kraft, falls die Funktionsrückgabe == FALSE war. In diesem Fall gab es keine Fehler, die Email kann versendet werden. Die Funktion "send_mail" die wir dazu brauchen, schreiben wir gleich im nächsten Teil.
Andernfalls geben wir dem Benutzer die einzelnen Fehlermeldungen durch eine for Schleife als Auflistung in HTML aus.
Eine Auflistung kennt ihr bestimmt, sie ist folgendermaßen aufgebaut:
<ul>
<li></li>
<li></li>
<li></li>
</ul>
"<li>%s</li>\n" ist unsere Vorlage, das %s (String) wird mit der Funktion sprinf jeweils mit dem Error ersetzt.
Die Ausgabe sieht am Ende etwa so aus:
Die Funktion send_mail()
Theoretisch könnten wir die Email ganz einfach und mit einer Zeile Code durch die mail() Funktion versenden, dazu muss allerdings ein SMTP Deamon auf dem Server installiert und in der PHP Konfiguration eingetragen sein, außerdem wäre es ja langweilig, wenn das Tutorial hier schon zu Ende wäre. Ich habe mich für den Versand über einen externen SMTP Server per Sockets entschieden.
Dazu sollten wir uns zuerst mal vor Augen führen wie ein SMTP Server arbeitet / eine SMTP Verbindung funktioniert, was unter folgender URL ausführlich erklärt wird:
http://www.elektronik-kompendium.de/sites/net/0903081.htm
RFC5322 legt den Aufbau einer Email fest:
http://tools.ietf.org/html/rfc5322
Die Funktion:
function send_mail($array)
{
// Funktionsinhalt
}
Den $_POST Array haben wir zuvor schon an diese Funktion übergeben, hier steht er jetzt unter dem Namen $array zur Verfügung.
Inhalt der Funktion:
Als erstes schreiben wir uns unseren Emailheader
$header = "MIME-Version: 1.0\r\n";
$header .= "Content-type: text/html; charset=iso-8859-1\r\n";
$header .= "To: deinname@deinhost.de\r\n";
$header .= "FROM: <".$array['email'].">\r\n";
$header .= "Subject: Kontaktformular\r\n";
Bei "FROM" tragen wir den Absender ein den uns der Benutzer im Formular hinterlassen hat. Wahlweise können wir davor noch den Namen des Absenders, umgeben von Gänsefüßchen "" angeben.
Der Rest sollte klar sein wenn ihr euch auf den Seiten umgesehen habt, die ich oben verlinkt habe.
Jetzt bauen wir eine Verbindung zum SMTP Server auf. PHP bietet die Funktion fsockopen um eine Socketverbindung herzustellen. Der Standardport für SMTP ist 25.
$smtp = fsockopen("smtp.host.de", 25);
$status = substr(fgets($smtp, 1024), 0, 3);
if($status != 220) return FALSE;
Nachdem wir die Verbindung hergestellt haben, fragen wir mit Hilfe der Funktion "fgets" die Willkommensmeldung ab. Die ersten 3 Zeichen davon beinhalten den Statuscode, also schneiden wir mit "substr" die ersten 3 Zeichen raus und speichern sie in einer Variable "$status".
Falls ein anderer Statuscode als 220 zurückgeliefert wurde, wird die Funktion beendet und FALSE zurückgegeben.
fputs($smtp, "HELO ".$_SERVER['SERVER_ADDR']."\r\n");
$status = substr(fgets($smtp, 1024), 0, 3);
if($status != 250) return FALSE;
In diesem Schritt stellen wir uns dem SMTP Server mit unserer ServerAdresse (IP Adresse) vor. "$_SERVER" (früher "$HTTP_SERVER_VARS") ist ein globaler Array in PHP, er beinhaltet Informationen wie Scriptpfade, gesendete Header, etc. Und neben der IP Adresse des Benutzers (REMOTE_ADDR) eben auch die IP Adresse vom Server, auf dem das Script ausgeführt wird.
Wie schon zuvor lesen wir den Statuscode aus und beenden die Funktion, falls der Code nicht unseren Vorstellungen entspricht.
fputs($smtp, "AUTH LOGIN\r\n");
$status = substr(fgets($smtp, 1024), 0, 3);
if($status != 334) return FALSE;
Jetzt senden wir eine Anfrage zur Authentifizierung an den SMTP Server.
fputs($smtp, base64_encode("user oder user@user.de")."\r\n");
$status = substr(fgets($smtp, 1024), 0, 3);
if($status != 334) return FALSE;
Wenn einer Authentifizierung gestattet wurde, erwartet der SMTP Server jetzt einen Base64 verschlüsselten Benutzernamen, das erreichen wir mit der PHP Funktion "base64_encode". Entschlüsseln kann man übrigens mit "base64_decode".
fputs($smtp, base64_encode("smtp-password")."\r\n");
$status = substr(fgets($smtp, 1024), 0, 3);
if($status != 235) return FALSE;
Wurde der Benutzername aktzeptiert so erwartet der SMTP Server nun das Passwort, ebenfalls Base64 verschlüsselt.
fputs($smtp, "MAIL FROM: <".$array['email'].">\r\n");
$status = substr(fgets($smtp, 1024), 0, 3);
if($status != 250) return FALSE;
Erhalten wir den Statuscode "235" so war der Login erfolgreich. Jetzt sagen wir dem SMTP Server mit "MAIL FROM" dass wir eine Email versenden wollen, zwischen "<" und ">" steht die Absenderadresse.
fputs($smtp, "RCPT TO: email@host.de\r\n");
$status = substr(fgets($smtp, 1024), 0, 3);
if($status != 250) return FALSE;
Wohin soll die Email gehen ? In diesem Schritt teilen wir dem SMTP Server unsere Support Emailadresse mit, an die er die Email versenden soll.
fputs($smtp, "DATA\r\n");
$status = substr(fgets($smtp, 1024), 0, 3);
if($status != 354) return FALSE;
Mit "DATA" teilen wir dem Server mit dass jetzt die eigentliche Email beginnt.
fputs($smtp, $header."\r\n\r\n");
fputs($smtp, $array['message']."\r\n");
fputs($smtp, ".\r\n");
Hier senden wir dem Server den oben definierten Emailheader, und gleich im Anschluss senden wir die vom Benutzer eingegebene Nachricht hinterher. Im effektivem Einsatz sollte man hier bei beachten ggf. noch ein paar Dinge zu filtern. Mit dem Punkt endet die Email.
$status = substr(fgets($smtp, 1024), 0, 3);
fputs($smtp, "QUIT\r\n");
fclose($smtp);
Wir fragen noch ein letztes mal den Statuscode ab und beenden anschließend die Verbindung. Mit "fclose" beenden wir das Socket.
if($status == 250)
{
return TRUE;
}
else
{
return FALSE;
}
Wenn als Statuscode "250" zurück gegeben wurde, ist alles glatt gelaufen. In diesem Fall kann die "send_mail" Funktion TRUE zurück liefern. Andernfalls eben den Statuscode.
WICHTIG !!! Hier noch der komplette Sourecode (für die Leute die zu faul zum lesen sind und einfach abkopieren )
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Kontaktformular</title>
</head>
<body>
<h1>Kontaktformular</h1>
<?php
if(isset($_POST['submit']))
{
$error = check_data($_POST);
if(!$error)
{
if(send_mail($_POST))
{
echo "Vielen Dank für ihre Anfrage, wir werden uns schnellst möglich mit ihnen in Verbindung setzen.";
}
else
{
echo "Beim versenden der Email ist leider ein Fehler aufgetreten";
}
}
else if(is_array($error))
{
echo "Folgende Fehler sind aufgetreten:\n";
echo "<ul>";
for($i=0; $i<count($error); $i++)
{
echo sprintf("<li>%s</li>\n", $error[$i]);
}
echo "</ul>";
}
}
function check_data($array)
{
$retval = array();
$error = array( "Bitte geben sie ihren Namen ein",
"Ihr Name enthält ungültige Zeichen",
"Ihr Name muss mindestens 5 Zeichen lang sein",
"Ihr Name darf maximal 15 Zeichen lang sein",
"Bitte geben sie ihre Emailadresse ein",
"Ihre Emailadresse ist ungültig",
"Bitte geben sie eine Nachricht ein" );
if(empty($array['user']))
{
array_push($retval, $error[0]);
}
else
{
if(!ctype_alnum($array['user']))
{
array_push($retval, $error[1]);
}
$len = strlen($array['user']);
switch($len)
{
case($len <= 5):
{
array_push($retval, $error[2]);
break;
}
case($len >= 15):
{
array_push($retval, $error[3]);
break;
}
}
}
if(empty($array['email']))
{
array_push($retval, $error[4]);
}
else if(!ereg('^[A-Za-z0-9]+([-_.]?[A-Za-z0-9])+@[A-Za-z0-9]+([-_.]?[A-Za-z0-9])+.[A-Za-z]', $array['email']))
{
array_push($retval, $error[5]);
}
if(empty($array['message']))
{
array_push($retval, $error[6]);
}
if(count($retval) == 0)
{
return FALSE;
}
else
{
return $retval;
}
}
function send_mail($array)
{
$header = "MIME-Version: 1.0\r\n";
$header .= "Content-type: text/html; charset=iso-8859-1\r\n";
$header .= "To: info@psp-hilfe.de\r\n";
$header .= "FROM: <".$array['email'].">\r\n";
$header .= "Subject: Kontaktformular\r\n";
$smtp = fsockopen("smtp.psp-hilfe.de", 25);
$status = substr(fgets($smtp, 1024), 0, 3);
if($status != 220) return FALSE;
fputs($smtp, "HELO ".$_SERVER['SERVER_ADDR']."\r\n");
$status = substr(fgets($smtp, 1024), 0, 3);
if($status != 250) return FALSE;
fputs($smtp, "AUTH LOGIN\r\n");
$status = substr(fgets($smtp, 1024), 0, 3);
if($status != 334) return FALSE;
fputs($smtp, base64_encode("test@psp-hilfe.de")."\r\n");
$status = substr(fgets($smtp, 1024), 0, 3);
if($status != 334) return FALSE;
fputs($smtp, base64_encode("pass")."\r\n");
$status = substr(fgets($smtp, 1024), 0, 3);
if($status != 235) return FALSE;
fputs($smtp, "MAIL FROM: <".$array['email'].">\r\n");
$status = substr(fgets($smtp, 1024), 0, 3);
if($status != 250) return FALSE;
fputs($smtp, "RCPT TO: email@email.email\r\n");
$status = substr(fgets($smtp, 1024), 0, 3);
if($status != 250) return FALSE;
fputs($smtp, "DATA\r\n");
$status = substr(fgets($smtp, 1024), 0, 3);
if($status != 354) return FALSE;
fputs($smtp, $header."\r\n\r\n");
fputs($smtp, $array['message']."\r\n");
fputs($smtp, ".\r\n");
$status = substr(fgets($smtp, 1024), 0, 3);
fputs($smtp, "QUIT\r\n");
fclose($smtp);
if($status == 250)
{
return TRUE;
}
else
{
return FALSE;
}
}
?>
<form method="POST" action="form.php">
<p>Name:<br /><input type="text" name="user" /></p>
<p>Emailadresse:<br /><input type="text" name="email" /></p>
<p>Nachricht: <br /><textarea name="message"></textarea></p>
<p><input type="submit" name="submit" /></p>
</form>
</body>
</html>