The internet is by far an evil place. Spam bots crawled my website even before Google did and I received my first spam message just before I finished securing my contact form. This tutorial will help you to avoid 99.9% of spam coming your way. The main parts of this tutorial include:
Warning! This entire tutorial comes with an overall exclusion of liability!
I'm running my own small webserver on a Raspberry Pi over my home broadband connection. (Read everything about my experience with the RaspberryPi as webserver here.) This means I have to setup PHP to relay emails over Google's free SMTPserver. This is by far the simplest solution.
pacman -S php-pear
pear install Mail pear install Net_SMTP
include('Mail.php'); $smtp = Mail::factory('smtp', array ('host' => 'ssl://smtp.gmail.com', 'port' => '465', 'auth' => true, 'username' => '<your_login>@gmail.com', 'password' => '<your_pwd>')); $mail = $smtp->send(<recipients>, <headers>, <email_content>); if (PEAR::isError($mail)) die($mail->getMessage());I highly recommend you to create an application password for your Google account. In case it gets compromised you can simply cancel it and you remain your access and security of your Google account.
internal
directive.There are different levels of protection against SPAM. There are simple measures which don't effect the usability of your contact form and then there are more secure precautions which mean also mean extra hurdles for legitimate users. You have to trade off security against usability as it seems reasonable for your application. First, the simple but essential steps which will already sort most of your spam problems and don't even bother your visitors:
<input name="p1" placeholder="Your Name" type="text" > <input name="p2" placeholder="Your email address" type="text" >This sorts out the simple spam bots which try the most common POST strings against your contact form. It also prevents spam bots from guessing where the email address etc. goes in your form.
<input name="p3" type="hidden" value="sometext" >And in the php script processing the form you check whether the hidden value was set:
if (!isset($_POST["p3"]) || $_POST["p3"] != "sometext") { header("Location: contact_form.html"); exit; }When the check fails it sends the user to the contact form instead. Replace the location with the name of the website which holds the contact form.
if ("POST" != getenv("REQUEST_METHOD")) { header("Location: contact_form.html"); exit; }
if ("" == getenv("HTTP_USER_AGENT") || "" == getenv("HTTP_REFERER")) { header("Location: contact_form.html"); exit; }
$email = $_POST["p2"]; if (!preg_match("/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/", $email)) exit;
<input name="email" style="display:none;" type="text">And check whether a spam bot took the bait in your php script processing your contact form:
if (!empty($_POST["email"])) exit;
The best way to get rid of spam bots is to use a CAPTCHA. Unfortunately, this adds an extra annoyance for your visitors. But the internet is full of them so that they are widely tolerated. There are professional CAPTCHA solutions which especially try to address the problem of barrier-free access. This script is perfect if you look for a simple solution for a smaller homepage.
captcha.php
with the following code to create your CAPTCHA image:
<?php session_start(); $string = ''; for ($i = 0; $i < 5; $i++) { $string .= chr(rand(97, 122)); } $_SESSION['captcha'] = $string; $image = imagecreatetruecolor(180, 60); $black = imagecolorallocate($image, 0, 0, 0); $white = imagecolorallocate($image, 255, 255, 255); imagefilledrectangle($image,0,0,180,60,$white); imagettftext ($image, 35, 0, 10, 45, $black, "font/zxx_noise.ttf", $_SESSION['captcha']); header("Content-type: image/png"); imagepng($image); ?>This small script creates a CAPTCHA of 5 random letters. To foul text recognition I use the ZXX font. You can download it from http://z-x-x.org/. Use one of the free websites to convert the font file into a TrueType Font (.ttf) like www.freefontconverter.com and place the .ttf file in a folder called font on your webserver.
<img class="img-responsive" src="captcha.php" /> <input name="captcha" placeholder="Type the 5 letters from the image" type="text" />and to your php script processing the form you add
session_start(); if ($_POST['captcha'] != $_SESSION['captcha']) exit;That's already all!
Important! All code comes with an overall exclusion of liability! Please don't just copy and paste code. Please read what the different bits are doing and change the scripts to your own needs. Most importantly, you have to secure the submission script from external access as it will hold your Google password! The simple measures taken in the script itself won't guaranty full protection. You have to secure the scripts on the webserver level, too.
Firstly, the form itself:
<form action="submission.php" class="well span7" method="POST"> <div class="row"> <div class="span3"> <label>Name</label> <input class="span3" name="p1" placeholder="Your Name" type="text" /> <label>Email Address</label> <input class="span3" name="p2" placeholder="Your email address" type="text" /> <img class="img-responsive" src="captcha.php" /> <label>CAPTCHA</label> <input class="span3" name="p3" placeholder="Type the 5 letters from the image" type="text" /> </div> <div class="span4"> <label>Message</label> <textarea class="input-xlarge span4" id="message" name="p4" rows="10"></textarea> </div> <input name="email" style="display:none;" type="text" /> <input name="p5" type="hidden" value="contact" /> <button class="btn btn-primary pull-right" type="submit">Send</button> </div> </form>
Secondly, the captcha script captcha.php
:
<?php session_start(); $string = ''; for ($i = 0; $i < 5; $i++) { $string .= chr(rand(97, 122)); } $_SESSION['captcha'] = $string; $image = imagecreatetruecolor(180, 60); $black = imagecolorallocate($image, 0, 0, 0); $white = imagecolorallocate($image, 255, 255, 255); imagefilledrectangle($image,0,0,180,60,$white); imagettftext ($image, 35, 0, 10, 45, $black, "font/zxx_noise.ttf", $_SESSION['captcha']); header("Content-type: image/png"); imagepng($image); ?>
Last but not least, the processing script submission.php
<?php session_start(); include('Mail.php'); if (!isset($_POST["p5"]) || $_POST["p5"] != "contact" || "POST" != getenv("REQUEST_METHOD")) { header("Location: /contact"); exit; } if (!empty($_POST["email"])) { header("Location: contact"); exit; } if ("" == getenv("HTTP_USER_AGENT") || "" == getenv("HTTP_REFERER")) { header("Location: /contact"); exit; } $name = $_POST["p1"]; $email_address = $_POST["p2"]; $message = $_POST["p4"]; if ($_POST['p3'] != $_SESSION['captcha']) $error = "Please type the 5 letters from the image!"; elseif (empty ($name)) $error = "You must enter your name."; elseif (empty ($email_address)) $error = "You must enter your email address."; elseif (!preg_match("/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/", $email_address)) $error = "You must enter a valid email address."; elseif (empty ($message)) $error = "You must enter a message."; elseif (preg_match("/http/i", $message) ) $error = "No URLs in the message allowed for SPAM prevention!"; elseif (preg_match("/http/i", $name) ) $error = "No URLs as Name allowed for SPAM prevention!"; if (isset($error)) { header("Location: /contact?e=".urlencode($error)); exit; } $email_content = "Name: $name \n"; $email_content .= "Email Address: $email_address\n"; $email_content .= "Message:\n\n$message"; $recipients = '#####'; $headers['From'] = $email_address; $headers['To'] = '#####'; $headers['Subject'] = '#####'; $smtp = Mail::factory('smtp', array ('host' => 'ssl://smtp.gmail.com', 'port' => '465', 'auth' => true, 'username' => '#####', 'password' => '#####')); $mail = $smtp->send($recipients, $headers, $email_content); if (PEAR::isError($mail)) die($mail->getMessage()); header("Location: /contact"); exit; ?>