ddantes
asked on
Using PHP to submit a contact form only if a field is left empty
The contact form on my website has been abused by spam bots. I'd like to try a captcha method, referred to as "honeypot", which presents an invisible text field that "tempts" a spam bot to populate it. If the text field is filled in, the form will not be submitted, but a phoney acknowledgment page will appear. If the text field is left blank, the form will be submitted, and an authentic acknowledgment page will appear. The contact form has a section, styled "display:none" which asks the visitor to solve a simple arithmetic problem, and type the answer into a text field. That field is named "captcha".
Below is php code for the contact form handler. I'd appreciate help with adding code to detect whether the "captcha" field has been populated. If it has been populated, the form should not really be submitted, but the visitor's browser should load a page which looks like an acknowledgment. If the captcha field has been left blank, the form should be submitted, and the "thanyou.htm" page should load.
Below is php code for the contact form handler. I'd appreciate help with adding code to detect whether the "captcha" field has been populated. If it has been populated, the form should not really be submitted, but the visitor's browser should load a page which looks like an acknowledgment. If the captcha field has been left blank, the form should be submitted, and the "thanyou.htm" page should load.
<?php
$errors = '';
$myemail = 'stay@mauitradewinds.com';//<-----Put Your email address here.
if(empty($_POST['firstname']) ||
empty($_POST['lastname']) ||
empty($_POST['email']) ||
empty($_POST['message']))
{
$errors .= "\n Error: At a minimum, we need your name, Email address and message in order to transmit your form.";
}
else
{
$firstname = array_key_exists('firstname',$_POST) ? $_POST['firstname']:'';
$lastname = array_key_exists('lastname',$_POST) ? $_POST['lastname']:'';
$Address = array_key_exists('Address',$_POST) ? $_POST['Address']:'';
$City = array_key_exists('City',$_POST) ? $_POST['City']:'';
$State = array_key_exists('State',$_POST) ? $_POST['State']:'';
$Zip = array_key_exists('Zip',$_POST) ? $_POST['Zip']:'';
$Country = array_key_exists('Country',$_POST) ? $_POST['Country']:'';
$Phone = array_key_exists('Phone',$_POST) ? $_POST['Phone']:'';
$email_address = array_key_exists('email',$_POST) ? $_POST['email']:'';
$message = array_key_exists('message',$_POST) ? $_POST['message']:'';
if (!preg_match(
'/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/i',
$email_address))
{
$errors .= "\n Error: Invalid email address";
}
}
if( empty($errors))
{
$to = $myemail;
$email_subject = "Contact form";
$email_body = "You have received a contact form from Site-1. ".
" Here are the details:\n First Name: $firstname \n Last Name: $lastname \n Address: $Address \n City: $City \n State: $State \n Zip: $Zip \n Country: $Country \n Phone: $Phone \n Email: $email_address \n Message: $message \n captcha: $captcha";
$headers = "From: $myemail\n";
$headers .= "Reply-To: $email_address";
mail($to,$email_subject,$email_body,$headers);
//redirect to the 'thank you' page
header('Location: thankyou.htm');
exit;//You should always "exit" immediately after a redirection request
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Contact form handler</title>
</head>
<body>
<!-- This page is displayed only if there is some error -->
<?php
echo nl2br($errors);
?>
</body>
</html>
ASKER
Thank you. I'm unsure about a couple of things. If the form will always be submitted, then this approach is not useful. But it seems, if the field is not blank, then the form won't be submitted, because a fake form will appear, and the program will exit, correct? If that's correct, could you supply the code for loading the fake form? I'll use a different name for the "honeypot" field -- not "captcha".
You're not understanding. The form is Always submitted to the PHP page. The idea is to check the 'honeypot' field first and if they filled it in, put up the 'fake thank you' page and exit without sending it to the database or email.
As Gary pointed out in your previous question, there are people paying people to fill in forms now. None of these methods prevent that. 'captcha' and 'honeypot' only work against automated spam that can't see what's going on.
As Gary pointed out in your previous question, there are people paying people to fill in forms now. None of these methods prevent that. 'captcha' and 'honeypot' only work against automated spam that can't see what's going on.
ASKER
OK. I was misusing the term "submit". I understand that the form will always be submitted to the PHP page, The objective is to serve the fake thank you page and exit, if the honeypot field is popupated.
So, to complete my understanding, after this:
if($_POST['name2'] != '') //show fake display and exit.
what code is required to actually show the fake display and exit?
So, to complete my understanding, after this:
if($_POST['name2'] != '') //show fake display and exit.
what code is required to actually show the fake display and exit?
If nothing else, you can do a 'header' redirect to a plain HTML page. See the examples here: http://us1.php.net/manual/en/function.header.php
ASKER
OK. So, the code would look like this?
<?php
$errors = '';
$myemail = 'stay@mauitradewinds.com';//<-----Put Your email address here.
if(empty($_POST['firstname']) ||
empty($_POST['lastname']) ||
empty($_POST['email']) ||
empty($_POST['message']))
{
$errors .= "\n Error: At a minimum, we need your name, Email address and message in order to transmit your form.";
}
else
{
$firstname = array_key_exists('firstname',$_POST) ? $_POST['firstname']:'';
$lastname = array_key_exists('lastname',$_POST) ? $_POST['lastname']:'';
$Address = array_key_exists('Address',$_POST) ? $_POST['Address']:'';
$City = array_key_exists('City',$_POST) ? $_POST['City']:'';
$State = array_key_exists('State',$_POST) ? $_POST['State']:'';
$Zip = array_key_exists('Zip',$_POST) ? $_POST['Zip']:'';
$Country = array_key_exists('Country',$_POST) ? $_POST['Country']:'';
$Phone = array_key_exists('Phone',$_POST) ? $_POST['Phone']:'';
$email_address = array_key_exists('email',$_POST) ? $_POST['email']:'';
$message = array_key_exists('message',$_POST) ? $_POST['message']:'';
if($_POST['name2'] != '') //show fake display and exit.
header("Location: http://www.fake.com/"); /* Redirect to fake thankyou page */
exit;
}
else
{
if (!preg_match(
'/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/i',
$email_address))
{
$errors .= "\n Error: Invalid email address";
}
}
if( empty($errors))
{
$to = $myemail;
$email_subject = "Contact form";
$email_body = "You have received a contact form from Site-1. ".
" Here are the details:\n First Name: $firstname \n Last Name: $lastname \n Address: $Address \n City: $City \n State: $State \n Zip: $Zip \n Country: $Country \n Phone: $Phone \n Email: $email_address \n Message: $message \n captcha: $captcha";
$headers = "From: $myemail\n";
$headers .= "Reply-To: $email_address";
mail($to,$email_subject,$email_body,$headers);
//redirect to the 'thank you' page
header('Location: thankyou.htm');
exit;//You should always "exit" immediately after a redirection request
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Contact form handler</title>
</head>
<body>
<!-- This page is displayed only if there is some error -->
<?php
echo nl2br($errors);
?>
</body>
</html>
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
the form will not be submitted, but a phoney acknowledgment page will appearDon't bother. The 'bot won't care and it's just more work for your server. Instead test the fake field (named zipcode in this example) like this:
<?php if (!empty($_POST['zipcode'])) die();
/* REST OF NORMAL SCRIPT HERE... */
Regarding the code snippet above, there are some things you might want to "upgrade."
Learn about PHP coding standards and use them, always.
Learn about PHP filter_var() and get rid of regular expressions that you do not understand. This one appears to be copied from some old, obsolete source on the internet.
Don't write a redirect. It makes your original script nearly impossible to debug. Instead build the "thank you" page into the action script right after the mail is sent.
Learn about PHP coding standards and use them, always.
Learn about PHP filter_var() and get rid of regular expressions that you do not understand. This one appears to be copied from some old, obsolete source on the internet.
Don't write a redirect. It makes your original script nearly impossible to debug. Instead build the "thank you" page into the action script right after the mail is sent.
Don't write a redirect.I don't agree with that. If you redirect from the PHP page to a 'thank you' page, users can 'refresh' the thank you page all day without affecting the database. And they do. For no reason what so ever.
And I have one client that insists that I do that. She doesn't want people to see 'php' in the address bar if she can help it. Just 'html'.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks to all experts for comments. We're having a tropical storm here, in Hawaii, with power interruptions every few minutes. I'll post again when we have the luxury of continuous A.C....
ASKER
In a perfect world, I would study PHP until I feel competent to write professional-quality code. I would also debug the code before implementing it. However, in weighing the importance of this project, versus the time and effort involved in doing it perfectly, I'm willing to make some compromises. I hope that is understandable.
The 'honeypot' portion of the contact form is named "how". There is text (styled "display:none"): "How did you learn about Maui Tradewinds?" followed by a text field (also styled "display:none") for entering a response. The form is at www.mauivacationrental.com/contact.htm
Below is the PHP code, and I'd appreciate correction of any sytax errors. I plan to revise the contact htm, making the submit button javascript-dependent. Will this PHP accomplish the stated intention of loading a thankyou page and then exiting, if the "how" field is populated, but proceding with normal function if the "how" field is empty?
The 'honeypot' portion of the contact form is named "how". There is text (styled "display:none"): "How did you learn about Maui Tradewinds?" followed by a text field (also styled "display:none") for entering a response. The form is at www.mauivacationrental.com/contact.htm
Below is the PHP code, and I'd appreciate correction of any sytax errors. I plan to revise the contact htm, making the submit button javascript-dependent. Will this PHP accomplish the stated intention of loading a thankyou page and then exiting, if the "how" field is populated, but proceding with normal function if the "how" field is empty?
<?php
if($_POST['how'] != '') { //show an acknowledgment page and exit.
header("Location: thankyou.htm/"); /* Redirect to thankyou page */
exit; }
$errors = '';
$myemail = 'stay@mauitradewinds.com';//<-----Put Your email address here.
if(empty($_POST['firstname']) ||
empty($_POST['lastname']) ||
empty($_POST['email']) ||
empty($_POST['message']))
{
$errors .= "\n Error: At a minimum, we need your name, Email address and message in order to transmit your form.";
}
else
{
$firstname = array_key_exists('firstname',$_POST) ? $_POST['firstname']:'';
$lastname = array_key_exists('lastname',$_POST) ? $_POST['lastname']:'';
$Address = array_key_exists('Address',$_POST) ? $_POST['Address']:'';
$City = array_key_exists('City',$_POST) ? $_POST['City']:'';
$State = array_key_exists('State',$_POST) ? $_POST['State']:'';
$Zip = array_key_exists('Zip',$_POST) ? $_POST['Zip']:'';
$Country = array_key_exists('Country',$_POST) ? $_POST['Country']:'';
$Phone = array_key_exists('Phone',$_POST) ? $_POST['Phone']:'';
$email_address = array_key_exists('email',$_POST) ? $_POST['email']:'';
$message = array_key_exists('message',$_POST) ? $_POST['message']:'';
if (!preg_match(
'/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/i',
$email_address))
{
$errors .= "\n Error: Invalid email address";
}
}
if( empty($errors))
{
$to = $myemail;
$email_subject = "Contact form";
$email_body = "You have received a contact form from Site-1. ".
" Here are the details:\n First Name: $firstname \n Last Name: $lastname \n Address: $Address \n City: $City \n State: $State \n Zip: $Zip \n Country: $Country \n Phone: $Phone \n Email: $email_address \n Message: $message";
$headers = "From: $myemail\n";
$headers .= "Reply-To: $email_address";
mail($to,$email_subject,$email_body,$headers);
//redirect to the 'thank you' page
header('Location: thankyou.htm');
exit;//You should always "exit" immediately after a redirection request
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Contact form handler</title>
</head>
<body>
<!-- This page is displayed only if there is some error -->
<?php
echo nl2br($errors);
?>
</body>
</html>
The first four lines may be correct. Not sure about the trailing slash on the URL in the header("Location..."). I would not do this part about displaying a page at all. Instead I would use this:
<?php
if(trim($_POST['how']) != '')
{
// SLEEP A MOMENT and exit.
sleep(4);
die();
}
ASKER
Thank you. Is there any way to test this?
Sure, make a test page copy of the regular page that doesn't hide the 'how' field and text and fill it it to see if it does what you want.
ASKER
Sorry for a stupid question. It works just as I had hoped. Before closing this question, I'm still wondering about not redirecting to an acknowledgment page. I would think, if a spambot engineer employed a human visitor to test the form, it might be preferable to give the impression the form was transmitted successfully. Your thoughts?
On most of my form pages, I just let them die if there is something wrong when they are submitted. I was thinking that you didn't want to show a human a bad result... but a human visitor isn't going to fill it out 'wrong' so I'm not sure that it matters.
ASKER
Thanks everyone!
ASKER
Gary: In another question https://www.experts-exchange.com/questions/28480066/Activate-a-disabled-button-with-javascript.html an Expert tells me that bots don't use the Submit button, so there's no point in disabling it. I did disable it, based on your comment ID: 40207422, but I'd like to verify whether that is actually useful. Thanks!
Like I said in that comment usually they don't visit the page and for the ones that do it will block them and even maybe make them think there is nothing to submit if they are harvesting forms.
It's just another tactic.
No matter what you do you will always be 2 steps behind the spammers.
It's just another tactic.
No matter what you do you will always be 2 steps behind the spammers.
ASKER
Understood. Thanks again.
Upon rereading this question, I realize I should have posted a link to this article. Sorry - not thinking...
https://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/A_9849-Making-CAPTCHA-Friendlier-with-PHP-Image-Manipulation.html
https://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/A_9849-Making-CAPTCHA-Friendlier-with-PHP-Image-Manipulation.html
ASKER
Thanks, Ray. I ended up using a combination of the "honeypot" method, along with a disabled
"Submit" button which requires javascript to activate. There have been no instances of spambot submission of our contact forms since these were implemented.
"Submit" button which requires javascript to activate. There have been no instances of spambot submission of our contact forms since these were implemented.
Open in new window