Posted on: November 10, 2017Updated: November 24, 2017
Simple contact form with Captcha using PHP
Previously, we have looked into how to make a captcha image using PHP and now we are going to use it to make a simple but efficient, spam free, contact form. Once again, we will rely on PHP sessions to compare values of the generated captcha and input provided by a user. Other required conditions will be created in order to complete the form and send an email to the desired email address. The first part of the tutorial will contain the conditions and variables needed to assemble and process the email, as well as HTML form structure. In the second part we will review the captcha code where a session will be included.
PART 1 - Create contact form
First thing to do is the functionality itself, how the form will respond when the send button is clicked on. Only after comes the HTML form structure.
<?php
// Session is started, if you are running PHP older than 5.4, uncomment the header modification for security reasons
session_start() ;
//header('Content-Type: text/html; charset=utf-8');
// When button send is clicked on, execute bellow...
if (isset ($_POST['send' ])) {
// Handle name post input, create error variable if it's empty
if (empty ($_POST['name' ])) {$nameerror = '<span style="color:red;">Name field is empty!</span>' ;}
// Handle email post input, create error for empty or if it doesn't match certain structure or use specific chars
if (empty ($_POST['email' ])) {$mailerror = '<span style="color:red;">Email field is empty!</span>' ;}
elseif (! preg_match("/^[_a-z0-9]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/i" , $_POST['email' ])) {$mailerror = '<span style="color:red;">The Email address is not valid!</span>' ;}
// Handle message post input
if (empty ($_POST['message' ])) {$messageerror = '<span style="color:red;">Message field is empty!</span>' ;}
// Handle Captcha post input, if the hashed captcha input doesn't match session(also hashed, relevant to PART 2) created when captcha is called, create error
if (hash('sha256' , $_POST['verify' ]) !== $_SESSION['code' ]) {$codeerror = '<span style="color:red;">The verification code does not match!</span>' ;}
else {
// Else create variables from input. Just in case, we will encode all applicable chars to prevent potential XSS injection when mail is delivered, if read in HTML form
// Email variable, however, was already checked above with preg_match function
$name = htmlentities($_POST['name' ]);
$subject = htmlentities($_POST['subject' ]);
$email = $_POST['email' ];
$message = htmlentities($_POST['message' ]);
}
// This could be included in the above else condition but just to be sure that nothing gets passed by chance, doublecheck for empty errors
// If there are none generated, then proceed and create an email and send it to the desired email address
if (empty ($nameerror ) && empty ($mailerror ) && empty ($messageerror ) && empty ($codeerror )) {
$sent = '<p><span sytle="color:green;">Thank you! Your message has been sent!</span></p>' ;
$from = 'From: ' .$email ;
$to = '[email protected]' ;
$content = $name . ' has made an inquiry: \n\n' .$message ;
mail($to , $subject , $content , $from );
}
// Create error variable when a condition is not met
else {$notsent = '<p><span sytle="color:red;">Your message was NOT sent because of the following error/s below!</span></p>' ;}
}
?>
So now that the functionality of the form is defined, all that is needed is the HTML structure, where we will also display the PHP error variables and include captcha image. Also note that it has been decided against handling the length of the each post input in PHP with strlen() function. Instead we will do that in HTML form but you can easily modify the script if you prefer it that way.
<-- Display sent or not sent notification -->
<?php echo $sent .$notsent ;?>
<span> * Required fields</span>
<form action="" method="post" >
<-- Name label and input type with the limit of 50 chars. Value will be saved, if posted(also stripped of any and if empty, error displayed below the input form -->
<label> * Enter your Name:</label><br/>
<input type="text" name="name" size="30" maxlength="50" value=" <?php if ($_POST['name' ]) {echo htmlentities($_POST['name' ]);} ?> " /><br/>
<?php if (!empty ($nameerror )) {echo $nameerror ."<br/>" ;} ?>
<-- Email label and input type with the limit of 50 chars. Value will be saved, if posted and if empty, error displayed below the input form -->
<label> * E-mail address:</label><br/>
<input type="text" name="email" size="30" maxlength="50" value=" <?php if ($_POST['email' ]) {echo htmlentities($_POST['email' ]);} ?> " /><br/>
<?php if (!empty ($emailerror )) {echo $emailerror ."<br/>" ;} ?>
<-- Subject label and input type with the limit of 50 chars. Value will be saved, if posted. There is no error since this is not a required field -->
<label> Message subject:</label><br/>
<input type="text" name="subject" size="30" maxlength="50" value=" <?php if ($_POST['subject' ]) {echo htmlentities($_POST['subject' ]);} ?> " /><br/>
<-- Message label and textarea type with the limit of 500 chars. Textarea input will be saved, if posted and if empty, error displayed below the input form-->
<label> * Enter your message:</label><br/>
<textarea id="textos" name="message" rows="15" cols="70" maxlength="500" > <?php if (isset ($_POST['message' ]) {echo htmlentities($_POST['message ']);} ?> </textarea><br/>
<label> (Limit: 500 characters)</label><br/>
<?php if (!empty ($messageerror )) {echo $messageerror ."<br/>" ;} ?>
<-- Include captcha from the file captcha.php as image and optionally set maxlength in input to match the one from the captcha file -->
<-- Note that the captcha file is called from the root folder. You may have to change that to suit your needs -->
<p> * Please enter the verification code below:</p>
<img src="/captcha.php" > <input type="text" name="verify" maxlength="6" ><br/>
<?php if (!empty ($codeerror )) {echo $codeerror ."<br/>" ;} ?>
<-- Create button with name send which is the trigger for PHP code execution -->
<button type="submit" name="send" value="Send" ><br/><br/>
</form>
PART 2 - Review the captcha file
While the above code is already fully functional, we still need to start a session in the captcha file and save the code generated inside it or else no one will be able to pass the code test condition(PART 1) and send an email.
<?php
// Start a session to create a different session to the one of contact form file
session_start() ;
$charpool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' ;
$codelen = 6 ;
$code = '' ;
for ($x = 0 ; $x < $codelen ; $x ++ ) {$code .= $charpool [rand(0 , strlen($charpool ) - 1 )];}
// Now that code is generated, save it(hashed) into the session to be compared against the verification input
$_SESSION['code' ] = hash('sha256' , $code );
header("Content-type: image/png" );
$image = imagecreatefrompng('images/cap.png' );
$textcolor = imagecolorallocate($image , 255 , 255 , 255 );
$font = './fonts/tahoma.ttf' ;
imagettftext($image , 15 , 3 , 16 , 29 , $textcolor , $font , $code );
imagepng($image );
imagedestroy($image );
That's it, the contact form with captcha should now be fully operational. Alternatively, the script can be downloaded here.