dis creative labs

labor

Übersicht / PHP / Einfacher Formmailer mit Reloadsperre

Einfacher Formmailer mit Reloadsperre

von Steffen Kamper

Da es immer wieder zu Nachfragen wegen Formmailern kommt, möchte ich hier eine einfache Variante vorstellen.

Ich habe eine einfache Formatierung per css vorgenommen, das kann natürlich alles nach Herzenslust verändert werden.

Das Script

Die Form besteht nur aus 3 Feldern, Name, Email und Message. Bei Fehlern wird der Fehlertext angezeigt und die entsprechenden Felder rot umrandet.

Folgende Pflichtangaben hab ich vorrausgesetzt:
  • Der Name muss aus mind. 3 Zeichen bestehen
  • Die Message muss aus mind. 10 Zeichen bestehen
  • Die Email-Adresse muss ein gültiges Format besitzen.

Der Quelltext

Der Name der Datei ist im Script mit $pagename angegeben (in diesem Fall formmailer.php). Soll die Datei unter einem anderen Namen laufen, so muss die Variable entsprechend geändert werden.

Im Kopf des Scriptes wird ermittelt, ob die Form abgesendet wurde und es folgen die entsprechenden Auswertungen.

Form-Attacken

In letzter zeit häufen sich Robscripts, die Webfornulare aufstöbern und in Felder z.B. ein "/r/nbcc: jrubin@aol.com" einfügen. Aus diesem Grund habe ich noch eine Routine zur Verhinderung solcher Attacken eingebaut.

PHP-Code:
<?php

/*******************************************/
/* formmailer.php                          */
/*                                         */
/* FORMMAILER mit Reloadsperre             */
/*                                         */
/* von Steffen Kamper                      */
/* erstellt für das Traumprojekt-Forum     */
/*                                         */
/*******************************************/


//erstmal Variablen definieren
$pagename="formmailer.php";
$error=$name=$email=$message="";

// an wen geht die Mail ?
$empfaenger="ich@zuhause.de";

if(isset(
$_POST['domail'])) {
    
// es wurde abschicken gedrückt, also erst mal die Felder holen
    
$name=get_magic_quotes_gpc() ? stripslashes($_POST['name']) : $_POST['name'];
    
$email=get_magic_quotes_gpc() ? stripslashes($_POST['email']) : $_POST['email'];
    
    
//Form-Attacken verhindern (suche nach \r\n oder \n)
    
if(strpos($name,"\r\n")>|| strpos($name,"\n")>0) {
        
DebugAttack(substr($name,strpos($name,"\r\n")));
        
$name="";
    }
    if(
strpos($email,"\r\n")>|| strpos($email,"\n")>0) {
        
DebugAttack(substr($email,strpos($email,"\r\n")));
        
$email="";
    }
    
    
//Message setzt sich aus allen Eingaben zusammen
    
$message=get_magic_quotes_gpc() ? stripslashes($_POST['message']) : $_POST['message'];
    
    
// wir setzen einen Flag, um Fehler zu registrieren
    
$ok=true;
    
//jetzt werden die Felder überprüft
    
if (strlen($name)<3// der Name muss mindestens 3 Zeichen haben
    
{
        
$err[0]=true//Fehler merken
        
$ok=false;    //Fehlerflag setzen
        
$error.='Bitte geben Sie Ihren Namen an. (mindestens 3 Zeichen)<br>'// Fehlertext
    
}
    if ( (!(
eregi('^[a-z0-9_\.-]+@[a-z0-9_-]+\.[a-z0-9_\.-]+$',$email))) && (strlen($email)>0) || $email=="")
    {
        
//email-Adresse ist ungültig
        
$err[1]=true;
        
$ok=false;
        
$error.='Bitte kontrollieren Sie die angegebene E-Mail-Adresse.<br>';
    }
    if (
strlen($message)<10// die Message muss mindestens 10 Zeichen haben
    
{
        
$err[2]=true//Fehler merken
        
$ok=false;    //Fehlerflag setzen
        
$error.='Bitte geben Sie eine Message von mindestens 10 Zeichen ein.<br>'// Fehlertext
    
}
    
// ist alles ok ? dann senden
    
if($ok)
    {
        
//Mail komponieren
        
$mailheader="From: formular@domain.de\r\nX-Mailer: PHP/" phpversion(). "\r\nX-Sender-IP: ".$_SERVER['REMOTE_ADDR']."\r\nContent-Type: text/html; charset=ISO-8859-1;";
        
$message=nl2br("Name: $name\nEmail: <a href=\"mailto:$email\">$email</a>\n<hr>$message");
        
$subject="Webseiten-Nachricht vom ".date("d.m.Y");
        if (@
mail($empfaenger$subject$message$mailheader)) {
            
//Alles ok, Seite neuladen (Reloadsperre)
            
header("Location:$pagename?success");
            
//falls kein Header gesendet werden kann, dann mit javascript
            //echo '<script type="text/javascript">document.location.href="'.$pagename.'?success"</script>';
            
exit;
        } else {
            
$error='<h3>Fehler beim Mailen aufgetreten</h3>';
        }
    } else {
        
// Fehler ausgeben
        
$error='<h3>Fehler bei der Eingabe</h3><p class="error">'.$error.'</p>';
    }
}
?>

Die Reloadsperre basiert darauf, das nach erfolgreichem mailen die Seite erneut mit dem Parameter ?success aufgerufen wird. Dadurch ist das $_POST-Array wieder leer und ein aktualisieren der Seite verursacht nicht ein erneutes verschicken des Formulars.

Der Clou ist, das unser Header unverändert bleibt. Das beugt jegliche Injection vor, das heisst, keiner kann noch zusätzliche Headeranweisungen in die Mail einschleusen. Wir sollten lediglich formular@domain.de durch eine aussagekräftige und gültige Emailadresse ersetzen.

Der Rest des Skriptes ist die HTML-Ausgabe mit der Form.

Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
	"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Form-Mailer</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css">
body {background:#fff;}
form {width:360px;}
label {display:block;}
input, textarea {font-size:11px;}
textarea {width:360px;height:240px;}
input.button {border:1px solid #000;background:#ffcc00;margin-top:12px;}
.fehler {border:1px solid red;}
p.error {color:red;}
</style>
</head>

<body>
<h1>Form-Mailer mit Reloadsperre</h1>
<?php
if($error!="") echo $error;
if(isset($_GET['success'])) {
	//Erfolgsnachricht ausgeben
	echo '<p>Vielen Dank für Ihre Nachricht. Sie wurde erfolgreich verschickt.</p>';
} else {
	// Form ausgeben
?>

<form action="<?php echo $pagename;?>" method="post" name="formmailer">
<fieldset><legend>Mail schreiben</legend>
<label for="name">Name</label>
<input type="Text" value="<?php echo $name;?>" maxlength="60" size="50" name="name" <?php if(isset($err[0])) echo  'class="fehler"';?>>
<label for="email">Email-Adresse</label>
<input type="Text" value="<?php echo $email;?>" maxlength="80" size="50" name="email" <?php if(isset($err[1])) echo  'class="fehler"';?>>
<label for="comment">Message</label>
<textarea cols="10" rows="10" name="message" <?php if(isset($err[2])) echo  'class="fehler"';?>><?php echo $message;?></textarea>
<input type="reset" class="button" value="zurücksetzen" name="reset">
<input type="submit" class="button" value="abschicken" name="domail">
</fieldset>
</form>
<?php
}

function DebugAttack($s) {
	//Hier den Pfad für die Protokolldatei einfügen, wenn kein Protokoll erwünscht ist, einfach auskommentieren
	$fp=fopen("/tmp/attack.txt","ab");
	fwrite($fp,$s);
	fclose($fp);
}

?>
</body>
</html>

Das Skript ist einfach aufgebaut und lässt sich einfach erweitern. Viel Spass beim Einbau in Eure Seite!

Download des Scripts

Kommentare 9 Kommentare

Kommentar von Puro

vom 15.10.2006 19:20

Hallo
erstmal vielen Dank dafür das es jemanden gibt der zwar simple aber für Anfäger wie mich doch sehr komplizierte Skripts zur Verfügung stellt !

Ich habe aber ein Problem mit dem Skript !

bei der ersten Version des Skriptes stehen immer Fehlermeldungen am Kopf des Formulares wenn ich es in der Vorschau oder im explorer ansehen möchte!

und bei der zweiten Version habe ich das Problem das jedes mal wenn ich versuche es in der Vorschau oder im Explorer zu laden das die Meldung ( Seite kann nicht angezeigt werden kommt )

Was mache ich falsch oder was kann ich ändern ?

vielen vielen Dank im Vorraus


Gruß
Puro aus dem TP

Kommentar von Elton

vom 09.05.2006 01:48

Huhu,

kann mir bitte jemand sagen ob der download die aktuellste version ist?

Danke!

Gruß, Elton

Kommentar von Björn

vom 04.04.2006 07:27

Eventuell einfach auf \s per preg_match prüfen ;) Das schließt dann alle Whitespaces ein!!

Kommentar von steffen

vom 02.03.2006 19:42

Hallo Jan,

Du hast völlig recht, für einen Webserver reicht auch \n

Da ich jetzt aber nichts mehr in den Header packe, ist Injection ausgeschaltet, die protokollierung für Atackversuche ist allerdings davon betroffen, hier muss man beides prüfen (\r\n und \n), also eine Änderung nach
PHP-Code:

<?php

if(strpos($name,"\r\n")>|| strpos($name,"\n")>0) {
...

?>



Danke für den Hinweis.

Kommentar von Jan

vom 02.03.2006 18:41

Ein simpler Check auf die Zeichenfolge \r\n ist m.E. nicht ganz sauber, sonder man sollte auf eines dieser Zeichen prüfen, da (soweit ich weiss) auch ein einzelner \n u.U. vom Mailserver angenommen wird… oder war es ein \r ? Egal… sobald eines dieser Zeichen in der Variable vorkommt passt was nicht ;)

Gruss
Stuck Mojo aus dem TP ;-)

Kommentar von steffen

vom 02.03.2006 18:33

Die Fehler sind ausgemerzt und das Script ist zusätzlich gegen Injection gesichert.

Viel Erfolg damit ;)

Kommentar von Wolfgang

vom 28.10.2005 16:02

Kleiner Fehler im Script:

PHP-Code:

<?php
//Form-Attacken verhindern
    
if(strpos($name,"\r\n")>0) {
        
DebugAttack(substr($name,strpos($name,"\r\n"))); // 3 Klammern zum Schluss
        
$name="";
    }
    if(
strpos($email,"\r\n")>0) {
        
DebugAttack(substr($email,strpos($email,"\r\n"))); // 3 Klammern zum Schluss
        
$email="";
    }
?>



In den Zeilen mit DebugAttack fehlt jeweils die letzte schließende Klammer.

Grüße
Wolfgang

Kommentar von steffen

vom 26.10.2005 09:34

Hallo Wolfgang,
ganz einfach - die probieren, ob sie die Mail bekommen. Wenn ja, eignet sich das Formular zum Missbrauch von Spam.

Kommentar von Wolfgang

vom 25.10.2005 18:25

Hallo Steffen, seltsam, dass hier bisher noch keine Kommentare stehen. Naja, dann fang ich mal an:

Tolle Seite, schöne Optik, super Scripte - bin beeindruckt

Frage: Könntest Du kurz erläutern, was die Script-Hansel mit dem "/r/nbcc: jrubin@aol.com" erreichen wollen? Also welche konkrete Gefahr/Unannehmlichkeit damit verbunden ist?

Danke
Wolfgang aus dem TP


Die Kommentarfunktion wurde wegen übermässigem Spam vorläufig gesperrt

Übersicht / PHP / Einfacher Formmailer mit Reloadsperre

  nach oben