rob: Spamsicheres Kontaktformular

Beitrag lesen

Hi!

ich bin neu hier im Forum und auch noch nicht so gut in Html und php. Trotzdem würde ich gerne mein Kontaktformular erweitern und es spamsicherer machen.

Dann benutze die Forumssuche und/oder schaue im Archiv.
Zu Kontaktformularen und Email mit PHP wurde schon sehr viel geschrieben.
Deine Frage taucht im Prinzip hier alle paar Tage mal wieder auf.

Daher wurde eigentlich auch schon alles beantwortet. Trotzdem mache ich mir noch mal die Mühe und schreibe dir was zu deinem Code.
Wenn du mehr wissen willst, dann schau in das Archiv.

Auch Abfragen ob ein @ in der Emailadresse ist will ich einführen

Das ist unzureichend.
Du kannst eine Emailadresse auf syntaktische Korrektheit prüfen, indem du beispielsweise einen regulären Ausdruck einsetzt.
Folgende Funktion setze ich dafür meist ein.
Du kannst sie gerne verwenden.

function check_adress( $email )  
{  
 $expression = "^[_a-zA-Z0-9-](\.{0,1}[_a-zA-Z0-9-])*@([a-zA-Z0-9-]{2,}\.){0,}[a-zA-Z0-9-]{3,}(\.[a-zA-Z]{2,4}){1,2}$";  
  
 if ( preg_match( $expression, $email ) )  
 {  
  return true;  
 }  
 else  
 {  
  return false;  
 }  
}

und auch keine leeren Emails sollen möglich sein.

if ( !empty( trim( $_POST['nachricht'] ) ) )  
{  
 // weiter geht's  
}  
else  
{  
 $errorMsg = 'Sie haben den Nachrichtentext vergessen.';  
}

Auch wäre es genial, wenn man über einen Reiter die Auswahl des Betreffs wählen könnte und nur bei einer Auswahl die Email versendet wird.

Reiter? Was für ein Reiter?
Meinst du ein Pulldown-Menü? Das macht man mit HTML und select/option.
Aber wäre es vielleicht nicht sinnvoller, wenn der User selbst einen Betreffstext eingeben könnte?

Ich habe gelesen, man kann über unsichtbare Boxen Spambots stoppen usw.
Ich bin für jeden Tipp offen.

Man kann einiges tun...

Wenn du eine Suchmaschine fragst, wirst du unweigerlich irgendwann auf Captchas stoßen.
Davon würde ich allerdings abraten.
User, die mit einem Textbrowser oder Screenreader surfen, haben dann keine Möglichkeit mehr, dein Formular einzusetzen.
Es gäbe zwar noch die Möglichkeit, sich den Captcha-Code anzuhören (ich glaube, Ebay bietet das), aber es gibt auch User ohne Soundkarte und/oder entsprechendes Plugin.

In jedem Fall sind Captchas nichts für barrierefreie Seiten und schränken die Zugänglichkeit ein.

In Gästebüchern gehe ich meist den folgenden Weg. Bei deinem Mailformular könntest du ebenso vorgehen.
Ich generiere serverseitig einen Timestamp und bringe diesen in einem versteckten Formularfeld unter.
<input type="hidden" name="zeit" value="<?php echo time(); ?>">
Dies schicke ich dann zum Server zurück und gleiche es mit einem aktuellen Timestamp ab.
Ein Mensch braucht einige Sekunden, um so ein Formular auszufüllen und abzuschicken.
Ein Bot braucht nicht einmal eine Sekunde dazu.
Also mache ich den Gästebucheintrag (bzw. in deinem Fall Mailversand) nur dann, wenn mehr als ein oder zwei Sekunden von Generierung des Formulars bis zum Empfang der Daten vergangen sind.
Ob man eine Fehlermeldung ausgeben will oder einfach nichts macht, bleibt jedem selbst überlassen.

Eine weitere sinnvolle Sache ist sicher auch das Umbenennen deines Mailformulars.
Viele Spambots suchen sich ihre Ziele über Suchmaschinen.
Ich hatte auch einigen Sites ziemliche Probleme mit Gästebuch-Spam.
Nachdem die entsprechende Datei nicht mehr "gaestebuch.php", "guestbook.php" o.ä. hieß, sondern "sag_die_meinung.php" oder "schreibt_mir_doch.php", haben die Spamangriffe stark nachgelassen.
Daher solltest du deinem Mailformular am besten einen unauffälligen Namen verpassen.

<form name="form1" method="post" action="mail.php">
      <tr>
        <td>
          <input name="name" type="text" class="navigationPulldown" value="Name" size="47"></td>
      </tr><br><br>
      <tr>
        <td>
   <input name="email" type="text" class="navigationPulldown" value="Email" size="47"></td>
      </tr><br><br>
      <tr>
      <td>
          <textarea name="nachricht" cols="44" rows="5" class="navigationPulldown">Hallo Kellogs</textarea></td>
      </tr><br><br>
      <tr>
        <td>
          <input name="Senden" type="submit" class="navigationPulldown" value="Senden">
    <input name="Loeschen" type="reset" class="navigationPulldown" value="Löschen"></td>
      </tr>
</form>

Warum mißbrauchst du Tabellen für Layoutzwecke?
Tabellen sind für tabellarischen Inhalt gedacht.
Mittlerweile ist dieser Mißbrauch nicht mehr notwendig. Setze CSS ein.

Das Php sieht so aus:

hmm...
De fehlt 'ne ganze Menge an wichtigen Dingen...

if (!empty($_POST['Senden'])) {

Ist OK, aber ich hätte hier isset() eingesetzt.

@mail (
  // Empfaenger
  'email@email.de',
  // Betreff
  'Von ' . $_POST['name'] .' (' . $_POST['email'] . ')',
  // Body
  $_POST['nachricht']);
};

Und das ist mehr als gefährlich! Damit hast du wirklich eine Spamschleuder fabriziert.

Wieso schreibst du eigentlich den Absender in den Betreff?
Der Betreff ist halt für den Betreff da...

Den Absender kannst du als zusätzlichen Header angeben.
Die Funktion mail() bietet die Möglichkeit, zusätzliche Header zu übergeben.
Das solltest du auch nutzen.

Sicherlich möchtest du, daß Umlaute und Sonderzeichen auch korrekt in deiner Email angezeigt werden.
Daher solltest du in jedem Fall die verwendete Zeichenkodierung in der Mail mit angeben.
Außerdem solltest du angeben, in welchem Format die Mail verschickt werden soll: text/plain oder text/html oder beides (Multipart-Email).

Das könnte beispielsweise so aussehen:

$header = "MIME-Versin: 1.0\r\n";  
$header.= "Content-Type: text/plain; charset=ISO-8859-15\r\n";  
$header.= "Content-Transfer-Encoding: 8bit\r\n";  
$header.= "From: ". $absender ."\r\n";  
$header.= "X-Mailer: PHP/" . phpversion() . "\r\n";

//Gehe zur Seite zurueck ob nun gemailt wurde oder nicht
header('Location: ' . $_SERVER['HTTP_REFERER']);

Oh, oh, oh...
Das ist aber gar nicht gut.

Der Referer ist eine verdammt unzuverlässige Größe.
Du kannst niemals sicher sein, ob überhaupt ein Referer mitgesendet wird.
Du kannst auch nicht sicher sein, ob dieser korrekt ist.
Einige Clients senden keinen Referer und oftmals wird dieser rausgefiltert.
Möglicherweise wird der Referer von einem Proxy unterdrückt/verändert.
Vielleicht wird er aber auch von einer Desktop-Firewall, einem Anti-Werbe-Tool, einer Anonymisierungs-Software oder sonstwas gefiltert.
Du darfst dich also nicht auf den Referer verlassen.

Leite den User doch auf eine andere Seite weiter anstatt zurück.
Warum nicht eine Seite mit "Vielen Dank für ihre Email"?
Wenn du den User unbedingt wieder zurückleiten willst (was ich aber wirklich nicht verstehe), dann speichere die vorher besuchte Seite in einer Session.

Jetzt aber zur Sicherheit deines Scriptes:

Nie, nie, niemals darfst du Variablen, die von außen kommen, ungeprüft in dein Script übernehmen!

Alle Usereingaben müssen zwingend als "böse" eingestuft werden. Du mußt jede Eingabe überprüfen und eventuell bereinigen.

Beispiel:
'Von ' . $_POST['name'] .' (' . $_POST['email'] . ')'
Es dürfen sich in diesen Zeilen (und allen anderen Header-Zeilen) keine Zeichenumbrüche befinden.

Vielleicht denkst du dir, daß da gar keine Zeilenumbrüche drin sein könnten, weil du nur ein einzeiliges Eingabefeld (input type=text) zur Verfügung stellst.
Das ist falsch! Man kann problemlos Daten an dein Script schicken. Dazu braucht man dein Formular nicht.

So, jedenfalls: Headerzeilen werden durch Zeilenumbrüche voneinander getrennt.

Wenn man Umbrüche senden kann und du nicht ausreichend checkst, kann man der Mailfunktion zusätzliche Header (z.B. CC- oder BCC-Feld) mit übergeben.
Und schon kann man mit deinem Script, Spammails an Zig-Tausend Empfänger schicken.

Setze String-Funktionen (z.B. str_replace()) oder reguläre Ausrücke (z.B. preg_replace()) ein, um alle Zeilenumbrüche zu entfernen.
Du könntest nach \r, \n, \r\n suchen oder nach den ASCII-Werten: hexadezimal 0D und 0A, oktale 12 und 15, dezimal 13 und 10.

Sieh zu, daß in allen Feldern nur das drin steht, was du erwartest.
Führe Prüfungen durch.
Baust du die Variablen irgendwo ein, dann entferne alles, was potientiell gefährlich sein könnte bzw. generell alles, was dort nicht erwartet wird.

Es wäre genial, von euch direkt den Code zu bekommen.

Also das kannst du vergessen.
Das hier heißt "SelfForum" und das "Self" im Namen hat schon seinen Sinn.
Es bringt auch nichts, wenn dir jemand den Code deines Scriptes schreiben würde. Dann lernst du es ja nicht.
Hier wird schon Eigeninitiative erwartet.

Aber du bekommst genug Hinweise und Hilfestellung, so daß du das alleine hinbekommst.

Schöner Gruß,
rob