Secure PHP Contact/Feedback Form

This page explains how to make a simple, secure and accessible PHP Contact/Feedback Form. It follows the usability guidelines for contact/feedback forms — this means that, for example, it sends a confirmation e-mail to the visitor. For security it also validates the user’s input to prevent attempts to crack the form and use it for spamming purposes.

The code

The code below implements the simple secure PHP Contact/Feedback Form. Note that the regular expression used to validate the e-mail address does not match some bizarre yet technically valid e-mail address such as " "@example.com — addresses of this form are exceedingly rare, and many e-mail clients do not support them anyway.

<style type="text/css">
  .label{
    text-align:right;
  }
  #submit{
    text-align:center;
  }
</style>
<?php
  $to='example@example.com';
  $messageSubject='Message subject';
  $confirmationSubject='Confirmation message subject';
  $confirmationBody="Confirmation message body";
  $email='';
  $body='';
  $displayForm=true;
  if ($_POST){
    $email=stripslashes($_POST['email']);
    $body=stripslashes($_POST['body']);
    // validate e-mail address
    $valid=eregi('^([0-9a-z]+[-._+&])*[0-9a-z]+@([-0-9a-z]+[.])+[a-z]{2,6}$',$email);
    $crack=eregi("(\r|\n)(to:|from:|cc:|bcc:)",$body);
    if ($email && $body && $valid && !$crack){
      if (mail($to,$messageSubject,$body,'From: '.$email."\r\n")
          && mail($email,$confirmationSubject,$confirmationBody.$body,'From: '.$to."\r\n")){
        $displayForm=false;
?>
<p>
  Your message was successfully sent.
  In addition, a confirmation copy was sent to your e-mail address.
  Your message is shown below.
</p>
<?php
        echo '<p>'.htmlspecialchars($body).'</p>';
      }else{ // the messages could not be sent
?>
<p>
  Something went wrong when the server tried to send your message.
  This is usually due to a server error, and is probably not your fault.
  We apologise for any inconvenience caused.
</p>
<?php
      }
    }else if ($crack){ // cracking attempt
?>
<p><strong>
  Your message contained e-mail headers within the message body.
  This seems to be a cracking attempt and the message has not been sent.
</strong></p>
<?php
    }else{ // form not complete
?>
<p><strong>
  Your message could not be sent.
  You must include both a valid e-mail address and a message.
</strong></p>
<?php
    }
  }
  if ($displayForm){
?>
<form action="URL" method="post">
  <table>
    <tr>
      <td class="label"><label for="email">Your e-mail address</label></td>
      <td>
        <input type="text" name="email" id="email" value="<?php echo htmlspecialchars($email); ?>" size="30">
        (a confirmation e-mail will be sent to this address)
      </td>
    </tr>
    <tr>
      <td class="label"><label for="body">Your message</label></td>
      <td><textarea name="body" id="body" cols="70" rows="5">
        <?php echo htmlspecialchars($body); ?>
      </textarea></td>
    </tr>
    <tr><td id="submit" colspan="2"><button type="submit">Send message</button></td></tr>
  </table>
</form>
<?php
  }
?>

How to use it

Copy the code above and paste it into your contact/feedback form page. Then change the following lines:

$to='example@example.com';
The e-mail address in this line should be changed to your address.
$messageSubject='Message subject';
This subject line will appear on messages sent to you using this form, allowing them to be easily filtered. Do not use newlines in this string, as a bug in the implementation of the mail function will then allow an attacker to insert arbitrary mail headers.
$confirmationSubject='Confirmation message subject';
This subject line will appear on the confirmation e-mail sent to the visitor. Do not use newlines in this string, as a bug in the implementation of the mail function will then allow an attacker to insert arbitrary mail headers.
$confirmationBody="Confirmation message body";
This message will be sent in the confirmation e-mail to the visitor, followed by their message body. This string is enclosed in double-quotes, so you can use \r\n to start a new line.
<form action="URL" method="post">
The URL in this line should be changed to the URL of the page containing the contact form — this may be a relative URL (that is, just the name of the page itself — for example “contact.php”). If the URL ends with a slash (like those on Safalra’s Website) then “./” should be used.

You can also change the HTML success and error messages.

For more ready-to-use examples of this kind, try O’Reilly & Associates’ excellent PHP Cookbook: