Skip to content
View in the app

A better way to browse. Learn more.

Web Designer Forum

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

reCAPTCHA not easy to implement, any other solutions?

Featured Replies

Has anyone successfully installed reCAPTCHA on to their contact page to help stop the spam? 

According to the reCAPTCHA website at https://developers.google.com/recaptcha/ its 'easy to add, advanced security'. 
I have been trying to use V2 with the checkbox option, it is clearly shown what you need to do to call up reCAPTCHA, but come to the code that is needed within a php form it is lacking easy to understand instructions. 

After spending a day trying to get reCAPTCHA to work, I have given-up. 

What are the other ways of stopping spam without putting someone off from using a simple contact form? Is there something simple to be added? 

  • Author

Thanks, I have a look into  the 'honeypot' solution to see what that is all about.

I use a honeypot (but wasn't fully confident of it) and the spawn suggestion from @BrowserBugs (which I was). I also check for "a href=" because my customers shouldn't need to include a link in the contact form. That combo currently works for me.

I'm currently trapping the spam into a specific mailbox along with the host IP so I can review it. The spam to arrive first and in greatest volume appears to all come from IPs in St Petersburg :-)

  • Author

I have tried to add honeypot and spawn features to my contact form, but with no luck.

I have stripped all code that I couldn't get working, this is what I now have.

contact.html

<form action="sendeail.php" method="post">
    <div class="to">
        <input class="text" name="name" onblur="if (this.value == '') {this.value = 'Name';}" onfocus="this.value = '';" required="" type="text" value="Name" />
        <input class="to-right text" name="email" onblur="if (this.value == '') {this.value = 'Email';}" onfocus="this.value = '';" required="" type="text" value="Email" />
    </div>
    <select name="enquirytype">
        <option value="General Enquiry">General Enquiry</option>
        <option value="Error on Website">Error on Website</option>
    </select>
    <textarea class="text" name="enquiry" onblur="if (this.value == '') {this.value = 'Message';}" onfocus="this.value = '';" value="Message:">Message</textarea>
    <input name="sent" type="hidden" value="
        <?php echo date('Y-m-d H:i:s'); ?>">
        <input class="mybutton" name="submit" type="submit" value="Submit" />
</form>


 

sendeail.php

<?php
    $name = $_POST['name'];
    $email = $_POST['email'];
    $enquirytype = $_POST['enquirytype'];
    $enquiry = $_POST['enquiry'];

    if(!$email == "" && (!strstr($email,"@") || !strstr($email,".")))
    {
        echo "
<h2>Please enter valid Email address</h2>\n";
    $badinput = "
<h2>Form was NOT submitted</h2>\n";
        echo $badinput;
    die ("Go back! ! ");
    }

    if(empty($name) || empty($email)) {
        echo "
<h2>Please fill in Name and Email Address</h2>\n";
    die ("Use back! ! ");
    }

    $todayis = gmdate("l, j F Y, g:i a ") ;
    $subject = "Enquiry";
    $notes = stripcslashes($notes);
    $message = " $todayis \n

    From: $name \n
    Email: $email \n
    Type of Enquiry: $enquirytype \n
    Enquiry: $enquiry \n
    ";

    $from = "From: $email\r\n";

    mail("joe.bloggs@somewhere.co.uk", $subject, $message, $from);
?>
<p class="contact-conformation">Date: 
    <?php echo $todayis ?>
</p>
<p class="contact-conformation">Thank you 
    <?php echo $name ?> for your enquiry.
</p>
<a class="contact-conformation-mybutton" href="index">Continue</a>

 

For spawn in sendeail.php you need...

<?php
	 function spawnSecure($var) {
		$spawn = trim(stripslashes($var));
		$now = date('Y-m-d H:i:s');
		$diff = strtotime($now) - strtotime($spawn);
		if($diff<=1) {
			return false; // Took 1 or less seconds to complete the form.
		} else {
			return true;
		}
	}
	if(!spawnSecure(trim(stripslashes($_POST['sent'])))) {
		echo "This appears to be an automated attempt. Click back to try again."; exit();
	}
	// Now the normal stuff can follow.	
?>

For honeypot you don't have a text field in the form for it. You need an input that you want to stay empty and then test if it's empty.

Edit: Ah shoot sorry, you're using an html page so the spawn date wouldn't get added to the form. I'd suggest either making contact.php or alternatively use htaccess to rewrite contact.html to contact.php.

Edited by BrowserBugs

  • Author

Thanks for having a look, is there something else I can do with the setup I have?

You can only use honeypot as no php required in the html. All you would need is an extra form field...

<form action="sendeail.php" method="post">
<div class="to">
<input class="text" name="name" onblur="if (this.value == '') {this.value = 'Name';}" onfocus="this.value = '';" required="" type="text" value="Name" />
<input class="to-right text" name="email" onblur="if (this.value == '') {this.value = 'Email';}" onfocus="this.value = '';" required="" type="text" value="Email" />
</div>
<select name="enquirytype">
<option value="General Enquiry">General Enquiry</option>
<option value="Error on Website">Error on Website</option>
</select>
<textarea class="text" name="enquiry" onblur="if (this.value == '') {this.value = 'Message';}" onfocus="this.value = '';" value="Message:">Message</textarea>
<input class="textt" name="something" type="text" placeholder="Ignore Me" />
<input class="mybutton" name="submit" type="submit" value="Submit" />
</form>

... then in sendeail.php ...

<?php
	if(!empty(trim($_POST['something']))) {
		echo "Possible spam as you've filled out a box that's not required. Click back to try again."; exit();
	}
	// Now the normal stuff can follow.	
?>

... to make the field be hidden from view but still technically visible use css ...

.textt{z-index:100;position:absolute;left:-5000px;}

... all this does is help catch bots which fill out everything by default.

Edit: Doh, forgot something again! You current form incorrectly uses value. The way it's set up at the moment it's adding a value, so say value="name" so it's not empty. Look into placeholders as i've sown, these are hints and don't actually fill in the field.

 

Edited by BrowserBugs
blonde

  • Author

I have added a second field (number field) with a name and placeholder of 'phone', hopefully this will act as another honeypot.

Repeating the code works, but is there a better way of including the 'url' and 'phone' in the same line?

<?php
    if(!empty(trim($_POST['url']))) {
        echo "Possible spam as you've filled out a box that's not required. Click back to try again."; exit();
    }
    if(!empty(trim($_POST['phone']))) {
        echo "Possible spam as you've filled out a box that's not required. Click back to try again."; exit();
    }

 

If they are caught by the honeypot don’t respond. Just use die();

But the cleverer bots can now detect a honeypot. So it’s in your best interest to change your contact page to php and implement other spam traps.

15 hours ago, GrahamUK33 said:

Repeating the code works, but is there a better way of including the 'url' and 'phone' in the same line?

Yep, using OR || ... 

<?php
if(!empty(trim($_POST['url'])) || !empty(trim($_POST['phone']))) {
	echo "Possible spam as you've filled out a box that's not required. Click back to try again."; exit();
}
?>

 

9 hours ago, fisicx said:

If they are caught by the honeypot don’t respond. Just use die();

But the cleverer bots can now detect a honeypot. So it’s in your best interest to change your contact page to php and implement other spam traps.

The honeypot message is fine, better user experience if they did it by mistake and the lower level spam bots which fall for the trap won't read and understand, only a human would and at which point human spam is impossible to beat.

Totally agree switching to php opens up a whole world of anti spam offerings :) 

die ("Go back! ! ");

Don't use die() in production code, it stops the flow of execution and provides a pretty terrible user experience with a blank screen. Clicking back in a modern browser will ask the form to re-submit, and you'll be stuck in a loop of not being able to get back to the original form without totally refreshing, at that stage all data will disappear. Instead this should be posted back to the same page after any validation runs, and either and display any errors or submit. I'd also recommend looking at client side validation once you've finished handling this server side to improve the user experience further.

The easiest way would be to push errors in an array and check to see if the array is empty before allowing submission, otherwise you can loop through the array to output the errors to users.

I would also consider improving your validation to include regex checking for email addresses, checking the length of the content doesn't exceed too any characters (at the moment I could make your form process 1gb of text if I wanted by dumping it in there) and also sanitising the content that gets sent through to your inbox to prevent attacks where a user could spoof a link or run Javascript inside of your mail client.

Forms are tricky, especially for beginners, because it's likely the first code a beginner will come across where they have multiple stages required, each to solve a different problem. It doesn't help that pretty much every form I've seen from a Google search is poorly written.

If anyone finds and fills in the honeypot it means they are being a bit naughty. Nobody with a legitimate reason to fill in the form will ever see the honeypot. So killing the process is fine. You don't want them to go back and have another go.

  • Author

I have turned off the autocomplete to hopeful help a real person from filling in the field without knowing, and have used 'url' as a type to entice the bots to fill that field out. I have also done the same for a phone number field, but used the 'tel' type.

<input class="url" name="url" type="url" placeholder="url" autocomplete="off" />

<input class="phone" name="phone" type="tel" placeholder="phone" autocomplete="off" />

So far it has stopped the spam I was receiving from the form, I will continue to monitor. If this doesn't work then I will bite the bullet and look at converting the HTML contact page into PHP for additional security.

1 hour ago, fisicx said:

If anyone finds and fills in the honeypot it means they are being a bit naughty. Nobody with a legitimate reason to fill in the form will ever see the honeypot. So killing the process is fine. You don't want them to go back and have another go.

The function was used for general failed form validation messages, not just the honeypot. There's no need to use it though, just re-use the same error handling as failed validation. This will keep the code cleaner, and there won't be a random die() function kicking around. 

For example, instead of die() you could have pushValidationError('URL field should not contain a value') as this has clear intent. You could have a function that removes submission if the honeypot is triggered if you really want. Keeping functions around that straight-up kill the process isn't wise in a production environment, a developer should be able to handle error cases properly and clean-up instead of resorting to blowing the page up.

Unfortunately in the script above there's no actual error capturing so it's hard to work it in, but it's something to be aware of in the future as an improvement.

2 hours ago, fisicx said:

If anyone finds and fills in the honeypot it means they are being a bit naughty. Nobody with a legitimate reason to fill in the form will ever see the honeypot. So killing the process is fine. You don't want them to go back and have another go.

The honeypot should be able to be found, else it won't do its job, hence I use z-index as it's still there rather than display none (easy for a bot). Simply tabbing would discover the field, no malicious intent.

1 hour ago, GrahamUK33 said:

I have turned off the autocomplete to hopeful help a real person from filling in the field without knowing, and have used 'url' as a type to entice the bots to fill that field out. I have also done the same for a phone number field, but used the 'tel' type.


<input class="url" name="url" type="url" placeholder="url" autocomplete="off" />

<input class="phone" name="phone" type="tel" placeholder="phone" autocomplete="off" />

So far it has stopped the spam I was receiving from the form, I will continue to monitor. If this doesn't work then I will bite the bullet and look at converting the HTML contact page into PHP for additional security.

I'd drop those placeholders and use something else. If the visitor saw a box with url, placeholder url then there is no reason they can think of not to include a url if they want. Placeholders like "Ignore" or no placeholder would serve better. The idea is always to reduce spam whilst not making the visitors work any harder.

I would also say it's a lot easier to use a php and post to self rather than posting to another page, especially for contact forms, you can always location change for success. This would give you more anti spam like referral, attempts, inline validation messages and other cool bits.

Create an account or sign in to comment

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.