July 27, 2009

Web Design From Scratch’s Anti-Spam Method

I just wrote a post about how to make sure that someone using your contact form is human, which utilized a validation image. While this is effective, it requires the user to spend an annoying 10 seconds deciphering the text and typing it in. Web Design From Scratch has a very clever solution.

The trick is to use javascript to make sure that the user is interacting with the form, by waiting for the user to focus or click on the form itself. Once it sees that the form has been interacted with in a human-like way, it sets a flag in a hidden input field. If the person browsing is not using javascript, then a <noscript> tag is used to show a normal CAPTCHA form which is checked by PHP only if the other input flag returned false.

Sure, there are other ways (the “hidden” empty input field) that work just fine, but this is certainly a clever way of going about it. It exploits a real difference between spambot and human.

June 29, 2009

Making a Secure Contact Form with PHP and jQuery

Its always nice when a site gives you an opportunity to contact the webmaster. You should always make sure, when you are building a website, to give your users opportunity to do this. One way to go about doing this is just giving out your email address. Unfortunately, putting your email address up on your site makes it easy form spam bots to find it and start sending you all sorts of emails. The best way is to make a contact form.


To follow this tutorial, you’ll need the jQuery Library.


Let’s start out web 1.0, with just a simple form with a submit button. You’ll want a simple HTML form that looks like this:


Contact Me

Email:


So now that we have a form, we’ll need a PHP page to process that form. What we’ll do is take the message, put it into an email and email it to you (you’ll need to put your email, or whatever email you want to receive contact requests). Put this code into a ‘contact.php’ file:



if (!empty($_POST['contact_text']) && !empty($_POST['contact_email'])) {
$to = 'webmaster@example.com';
$subject = 'Contact Request from '.$_POST['contact_email'];
$message = $_POST['contact_text'];
$headers = 'From: '.$_POST['contact_email']." \r\n" .
'Reply-To: '.$_POST['contact_email']."\r\n" .
'X-Mailer: PHP/' . phpversion();
mail($to, $subject, $message, $headers);
echo "Thanks for contacting me!";
} else {
echo "Please enter your email and a message.";
}
?>


Basically, that code checks to make sure that both $_POST['contact_email'] and $_POST['contact_text'] are defined, and then it constructs an email to you (webmaster@example.com). In the message is the text that they entered. Then it prints a friendly message.


The only problem with what we have so far is that the contact form is very vulnerable to automatic spam. Not quite as bad as putting your email out there, but it is still pretty easy for spammers to just send a request to your ‘contact.php’ page and bombard you with emails. There is a way to prevent this from happening. It involves using PHP’s $_SESSION superglobal to make sure that the contact-er is using your contact form, and not just a single request to contact.php. You need to add a little PHP code to your contact form to make this work. Because we are going to use the session superglobal, we need to set up the session at the top of your pages. In both the page holding the form AND contact.php, put this code at the top:




Now, what we’re going to do is make a random string (an md5 hash of a random number between 1 and 10000), and put it into the form as a ‘hidden’ input field. We also store the hash in a session variable, so we can compare the two in contact.php. Here’s what your form should look like now.

Contact Me

Email:

$randhash = md5(rand(0,10000));
$_SESSION['contact_key'] = $randhash;
?>


(Notice the PHP lines and the new ‘input’ tag).

And now in contact.php, we need to make sure that the two keys are the same. This is what contact.php should look like:


session_start();
if (isset($_POST['contact_key'])) {
if ($_POST['contact_key'] == $_SESSION['contact_key']) {
if (!empty($_POST['contact_text']) && !empty($_POST['contact_email'])) {
$to = 'webmaster@example.com';
$subject = 'Contact Request from '.$_POST['contact_email'];
$message = $_POST['contact_text'];
$headers = 'From: '.$_POST['contact_email']." \r\n" .
'Reply-To: '.$_POST['contact_email']."\r\n" .
'X-Mailer: PHP/' . phpversion();
mail($to, $subject, $message, $headers);
echo "Thanks for contacting me!";
} else {
echo "Please enter your email and a message.";
}
}
}
?>


Great! Now we have a functioning contact form. The only problem is, when people use the form, they are sent to a boring page with only text in it. So let’s make the form asynchronous with javascript. jQuery javascript, actually. The script will wait for the form submit button to be pushed, and then will use AJAX to send a request to contact.php, thus sending the contact request. When that finishes, it will append the response text to the form to give the contact-er a result (good if all fields were filled in, bad if they forgot their email or a message). All you need to do is put a little bit of code into your page with the form.

contactform = $('form#contact');
contactform.submit(function() {
$.post('/contact.php', $(this).serialize(), function(data) {
$('form#contact').append("
"+data);
});
return false;
});

So there we go. Somebody can, with javascript enabled, just press the send button and send the contact request to your email asynchronously, without your putting your email out to be picked up by spam bots. The best thing about this is that when somebody isn’t running javascript in their browser, they will still be able to use the form effectively.

Obviously you’d want to style up your form and maybe change around the ’submit’ event to make it a little more stylish, but we have here a solid, secure AJAX-PHP contact form which will help make your site more user-friendly and accessible.

UPDATE: If you want to make sure that your form is validated, check out this tutorial.