The problem with my basic PHP Mail Form tutorial is that it offers no protection from spam and meta tag injection. This is fine if you have a very low-traffic site not listed at major search engines, or have a private website, but bigger sites need more.
Let's take a look at the basic code we've got so far. Notice there's no validation of any of the submitted data which means a visitor could send anything via the form:
|
<?php
$name = $_POST['name']; $email = $_POST['email']; $url = $_POST['url']; $comments = $_POST['comments']; $recipient = "youremail@url.com"; $subject = "personal website submission form"; $message = "Name: $name n"; $message .= "E-mail: $email n"; $message .= "URL: $url n"; $message .= "Comments: $comments nn"; $headers = "From: My Form n"; $headers .= "Reply-To: $email"; mail($recipient,$subject,$message,$headers); ?> |
First things first, we need to add at the top of the page, above all of the current code, a spot of PHP which prevents users/bots loading the process page directly and can help get rid of some automated spam:
|
if (!isset($_POST['submit'])) {
echo "<h1>Error</h1>n <p>Accessing this page directly is not allowed.</p>"; exit; } |
Note: exit; stops the page from being processed further.
Our first step is to process the submitted data and to get rid of any HTML "nasties" and special characters that might have been submitted via our form. The quickest way to do this is to create a function that'll clear up our data for us. The following function, called cleanUp trims whitespace, strips HTML tags and converts left over "special" characters to their proper entities:
|
function cleanUp($data) {
$data = trim(strip_tags(htmlspecialchars($data))); return $data; } |
We'll add this to the top of our processing code, and apply the function to submitted data:
|
function cleanUp($data) {
$data = trim(strip_tags(htmlspecialchars($data))); return $data; } $name = cleanUp($_POST['name']); $email = cleanUp($_POST['email']); $url = cleanUp($_POST['url']); $comments = cleanUp($_POST['comments']); |
Now, we need to check for empty fields. There's a handy dandy empty() function built into PHP which, when combined with an if statement, will do this for us:
|
if ((empty($name)) || (empty($email)) || (empty($comments))) {
echo "<h2>Input Error</h2>n <p><strong>Name</strong>, <strong>e-mail</strong> and <strong>comments</strong> are required fields. Please fill them in and try again:</p>"; echo "<form action="process.php" method="post"><p>"; echo "<input type="text" name="name" id="name" value="$name" /> Name<br />"; echo "<input type="text" name="email" id="email" value="$email" /> E-mail<br />"; echo "<input type="text" name="url" id="url" value="$url" /> Site URL<br />"; echo "<textarea name="comments" id="comments">$comments</textarea> Comments<br />"; echo "<input type="submit" name="submit" id="submit" value="Send" />"; echo "</p></form>"; exit; } |
The code above gives the user access to the form again, as well as their originally submitted data. This allows them to edit the field with the problem without losing any important messages/etc. Much less frustrating for everyone!
|
if (!ereg("^[_a-zA-Z0-9-]+(.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(.[a-zA-Z0-9-]+)*$",$email)) {
echo "<h2>Input Error</h2>n <p>The e-mail address "$email" isn't valid. Please edit it and try again:</p>"; echo "<form action="process.php" method="post"><p>"; echo "<input type="text" name="name" id="name" value="$name" /> Name<br />"; echo "<input type="text" name="email" id="email" value="$email" /> E-mail<br />"; echo "<input type="text" name="url" id="url" value="$url" /> Site URL<br />"; echo "<textarea name="comments" id="comments">$comments</textarea> Comments<br />"; echo "<input type="submit" name="submit" id="submit" value="Send" />"; echo "</p></form>"; exit; } |
Our final step involves stripping new lines and carriage returns from the $email variable and blocking instances of "Content-Type"; a step in the right direction to combatting meta/header injection:
|
$email = preg_replace("([rn])", "", $email);
$find = "/(content-type|bcc:|cc:)/i"; if (preg_match($find, $name) || preg_match($find, $email) || preg_match($find, $url) || preg_match($find, $comments)) { <p>No meta/header injections, please.</p>"; exit; } |
Combine these together with the PHP that sends the e-mail and we have a new and more secure process.php that works perfectly with the form HTML from the original tutorial:
|
<?php
if (!isset($_POST['submit'])) { echo "<h1>Error</h1>n <p>Accessing this page directly is not allowed.</p>"; exit; } function cleanUp($data) { $data = trim(strip_tags(htmlspecialchars($data))); return $data; } $name = cleanUp($_POST['name']); $email = cleanUp($_POST['email']); $url = cleanUp($_POST['url']); $comments = cleanUp($_POST['comments']); if ((empty($name)) || (empty($email)) || (empty($comments))) { echo "<h2>Input Error</h2>n <p><strong>Name</strong>, <strong>e-mail</strong> and <strong>comments</strong> are required fields. Please fill them in and try again:</p>"; echo "<form action="process.php" method="post"><p>"; echo "<input type="text" name="name" id="name" value="$name" /> Name<br />"; echo "<input type="text" name="email" id="email" value="$email" /> E-mail<br />"; echo "<input type="text" name="url" id="url" value="$url" /> Site URL<br />"; echo "<textarea name="comments" id="comments">$comments</textarea> Comments<br />"; echo "<input type="submit" name="submit" id="submit" value="Send" />"; echo "</p></form>"; exit; } if (!ereg("^[_a-zA-Z0-9-]+(.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(.[a-zA-Z0-9-]+)*$",$email)) { echo "<h2>Input Error</h2>n <p>The e-mail address "$email" isn't valid. Please edit it and try again:</p>"; echo "<form action="process.php" method="post"><p>"; echo "<input type="text" name="name" id="name" value="$name" /> Name<br />"; echo "<input type="text" name="email" id="email" value="$email" /> E-mail<br />"; echo "<input type="text" name="url" id="url" value="$url" /> Site URL<br />"; echo "<textarea name="comments" id="comments">$comments</textarea> Comments<br />"; echo "<input type="submit" name="submit" id="submit" value="Send" />"; echo "</p></form>"; exit; } $email = preg_replace("([rn])", "", $email); $find = "/(content-type|bcc:|cc:)/i"; if (preg_match($find, $name) || preg_match($find, $email) || preg_match($find, $url) || preg_match($find, $comments)) { echo "<h1>Error</h1>n <p>No meta/header injections, please.</p>"; exit; } $recipient = "youremail@url.com"; $subject = "personal website submission form"; $message = "Name: $name n"; $message .= "E-mail: $email n"; $message .= "URL: $url n"; $message .= "Comments: $comments"; $headers = "From: My Form rn"; $headers .= "Reply-To: $email"; if (mail($recipient,$subject,$message,$headers)) { echo "<p>Mail sent successfully.</p>"; } else { echo "<p>Mail not sent this time.</p>"; } ?> |












