Hallo allemaal,

Ik heb met HTML5 (Bootstrap3) een contactformulier gemaakt.

Omdat ik de server taal PHP niet beheers ben ik opzoek gegaan naar een veilige code. Via w3schools.com kwam ik
een uitgebreid PHP script tegen voor formulieren.
https://www.w3schools.com/php/showphp.asp?filename=demo_form_validation_complete

Omdat ik het ingevulde formulier graag naar een e-mail adres wil laten sturen ben ik weer opzoek gegaan. Via phphulp.nl en PHPwiki heb ik stukjes code gevonden en vervolgens geprobeerd die stukjes script aan de code van w3schools.com toe te voegen. Klopt de code nu nog wel? Wellicht de volgorde?

Ik zie door de bomen het bos niet meer. Kan iemand mij alstublieft helpen?



<?php 
	
if(isset($_POST['emailadres'])) 
{
	$email_from = "[email protected]";
	$email_to = "[email protected]";
	$email_subject = "Contactform";
	
	$emailadres = filter_input(INPUT_POST,'emailadres', FILTER_VALIDATE_EMAIL);
	$naam = $_POST['naam'];
	$plaats = $_POST['plaats'];
	$email = $_POST['email'];
	$geslacht = $_POST['geslacht'];
	$comment = $_POST['comment'];
	$html = true;


$email_message = nl2br;

$headers .= "From:". $email_from . "\r\n";
$headers .= "To:". $email_to . "\r\n";
$headers .= "X-Mailer: PHP/".phpversion(). "\r\n";
$headers .= ($html) ? "MIME-Version: 1.0" . "\r\n";
$headers .= ($html) ? "Content-type:text/html;charset=UTF-8" . "\r\n";

@mail($email_to,$email_subject,$email_message,$headers);	
}
	
// define variables and set to empty values
$naamErr = $plaatsErr = $emailErr = $geslachtErr = $commentErr "";
$naam = $plaats = $email = $geslacht = $comment "";

if ($_SERVER["REQUEST_METHOD"] == "POST") {
  if (empty($_POST["naam"])) {
    $naamErr = "Typ uw naam in";
  } else {
    $naam = test_input($_POST["naam"]);
    // check if name only contains letters and whitespace
    if (!preg_match("/^[a-zA-Z ]*$/",$naam)) {
      $naamErr = "Alleen letters en spaties"; 
    }
  }
  
  if (empty($_POST["plaats"])) {
    $plaatsErr = "Typ uw woonplaats in";
  } else {
    $plaats = test_input($_POST["plaats"]);
    // check if name only contains letters and whitespace
    if (!preg_match("/^[a-zA-Z ]*$/",$plaats)) {
      $plaatsErr = "Alleen letters en spaties"; 
    }
  }
  
  
  if (empty($_POST["email"])) {
    $emailErr = "Typ geldig email adres";
  } else {
    $email = test_input($_POST["email"]);
    // check if e-mail address is well-formed
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
      $emailErr = "Ongeldige email"; 
    }
  }
    
	 if (empty($_POST["geslacht"])) {
    $geslachtErr = "Maak geslachts keuze";
  } else {
    $geslacht = test_input($_POST["geslacht"]);
  }
}
	
  if (empty($_POST["comment"])) {
    $comment = "Typ uw opmerking of vraag";
  } else {
    $comment = test_input($_POST["comment"]);
	// check if name only contains letters and whitespace
    if (!preg_match("/^[a-zA-Z ]*$/",$plaats)) {
      $plaatsErr = "Alleen letters en spaties"; 
  	}
  }


function test_input($data) {
  $data = trim($data);
  $data = stripslashes($data);
  $data = htmlspecialchars($data);
  return $data;
}
?>

	
<form class="form-horizontal" method="post" name="contactform" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">	
	
<h6>* Verplichte velden</h6><br />							
<div class="form-group row">
<label for="naam" class="col-sm-2 col-form-label">naam*</label>
<div class="col-sm-2">
<input class="form-control" type="text" name="naam" id="naam" placeholder="voor en achternaam" required>
<span class="error"><?php echo $naamErr;?></span>
</div>
</div>
				
<div class="form-group row">
<label for="plaats" class="col-sm-2 col-form-label">Woonplaats*</label>
<div class="col-sm-2">
<input class="form-control" type="text" name="plaats" id="plaats" required>
<span class="error"><?php echo $plaatsErr;?></span>
</div>
</div>
	
<div class="form-group row">
<label for="email" class="col-sm-2 col-form-label">E-mail*</label>
<div class="col-sm-3">
<input class="form-control" type="email" name="email" placeholder="[email protected]" id="email" required>
<span class="error"><?php echo $emailErr;?></span>
</div>
</div>
				
<div class="form-group row">
<label for="geslacht" class="col-sm-2">Geslacht*</label>
<div class="col-sm-2">
<select class="form-control" name="geslacht" id="geslacht">
<option>Man</option>
<option>Vrouw</option>
</select>
<span class="error"><?php echo $geslachtErr;?></span>
</div>
</div>
				
<div class="form-group row">
<label for="comment" class="col-sm-2">Opmerking*</label>
<div class="col-sm-5">
<textarea class="form-control" rows="3" name="comment" id="comment"></textarea>
<span class="error"><?php echo $commentErr;?></span>
</div> 
</div>	
				
<div class="form-group row">
<div class="col-sm-2"></div>
<div class="col-sm-2">
<button type="submit" class="btn btn-primary" value="sent">Verzend</button>	
</div>	
</div>	
</form>

<?php
echo "<h2>Your Input:</h2>";
echo $naam;
echo "<br />";
echo $plaats;
echo "br />"
echo $email;
echo "<br />";
echo $geslacht;
echo "<br />";
echo $comment;
echo "<br />";
?>

De structuur is niet echt super netjes. Het is bij PHP niet enkel een kwestie van code kopiëren en plakken, maar je zult ook moeten begrijpen wat er gebeurt.

Uiteindelijk krijg je een aansluitend geheel en steekt de puzzel in elkaar.

Ik zal vanavond (mits iemand anders mij voor is) een voorbeeldje maken, zodra ik gegeten heb ;-)
Waar komt die idiote test_input functie vandaan? Ik zie hem vaker voorbij komen, de bedenker daarvan moet serieus een schop onder zijn/haar kont hebben.
W3schools. Ze begrijpen niet dat je output moet beveiligen, en juist niet de input.
@Anja, ik neem aan dat je op regel 6 de daadwerkelijke (e-mail)bestemming invult?

Dan mis je op regel 18 waarschijnlijk een verwijzing naar $comment, dit moet mogelijk zoiets zijn als:
$email_message = nl2br($comment);


Verder ziet het er in de gauwigheid wel ok uit, afgezien van enkele technische keuzes misschien *kuch* :).

Maar kun je concreet aangeven of/wat er precies misgaat? Als de bestemming klopt ($email_to) zou je -indien alles verder ok is- op den duur een e-mailbericht moeten ontvangen. Indien daar geen sprake van is kunnen we verder op zoek gaan naar mogelijke oorzaken.

Dus parkeer het script in een tijdelijke directory en probeer het eens uit :). Mogelijk wil je op den duur wel een soort van controle inbouwen tegen spam, maar dat is stap 2 of 3, voor nu heb je in principe genoeg code om snel te testen of dit werkt.

Voor ontwikkeling zou je bovenaan de code nog tijdelijk het volgende kunnen toevoegen:
<?php
// voor ontwikkeling
error_reporting(E_ALL);
ini_set('display_errors', 'stdout');
?>

Dit zorgt ervoor dat je code "mondig" is in het melden van fouten, deze worden dan op je scherm gedumpt, dit kan een handig geheugensteuntje zijn voor als je ergens iets vergeten bent en/of ergens een typefout hebt gemaakt ofzo.
Ik dacht dat W3schools best hoog staat aangeschreven, maar dat script van hun is om te janken.
Is het logisch om eerst te controleren of emailadres is ingevuld en en zo ja een e-mail te versturen en daarna pas controleren of alle (verplichte) velden wel ingevuld zijn?
Wel netjes dat je bij het ontbreken van verplichte input of foutieve input meldingen geeft, maar dat is na een roundtrip server. Wat je veelal ziet, is clientside form validation (jQuery + jQuery Validation Plugin, bijvoorbeeld). Er wordt niet verzonden, voordat voldaan is aan de requirements zoals je die zelf hebt gedefinieerd (minimale lengte, required, postcodeNL, etc.). Tevens worden meldingen weergegeven in de gewenste taal als iets (nog) niet juist is.

Je zou ook nog iets kunnen doen tegen ongewenst formuliergebruik door bots (captcha) of ander ongewenst gebruik (unique id) als waarborg dat enkel formulieren in behandeling worden genomen, die binnen bepaalde tijdspanne zijn uitgegeven door jouw server.

PS welke values horen bij de respectievelijke geslachten?
In ieder geval de echt grote fouten, waardoor de pagina helemaal niets deed, eruit gehaald. Er zijn zeker nog verbeteringen mogelijk, zoals gezegd, maar hier kun je wel mee verder denk ik.

<?php
if (isset($_POST['emailadres'])) {
    $email_from    = "[email protected]";
    $email_to      = "[email protected]";
    $email_subject = "Contactform";
    $emailadres    = filter_input(INPUT_POST, 'emailadres', FILTER_VALIDATE_EMAIL);
    $naam          = $_POST['naam'];
    $plaats        = $_POST['plaats'];
    $email         = $_POST['email'];
    $geslacht      = $_POST['geslacht'];
    $comment       = $_POST['comment'];
    $html          = true;

    $email_message = nl2br($comment);

    $headers .= "From:" . $email_from . "\r\n";
    $headers .= "To:" . $email_to . "\r\n";
    $headers .= "X-Mailer: PHP/" . phpversion() . "\r\n";
    $headers .= ($html) ? "MIME-Version: 1.0" . "\r\n" : '';
    $headers .= ($html) ? "Content-type:text/html;charset=UTF-8" . "\r\n" : '';

    @mail($email_to, $email_subject, $email_message, $headers);
}

// define variables and set to empty values
$naamErr = $plaatsErr = $emailErr = $geslachtErr = $commentErr = "";
$naam    = $plaats    = $email    = $geslacht    = $comment    = "";

if ("POST" == $_SERVER["REQUEST_METHOD"]) {
    if (empty($_POST["naam"])) {
        $naamErr = "Typ uw naam in";
    } else {
        $naam = test_input($_POST["naam"]);
        // check if name only contains letters and whitespace
        if ( ! preg_match("/^[a-zA-Z ]*$/", $naam)) {
            $naamErr = "Alleen letters en spaties";
        }
    }

    if (empty($_POST["plaats"])) {
        $plaatsErr = "Typ uw woonplaats in";
    } else {
        $plaats = test_input($_POST["plaats"]);
        // check if name only contains letters and whitespace
        if ( ! preg_match("/^[a-zA-Z ]*$/", $plaats)) {
            $plaatsErr = "Alleen letters en spaties";
        }
    }

    if (empty($_POST["email"])) {
        $emailErr = "Typ geldig email adres";
    } else {
        $email = test_input($_POST["email"]);
        // check if e-mail address is well-formed
        if ( ! filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $emailErr = "Ongeldige email";
        }
    }

    if (empty($_POST["geslacht"])) {
        $geslachtErr = "Maak geslachts keuze";
    } else {
        $geslacht = test_input($_POST["geslacht"]);
    }
}

if (empty($_POST["comment"])) {
    $comment = "Typ uw opmerking of vraag";
} else {
    $comment = test_input($_POST["comment"]);
    // check if name only contains letters and whitespace
    if ( ! preg_match("/^[a-zA-Z ]*$/", $plaats)) {
        $plaatsErr = "Alleen letters en spaties";
    }
}

function test_input($data)
{
    $data = trim($data);
    $data = stripslashes($data);
    $data = htmlspecialchars($data);

    return $data;
}

?>

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <form class="form-horizontal" method="post" name="contactform">

        <h6>* Verplichte velden</h6>

        <div class="form-group row">
            <label for="naam" class="col-sm-2 col-form-label">naam*</label>
            <div class="col-sm-2">
                <input class="form-control" type="text" name="naam" id="naam" placeholder="voor en achternaam" required>
                <span class="error"><?php echo $naamErr; ?></span>
            </div>
        </div>

        <div class="form-group row">
            <label for="plaats" class="col-sm-2 col-form-label">Woonplaats*</label>
            <div class="col-sm-2">
                <input class="form-control" type="text" name="plaats" id="plaats" required>
                <span class="error"><?php echo $plaatsErr; ?></span>
            </div>
        </div>

<div class="form-group row">
<label for="email" class="col-sm-2 col-form-label">E-mail*</label>
<div class="col-sm-3">
<input class="form-control" type="email" name="email" placeholder="[email protected]" id="email" required>
<span class="error"><?php echo $emailErr; ?></span>
</div>
</div>

<div class="form-group row">
<label for="geslacht" class="col-sm-2">Geslacht*</label>
<div class="col-sm-2">
<select class="form-control" name="geslacht" id="geslacht">
<option>Man</option>
<option>Vrouw</option>
</select>
<span class="error"><?php echo $geslachtErr; ?></span>
</div>
</div>

<div class="form-group row">
<label for="comment" class="col-sm-2">Opmerking*</label>
<div class="col-sm-5">
<textarea class="form-control" rows="3" name="comment" id="comment"></textarea>
<span class="error"><?php echo $commentErr; ?></span>
</div>
</div>

<div class="form-group row">
<div class="col-sm-2"></div>
<div class="col-sm-2">
<button type="submit" class="btn btn-primary" value="sent">Verzend</button>
</div>
</div>

    </form>
</body>
</html>
Als je het helemaal netjes doet haal je de @ weg, en bouw je foutafhandeling in.
Mocht je mail() functie om vreemde redenen niet werken, dan krijgt de bezoeker netjes een foutmelding.


<?php // kleurtjes tonen
if(mail($email_to, $email_subject, $email_message, $headers)) {
	// Alles is oké! We stturen de gebruiker nu door naar bedankt.php waar een bedankje op vermeld staat.
	header("Location: bedankt.php");
	exit();
} else {
	echo "Er is een technische fout aan onze kant. Gelieve ons een mail te sturen op: ".$email_to;
}
?>
regel 17 lijkt me overbodig: dat wordt in de function mail() al aangegeven..

regel 72: er zijn zat namen waarin andere tekens dan de letters A-Z of een spatie staan:
Willem-Alexander en Máxima: een - voor de koning, en de á van de koningin vallen niet onder jouw filter!
Idem voor de plaatsnaam: 's-Hertogenbosch komt op 2 punten niet door het filter.

de functie test_input()
dat suggereert dat je iets test, maar je verandert daar een invoer. Trim() kan ik nog vatten, maar stripslashes? Dat is iets wat hooguit voorkomt uit de "magic-quotes" settings in PHP. Maar die staat al jaaaren default uit, en kán tegenwoordig niet eens meer aan. Dus je stript hooguit slashes die er wel horen te staan.

en htmlspecialchars() heeft alleen nut in html. Nu pas je dat inderdaad toe op deze mail(), maar als je de setting op regel 12 verandert, veranderen je headers mee, maar htmlspecialchars blijft actief...


En je textarea "comment". Die mag vreemd genoeg alleen letters en spaties bevatten. Geen interpunctie, geen enters, geen cijfers. Vreemd genoeg verwacht je op regel 14 wel dat er enters voor kunnen komen.

NB de accolade op regel 65 zou naar 76 moeten, lijkt me

-------
qua opbouw:
ik zou beginnen met het blok dat op regel 29 begint:
je wilt eerst weten of er fouten zijn.
Zo nee, (dus als alle $xxxErr leeg zijn) ga je de mail sturen
Zo ja, dan toon je het form opnieuw met de melding(en).

Reageren