Most anti-spam methods used by websites today are annoying at best. They use impossible-to-read captcha images, or they make users jump through some kind of hoop to get the email address instead of just clicking on it. This can mean lost sales and opportunities for you, because each hurdle turns away more users.
This article looks at how to use some simple HTML, CSS, & Javascript to protect your private information without making your guests jump through hoops.
Download a working copy of the contact form discussed here.
The Goal
I want users to be able to contact me simple and easy, no captchas, no math problems, just a regular contact form, clickable email address, and everything copy-paste-able.
The Problem
Spammers love captcha-free forms and clickable email addresses. I do not want to receive a ton of spam!
The Solution
With a little bit of CSS and JavaScript wizardry, we can make a simple, easy-to-use contact page that will block almost all automated contact form spam.
Part 1: The Contact Form
We are going to make a standard contact form with one extra feature: an input named “url” and a note beside it that says “Don’t type anything here!”
The HTML:
<form action="/submit.php" method="post">
<p>Your name: <input type="text" name="name" /></p>
<p>Your email: <input type="text" name="email" /></p>
<p class="antispam">Leave this empty: <input type="text" name="url" /></p>
<p><textarea name="message"></textarea></p>
<p><input type="submit" value="Send" /></p>
</form>
Then we use CSS to hide the input and the note.
The CSS:
.antispam { display:none;}
Then we make a rule in the server that says ‘if the user typed anything in the “url” box, then throw it out.’
The PHP:
<?php
// if the url field is empty
if(isset($_POST['url']) && $_POST['url'] == ''){
// then send the form to your email
mail( 'you@yoursite.com', 'Contact Form', print_r($_POST,true) );
}
// otherwise, let the spammer think that they got their message through
?>
<h1>Thanks</h1>
We'll get back to you as soon as possible
A regular person won’t even see the box normally, and will therefore leave it blank without even thinking about it. If the CSS fails to load, they get a note explaining what to do.
However, when a spam bot looks at this, it sees a good spot to stick whatever spammy url they’re trying to advertise.
Now the php script on the server can tell who is a spammer and who isn’t. The regular people get sent to your email, the spammers get ignored!
Part 2: Click-able Email Address
Spammers steal your email address by scanning through the source code of the site and grabbing anything that looks like an email address. So we’re going to make sure that there is no email address in the source code and instead generate it by JavaScript.
The Javascript:
var first = "yourname";
var last = "yoursite.com";
The HTML:
My e-mail address:
<script type="text/javascript">
document.write('<a href="mailto:'+first + '@' + last+'">'+first + '@' + last+'<\/a>');
</script>
<noscript>
Please enable javascript or use my <a href="/contact.php">contact form</a>
</noscript>
A regular user will see a regular email address and things just work. A user who happens to have javascript disabled will see an explanation and an alternative solution. And a spammer won’t see a thing!
This method can easily be extended to phone numbers and other personal information.
Advanced version: Prettier message body and a proper From:
field
These were the most commonly requested features, so I added an advanced version that changes the From:
field of the email to whatever the user typed in the box, and removes all of the Array
brackets from the body of the message:
<?php
// if the url field is empty
if(isset($_POST['url']) && $_POST['url'] == ''){
// put your email address here
$youremail = 'you@yoursite.com';
// prepare a "pretty" version of the message
$body = "This is the form that was just submitted:
Name: $_POST[name]
E-Mail: $_POST[email]
Message: $_POST[message]";
// Use the submitters email if they supplied one
// (and it isn't trying to hack your form).
// Otherwise send from your email address.
if( $_POST['email'] && !preg_match( "/[\r\n]/", $_POST['email']) ) {
$headers = "From: $_POST[email]";
} else {
$headers = "From: $youremail";
}
// finally, send the message
mail($youremail, 'Contact Form', $body, $headers ); } // otherwise, let the spammer think that they got their message through ?>
The preg_match()
is there to make sure spammers can’t abuse your server by injecting extra fields (such as CC and BCC) into the header. Take a look at http://www.thesitewizard.com/php/protect-script-from-email-injection.shtml for more info.
Advanced version 2: Don't send blank emails
<?php
// if the url field is empty
if(isset($_POST['url']) && $_POST['url'] == ''){
if($_POST["message"] == "" || $_POST["name"] == ""){
echo "<p>Please press the back button and fill in all fields</p>";
} else {
// then send the form to your email
mail( 'you@yoursite.com', 'Contact Form', print_r($_POST,true) );
}
}
// otherwise, let the spammer think that they got their message through
?>
<h1>Thanks</h1>
<p>We'll get back to you as soon as possible</p>
Advanced version 3: Redirect to a new page
<?php
// if the url field is empty
if(isset($_POST['url']) && $_POST['url'] == ''){
// then send the form to your email
mail( 'you@yoursite.com', 'Contact Form', print_r($_POST,true) );
}
// otherwise, let the spammer think that they got their message through
header('Location: http://www.mysite.com/thankyou.html');
exit('Redirecting you to http://www.mysite.com/thankyou.html');
?>
Complete Examples
A complete working copy of the code is available to browse on Github and you can also download a .zip file of the code
For a live demo, see http://spam-free-contact-example.herokuapp.com/simple/contact.htm
WordPress version
I found that there is an anti-spam plugin for WordPress that uses similar methods to the ones I describe here: http://wordpress.org/extend/plugins/nospamnx/ – I installed it on this blog and it’s stopped nearly 30,000 spam comments so far.
Need help?
I can help you get set up and/or connect you to other competent developers.
A typical installation would be around $500 for me to perform it, but you can likely find a lower-cost option by posting a job on elance.
(Link to this page in the job description and then search for developers with php
and email
skills and invite them to submit a bid.)
About the Author
Nathan is an experienced Web Developer with a sharp eye for security and a zeal for User Experience. He currently works primarily on JavaScript and Node.js.
However, the focus has never been on the technology – it's about solving problems and meeting needs. “Computers work for us, not the other way around.”