Nathi: Formmailer - PHP, Perl od. Javascript?

Hallo Zusammen,

Zu allererst: ja, ich habe die Suchfunktion benutzt und auch die Frommailer auf dieser Seite entdeckt!
Was mich aber an allen gefundenen Skripten ärgert, ist die unzureichende Berücksichtigung von Pflichtfeldern! Entweder, diese können gar nicht erst definiert werden oder es erfolgt bei "Nichtausfüllen" eine Weiterleitung auf eine "Error-Page", die man erst wieder durch den "Zurück-Button" im Browser verlassen kann, um fehelende Felder auszufüllen (meistens ist dann auch noch der Text weg, der bisher geschrieben wurde)!
Ich suche eine elegantere Lösung, wie diese hier
Fehlermeldung erscheint innerhalb der aktuellen Page ohne Weiterleitung und nicht ausgefüllte Felder werden rot markiert!
Kann mir jemand sagen, wie das gemacht wird? Das scheinnt ja weder über Perl, noch PHP realisiert worden zu sein, oder?

Würd mich über eine Antwort freuen,

Gruß,

Nathi

  1. Liebe(r) Nathi,

    Du beschreibst ein "Affenformular".

    Wenn Du den einfachen Formmailer in PHP zu Grunde legst, dann kannst Du der Reihe nach die Indices in $_POST überprüfen, um im Fehlerfalle eine Variable entsprechend zu befüllen und das Formular eben wieder ausgeben.

    Beispiel für ein Affenformular:

    <?php  
    /* Formular auswerten */  
    $fehler = false; // Noch ist alles OK.  
      
    if (!empty($_POST)) {  
        // Es wurden POST-Daten gesendet -> Auswerten!  
        $pflichtfelder = array("vname", "nname", "adresse", "plz", "ort");  
      
        foreach ($pflichtfelder as $pf) {  
            if (!isset($_POST[$pf]) || empty($_POST[$pf])) {  
                $fehler = true;  
            }  
        }  
      
        // Verarbeiten oder Formular wieder ausgeben?  
        if (!$fehler) {  
            // Verarbeiten!  
            echo "Vielen Dank. Die Daten wurden verarbeitet.";  
        }  
      
    }  
      
    if ($fehler || empty($_POST)) {  
        // Formular ausgeben (entweder war $_POST leer oder $fehler war true)  
      
    ?>
    ~~~~~~html
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">  
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de">  
        <head>  
            <title>Einfacher PHP-Formmailer</title>  
            <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />  
            <style type="text/css">
    

    ~~~css .fehler {
                background-color: #ff8080;
                border-color: #ff0000;
            }

            ~~~html
    </style>  
        </head>  
        <body>  
            <h1>Beispielformular</h1>  
            <form action="<?php print $_SERVER['PHP_SELF']; ?>" method="post">  
                <!-- Hier die eigentlichen Formularfelder eintragen. Die folgenden sind Beispielangaben. -->  
                <dl>  
                    <dt><label for="vname">Ihr Vorname</label>:</dt>  
                    <dd><input type="text" name="vname" id="vname" 
    ~~~~~~php
    <?php  
        $test = isset($_POST["vname"]) ? $_POST["vname"] : "";  
        echo 'value="', $test, '"';  
        if (empty($test) && $fehler)  
            echo ' class="fehler"';  
                    ?>
    ~~~ ~~~html
    /></dd>  
                    <dt><label for="nname">Ihr Nachname</label>:</dt>  
                    <dd><input type="text" name="nname" id="nname" 
    ~~~~~~php
    <?php  
        $test = isset($_POST["nname"]) ? $_POST["nname"] : "";  
        echo 'value="', $test, '"';  
        if (empty($test) && $fehler)  
            echo ' class="fehler"';  
                    ?>
    ~~~ ~~~html
    /></dd>  
                    <dt><label for="adresse">Ihre Anschrift</label>:</dt>  
                    <dd><input type="text" name="adresse" id="adresse" 
    ~~~~~~php
    <?php  
        $test = isset($_POST["adresse"]) ? $_POST["adresse"] : "";  
        echo 'value="', $test, '"';  
        if (empty($test) && $fehler)  
            echo ' class="fehler"';  
                    ?>
    ~~~ ~~~html
    /></dd>  
                    <dt><label for="plz">PLZ</label> und <label for="ort">Wohnort</label>:</dt>  
                    <dd>  
                        <input type="text" name="plz" id="plz" 
    ~~~~~~php
    <?php  
        $test = isset($_POST["plz"]) ? $_POST["plz"] : "";  
        echo 'value="', $test, '"';  
        if (empty($test) && $fehler)  
            echo ' class="fehler"';  
                    ?>
    ~~~ ~~~html
    />  
                        <input type="text" name="ort" id="ort" 
    ~~~~~~php
    <?php  
        $test = isset($_POST["ort"]) ? $_POST["ort"] : "";  
        echo 'value="', $test, '"';  
        if (empty($test) && $fehler)  
            echo ' class="fehler"';  
                    ?>
    ~~~ ~~~html
    />  
                    </dd>  
                </dl>  
                <!-- Ende der Beispielangaben -->  
                <p>  
                <input type="submit" value="Senden" />  
                <input type="reset" value="Zurücksetzen" />  
                </p>  
            </form>  
        </body>  
    </html>
    
    <?php  
    }  
    ?>
    

    Du siehst wahrscheinlich selbst, dass obiger Code suboptimal ist. Besser wäre es, den HTML-Code in eine HTML-Datei auszulagern, die dann vom eigentlichen PHP-Script eingelesen, und bei Bedarf modifiziert wird.

    Ich mache das eher so:

    [HTML-Datei "formular-template.html"]

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">  
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de">  
        <head>  
            <title>Einfacher PHP-Formmailer</title>  
            <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />  
            <style type="text/css">
    

    ~~~css .fehler {
                background-color: #ff8080;
                border-color: #ff0000;
            }

            ~~~html
    </style>  
        </head>  
        <body>  
            <h1>Beispielformular</h1>  
            <form action="" method="post">  
                <!-- Hier die eigentlichen Formularfelder eintragen. Die folgenden sind Beispielangaben. -->  
                <dl>  
                    <dt><label for="vname">Ihr Vorname</label>:</dt>  
                    <dd><input type="text" name="vname" id="vname" /></dd>  
                    <dt><label for="nname">Ihr Nachname</label>:</dt>  
                    <dd><input type="text" name="nname" id="nname" /></dd>  
                    <dt><label for="adresse">Ihre Anschrift</label>:</dt>  
                    <dd><input type="text" name="adresse" id="adresse" /></dd>  
                    <dt><label for="plz">PLZ</label> und <label for="ort">Wohnort</label>:</dt>  
                    <dd>  
                        <input type="text" name="plz" id="plz" />  
                        <input type="text" name="ort" id="ort" />  
                    </dd>  
                </dl>  
                <!-- Ende der Beispielangaben -->  
                <p>  
                    <input name="submit-button" type="submit" value="Senden" />  
                </p>  
            </form>  
        </body>  
    </html>
    

    [PHP-Datei "test.php"]

    <?php  
    /* Formular auswerten */  
    $fehler = false; // Noch ist alles OK.  
    $pflichtfelder = array("vname", "nname", "adresse", "plz", "ort");  
      
    if (!empty($_POST)) {  
        // Es wurden POST-Daten gesendet -> Auswerten!  
      
        foreach ($pflichtfelder as $pf) {  
            if (!isset($_POST[$pf]) || empty($_POST[$pf])) {  
                $fehler = true;  
            }  
        }  
      
        // Verarbeiten oder Formular wieder ausgeben?  
        if (!$fehler) {  
            // Verarbeiten!  
            echo "Vielen Dank. Die Daten wurden verarbeitet.";  
        }  
    }  
      
    if ($fehler || empty($_POST)) {  
        // Formular ausgeben (entweder war $_POST leer oder $fehler war true)  
        $html = file_get_contents('formular-template.html');  
      
        foreach ($pflichtfelder as $pf) {  
            $test = isset($_POST[$pf]) ? $_POST[$pf] : "";  
            $html_zusatz = 'value="'.$test.'"';  
            if (empty($test) && $fehler)  
                $html_zusatz .= ' class="fehler"';  
      
            $html = preg_replace('~(?is)(id="'.$pf.'")~', '\\1 '.$html_zusatz, $html);  
        }  
      
        echo $html;  
    }  
    ?>
    

    Hoffentlich hilft's...

    Liebe Grüße,

    Felix Riesterer.

    --
    ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
    1. Hallo Felix,

      Du beschreibst ein "Affenformular".

      Aha, manchmal weiß man halt auch einfach nicht wonach man zu suchen hat ;-)! Vielen lieben Dank für deine Hilfe! Werde das heute nach der Arbeit gleich mal ausprobieren!

      Gruß, Nathalie

      1. Liebe Nathi,

        Werde das heute nach der Arbeit gleich mal ausprobieren!

        und? Erfolgreich gewesen?

        Liebe Grüße,

        Felix Riesterer.

        --
        ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
        1. Hallo Felix,

          Lieber Nathi,

          Bin ein "Mädchen", also ohne ..r ;-) !
          Bin gerade dabei, mir das Skript verständlich zu machen! Wollte das nicht einfach stupide übernehmen, ohne zu verstehen, was da genau passiert! Und mit php hatte ich bis jetzt noch nicht so viel zu tun! Aber hab ja noch die ganze Nacht Zeit, da ich morgen frei hab! Vielleicht schaffe ich es ja die Nacht noch, das ganze im Corporate-Style meiner Website zu implementieren...
          Danke dir/euch für eure Bemühungen,

          Gruß, Nathi (Nathalie ;-))

    2. Hallo,

      $test = isset($_POST[$pf]) ? $_POST[$pf] : "";
              $html_zusatz = 'value="'.$test.'"';

      Unsichere Daten aus $_GET/$_POST/$_COOKIE sollte man auf keinen Fall direkt ins HTML reinschreiben, sie müssen vorher bereinigt und dem Kontext entsprechend maskiert werden, d.h. mindestens mit htmlspecialchars.

      Mathias

      1. Lieber molily,

        Unsichere Daten aus $_GET/$_POST/$_COOKIE sollte man auf keinen Fall direkt ins HTML reinschreiben, sie müssen vorher bereinigt und dem Kontext entsprechend maskiert werden, d.h. mindestens mit htmlspecialchars.

        ja, Du hast Recht. Mein Code war eben wieder einmal "quick and dirty"...

        Liebe Grüße,

        Felix Riesterer.

        --
        ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
      2. Hallo,

        Unsichere Daten aus $_GET/$_POST/$_COOKIE sollte man auf keinen Fall direkt ins HTML reinschreiben, sie müssen vorher bereinigt und dem Kontext entsprechend maskiert werden, d.h. mindestens mit htmlspecialchars.

        Vielen Dank für den Hinweis! Soll ich dann einfach den ganzen Code ändern, indem ich $_post gegen htmlspecialchars($_post)austausche? Oder geht das auch mit diesem netten Tool hier zuverlässig?

        Liebe Grüße, Nathi

        1. Lieber Nathi,

          Du machst einfach das hier:

          $test = isset($_POST[$pf]) ? htmlspecialchars($_POST[$pf]) : "";

          Und dann sollte alles Weitere passen.

          Liebe Grüße,

          Felix Riesterer.

          --
          ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
          1. Hi Felix,

            Sorry, wenn ich nochmal störe!

            Du machst einfach das hier:

            $test = isset($_POST[$pf]) ? htmlspecialchars($_POST[$pf]) : "";

            Und dann sollte alles Weitere passen.

            Reicht das, wenn ich das nur bei dem von dir genannten Teil des Scriptes ändere oder müsste das htmlspecialchars auch für die anderen $_POST-Elemente im Skript geändert werden?

            Liebe Grüße

            1. So, habe das ganze jetzt (endlich) soweit hinbekommen, dass mir eine e-mail zugesandt wird! Jetzt noch zwei Fragen:

              1. Hab beim googlen diverse Beiträge gesehen, in denen es heißt, dass htmlspecialchars nicht mehr notwendig sei, wenn ich die Php-Datei auslagere und aus der HTML-Datei anspreche gemäß:

              <form action="sendmail.php" method="post">

              Stimmt das? Das hattest du (Felix) mir ja ohnehin in deiner zweiten "Version" empfohlen, wenn ich das richtig verstanden habe!?

              2. Ich bekomme beim Absenden des Formulars eine e-mail an meine Adresse, und das hat mich ja schon mal sehr gefreut ;-) ! Jedoch ohne Text! Was muss ich in das php-Script noch einfügen, dass die Felder auch ausgelesen werden? Evtl. den ganzen php-Block des Formmailers? Habe nämlich bisher nur den Code:

              mail("empfängermailadresse", "Betreff der mail", mailtext, "From:absender");

              hinzugefügt, aber das scheint ja nicht zu funktionieren!
              Würde mich freuen, wenn mir da nochmals geholfen wurde!

              Muss mir da wohl morgen mal ein PHP-Büchlein zulegen! PHP lässt sich ja leider nicht sachlogisch erschließen, auch wenn man HTML/Javascript Kenntnisse hat!

              Vielen lieben Dank, Gruß Nathi

              1. Hallo

                1. Hab beim googlen diverse Beiträge gesehen, in denen es heißt, dass htmlspecialchars nicht mehr notwendig sei, wenn ich die Php-Datei auslagere und aus der HTML-Datei anspreche gemäß:

                <form action="sendmail.php" method="post">

                Stimmt das? Das hattest du (Felix) mir ja ohnehin in deiner zweiten "Version" empfohlen, wenn ich das richtig verstanden habe!?

                Da hast du ihn nicht ganz richtig verstanden. Ihm ging es darum, entsprechend dem EVA-Prinzip, die HTML-Ausgabe (A von EVA) vom Rest des Skripts (E für Eingabe, V für Verarbeitung) zu trennen. Zudem würdest du mit deinem obigen Vorgehen (Aufruf eines externen Skripts) das Affenformular aufgeben.

                Zu den einzelnen Schritten (bezogen auf ein Affenformular):

                E für Eingabe: Die Eingabe erfolgt durch den Aufruf des Skripts.

                Fall 1: Es wird einfach nur aufgerufen, es kommen also keine Daten aus dem Formular. Es wird nur der HTML-Quelltext mit leerem Formular (bzw. mit eventuell gewünschten Vorbelegungen der Formularfelder) ausgegeben.

                Fall 2: Das Formular wird abgeschickt, es liegen (mehr oder minder stimmige) Eingaben vor. Sie müssen überprüft werden, womit wir zu V wie Verarbeitung kommen.

                V für Verarbeitung:

                Die übergebenen Werte aus dem Formular sollen bestimmten Kriterien entsprechen. Es kann aber sein, dass vollkommen nutzlose oder gar schädliche Eingaben gemacht wurden. Dies geht recht einfach. Man kopiere den HTML-Quelltext und ändere das Formular und dann den zu übergebenden Inhalt.

                Beispiele für Prüfungen:
                Werte müssen in einem spezifizierten Bereich liegen. Dies können numerische Bereiche (z.B. Stunden zwischen 0 und 24) sein. Es kann sich dabei aber auch um Texte handeln, die beispielsweise in den <option>s eines <select>s notiert sind. Solche Dinge kann man z.B. mit in_array prüfen, wenn man die erlaubten Werte in Prüfarrays vorhält (die man auch zum skriptgesteuerten Aufbau des Formulars benutzen kann). In bestimmten Fällen prüft man gegen reguläre Ausdrücke, die bezüglich des erlaubten Wertebereichs flexibler sind.

                Es kommen natürlich auch freie Texte vor. Diese kann man schlecht gegen konkrete Vorgaben prüfen. In solchen Fällen prüft man, ob die entsprechenden Werte nicht leer (was natürlich auch eine konkrete Vorgabe ist) sind, was im Falle von Pflichtfeldern zur Wiedervorlage des Formulars mit Markierung der fehlenden Eingaben führt.

                Nach der Prüfung sämtlicher Eingaben muss also entschieden werden, ob alle Eingaben ihre Richtigkeit haben, was zum Versenden der Email oder auch zum Speichern der Eingaben in einer Datenbank führt, oder ob Eingaben fehlen; Folge: das Formular wird erneut aufgerufen.

                Nun sind wir bei A wie Ausgabe:

                Fall 1: Ausgabe des leeren Formulars
                (siehe Eingabe, Fall 1)

                Fall 2: Es fehlen Eingaben
                Das Formular wird mit Vorbelegung jener Formularfelder, deren Eingaben bereits gültig sind und mit Markierung der Felder, deren Eingaben fehlerhaft waren bzw. fehlten, aufgerufen.

                Fall 3:
                Alle Eingaben sind erfolgt und die Email wurde versandt oder die Daten wurden gespeichert. Man kann nun z.B. eine Danksagung ausgeben ("Danke für blablabla, folgende Daten wurden versendet/gespeichert: .....").

                All diese Aufgaben können innerhalb eines Skripts erledigt werden. Eben ein Affenformular.

                Um auf deine Frage zur Maskierung zurückzukommen: Jede Ausgabetechnik erfordert eine spezielle Maskierung, da es für viele Sprachen unterschiedliche Maskierungsregeln gibt. Eine Ausnahme dürfte hierbei Plaintext sein, also das, was du auch in einem Editor schreiben würdest.

                Werden nun Daten in HTML eingefügt, *müssen* diese Daten nach den Regeln von HTML maskiert werden. Genau dazu dient bei PHP htmlspecialchars. Dabei ist es egal, welches Skript dies tut -es könnte ja z.B. mit include in das aufgerufene Skript eingefügt worden sein- es ist nur wichtig, dass als Ausgabemedium HTML zum Einsatz kommt. Das würde z.B. dann zutreffen, wenn du dem Besucher nach dem Versand der Email die Eingaben noch einmal anzeigst. *Aber auch erst dann, wenn du das tust!*

                Würdest du deine Daten aus dem Formular nach der erfolgreichen Prüfung in eine MySQL-Datenbank speichern, müsstest du die Daten bei der Übergabe nach den Regeln von MySQL maskieren, dazu gibt es in PHP die Funktion mysql_real_escape_string. Für Anfänger verwirrende besonderheit dabei: Die Maskierung erfolgt konkret für die Übergabe der Daten an die Datenbank. *In* der Datenbank liegen die Daten dann wieder unmaskiert vor und werden bei einer eventuellen Ausgabe wieder dem Kontext entsprechend (z.B. HTML->htmlspecialchars) maskiert.

                Andere Medien würden, ihren eigenen Regeln entsprechend, andere Maskierungen erfordern.

                1. Ich bekomme beim Absenden des Formulars eine e-mail an meine Adresse, und das hat mich ja schon mal sehr gefreut ;-) ! Jedoch ohne Text! ...

                mail("empfängermailadresse", "Betreff der mail", mailtext, "From:absender");

                mailtext ist eine Kostante, keine Variable. Wenn die Variable wirklich diesen Namen trägt, hast du nur das dem Namen vorangestellte "$" vergessen.

                Tschö, Auge

                --
                Die deutschen Interessen werden am Liechtenstein verteidigt.
                Veranstaltungsdatenbank Vdb 0.2
                1. Hui, das war aber ausführlich! Vielen lieben Dank! Bin jetzt auch etwas besser in der Materie drin, da ich mir "PHP für Dummies" zugelegt habe!

                  Also nochmals vielen lieben Dank euch für die super Hilfe!

                  Gruß, Nathi

              2. Hi,

                mail("empfängermailadresse", "Betreff der mail", mailtext, "From:absender");

                der Unterschied zwischen Konstanten und Variablen wurde Dir ja schon erklärt. "empfängermailadresse" dürfte in Wirklichkeit Deine Mailadresse enthalten, aber was ist mit "absender"? Das wird doch hoffentlich nicht $absender bzw. $_POST['absender'] sein, oder?
                Falls doch, dann solltest Du meinen Tipp zu sicheren Formmailern lesen.

                freundliche Grüße
                Ingo

            2. Liebe Nathi,

              wie Auge weiter unten schon schrieb: Eingegebene Daten müssen ihrem Kontext nach maskiert werden. Immer dann, wenn Daten aus $_POST wieder an den Browser zurück gegeben werden sollen, müssen sie ihrem Kontext entsprechend (und das ist hier HTML) maskiert werden.

              Da in meinem Script-Beispiel der Inhalt von $_POST in die Variablen $test übernommen werden soll, um dann später als HTML-Code ausgegeben zu werden (genauer: als Inhalt eines value-Attributs), muss hier an dieser Stelle
              $test = htmlspecialchars($irgendwas);
              stehen. Nur hier. Vorher wird ja nur darauf geprüft, ob ein gewisser Index in $_POST ünberhaupt vorhanden, und wenn, ob er leer oder gefüllt ist, geprüft. Da muss deshalb nix umgewandelt werden.

              Liebe Grüße,

              Felix Riesterer.

              --
              ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
  2. Hi,

    Ich suche eine elegantere Lösung, wie diese hier

    Vorbilder sind mit Vorsicht zu genießen. Ich finde es beispielsweise nicht besonders elegant, wenn ein Formular *gar nicht* abgeschickt werden kann - so bei dem von Dir genannten Beispiel. Ohne JavaScript geht da *nichts*.

    Das scheinnt ja weder über Perl, noch PHP realisiert worden zu sein, oder?

    Das lässt sich zwar unmöglich ermitteln, ohne das Innere des Servers zu betrachten; aber es gibt ja noch genügend andere serverseitige Techniken, mit denen man derlei Dinge tun kann. Hier allerdings haben die Entwickler schlichtweg versagt, weswegen ich die Frage nach der Technik für müßig halte.

    Cheatah

    --
    X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
    X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
    X-Will-Answer-Email: No
    X-Please-Search-Archive-First: Absolutely Yes