I am trying to create a hidden email field in my contact form that, when filled out, will not send me an email (meaning a spammer filled in the hidden email field), instead, just sending the spammer to a confirmation page saying that the email was sent.
I can't get it to work properly.
Test site - http://www.webexplosive.com/s1/contact.html
Here is my php script for the contact form:
<?php
$firstname = $_POST['firstname'];
$lastname = $_POST['lastname'];
$email1 = $_POST ['email1'];
$phone = $_POST ['phone'];
$comments = $_POST ['comments'];
$testBot = $_POST ['email2'];
$headers = "MIME-Version: 1.0\r\n";
$headers = "From: $email1";
$to = 'beefjelly69#yahoo.com';
$subject = 'Contact Form Submitted - Virginia Subsite';
$message = "
First name: $firstname \n
Last name: $lastname \n
Email: $email1 \n
Phone: $phone \n
Comments: $comments \n";
mail($to, $subject, $message, $headers);
header("Location: thankyou.html");
if(email2 == "") { //If email2 form section is blank then...
$firstname = $_POST['firstname'];
$lastname = $_POST['lastname'];
$email1 = $_POST ['email1'];
$phone = $_POST ['phone'];
$comments = $_POST ['comments'];
$testBot = $_POST ['email2'];
$headers = "MIME-Version: 1.0\r\n";
$headers = "From: $email1";
$to = 'beefjelly69#yahoo.com';
$subject = 'Contact Form Submitted - Virginia Subsite';
$message = "
First name: $firstname \n
Last name: $lastname \n
Email: $email1 \n
Phone: $phone \n
Comments: $comments \n";
mail($to, $subject, $message, $headers);
header("Location: thankyou.html");
}
else {
header("Location: thankyou.html");
}
?>
Code Technique
The best way, I've seen for weeding out bots and spammers in conmment and public forms, without captcha. Is to generate a random md5 hash (each refresh, should render the previous hash useless), store said hash in a cookie (for POST retrieval). Then append the hash string to each input[name=username_d109770c2788b022deb0fac1182c9e19] (I'd also POST the hash on the form, and validate the POST against the cookie).
The benefit to hashing input fields is.. it will increase the difficulty of bots being able to hard code to specific inputs (plus passive server validation).
Once you've done this simply add input validation such as email regular expressions and so fourth.
Security Technique
Install the honeypot project to your server, it has 101,130,389 spam servers identified as of 8:48 PM, 19/02/2014 (UTC+12:00).
Project Honey Pot is a web based honeypot network which uses software embedded in web sites to collect information about IP addresses used when harvesting e-mail addresses for spam
This is because you always call the mail form first. You need to validate it before you call it. Call the mail function after you have checked that the email2 field is empty.
As it is, it will always send the mail, before hitting the if statement.
Suggestion: Look into implementing a captcha or something similar than that.
Here's a revised version of your code with basic form validation (but it only checks for empty fields, it doesn't check if the e-mail is valid - you can easily add that though) and more importantly, email header injection protection.
Note : I didn't test this code and it may fail miserably - feel free to downvote if that's the case
// Form validation, display errors
// in case of empty fields
$fields = ["firstname", "lastname", "email1", "phone", "comments"]
foreach ($fields as $field) {
if (!isset($_POST[$field]) || empty($_POST[$field])) {
die("Error, ".$field." can't be empty, please retry."); // if validation fails we stop the script
}
}
if (isset($_POST["email2"]) && !empty($_POST["email2"])) {
die(); // hidden field isn't empty, so it's spam, so we stop there
}
// e-mail header injection protection
$email1 = filter_var($_POST["email1"], FILTER_SANITIZE_EMAIL);
$firstname = $_POST['firstname'];
$lastname = $_POST['lastname'];
$phone = $_POST ['phone'];
$comments = $_POST ['comments'];
$headers = "MIME-Version: 1.0\r\n";
$headers = "From: $email1";
$to = 'beefjelly69#yahoo.com';
$subject = 'Contact Form Submitted - Virginia Subsite';
$message = "
First name: $firstname \n
Last name: $lastname \n
Email: $email1 \n
Phone: $phone \n
Comments: $comments \n";
mail($to, $subject, $message, $headers);
header("Location: thankyou.html");
(A late answer, but could prove to be useful down the road).
Generally, SPAMBOTS will look for a form element called email or contact or any visible input they can put their little spammy hands on.
What you could do is to show/mark an input stating "If you're human, DO NOT fill this".
For example:
If you're human, DO NOT fill this: <input type="text" name="email">
then check if the field is not empty. If it is not empty and (most likely) filled in by the SPAMBOT, then make it die(); or redirect.
For example: and using an if(isset... from a named submit button:
<input type="submit" name="soobmeet" value="Send">
Sidenote: I chose "soobmeet" because it's generally not a good idea to name it "submit" etc.
(Something I learned recently from one the BIG GUNS here on SO)
PHP
<?php
if(isset($_POST['soobmeet'])){
$firstname = $_POST['firstname'];
$lastname = $_POST['lastname'];
$email1 = $_POST ['email1'];
$phone = $_POST ['phone'];
$comments = $_POST ['comments'];
$email = $_POST ['email'];
if(!empty($_POST['email'])){
header("Location: get_lost.html");
// or make it die();
}
else{
$headers = "MIME-Version: 1.0\r\n";
$headers = "From: $email1";
$to = 'email#example.com';
$subject = 'Contact Form Submitted - Virginia Subsite';
$message = "
First name: $firstname \n
Last name: $lastname \n
Email: $email1 \n
Phone: $phone \n
Comments: $comments \n";
mail($to, $subject, $message, $headers);
header("Location: thankyou.html");
}
}
?>
First of all, I honestly don't recommend this as a spam/bot deterrent - there are many well tested third party libraries out there for you to use. Having said that, I've edited your code with some minor improvements. Hope this helps somewhat.
<?php
// Note: It is your own responsibility to validate user input!
if(isset($_POST['email2']) && $_POST['email2'] != "") {
$strFirstName = $_REQUEST['firstname'];
$strLastName = $_REQUEST['lastname'];
$strEmail = $_REQUEST['email1'];
$strPhone = $_REQUEST['phone'];
$strComments = $_REQUEST['comments'];
$strTestBot = $_REQUEST['email2'];
$strBody = "First name: ".$strFirstName." \nLast name: ".$strLastName." \nEmail: ".$strEmail." \nPhone: ".$strComments." \n";
mail('beefjelly69#yahoo.com', 'Contact Form Submitted - Virginia Subsite', $strBody, 'From: '.$strEmail);
header("Location: thankyou.html");
} else {
header("Location: thankyou.html");
}
?>
Is this what you're trying to achieve? Also, you should be validating each of the fields e.g. checking whether they're empty, of the right format and length etc. preg_match() is an awesome way of doing this, plus you can add some minor validation at the client side as well.
Related
I have two scenarios for my form that will determine if the submission is successful or failed. Either outcome serves the user with a unique page. I am looking for a way that the successful submissions are emailed to group A email addresses and the failed submissions are sent to Group B email addresses.
Here is my code:
<?php session_start();
if(isset($_POST['Submit'])) {
$from=$_POST['empty'];
$to=$_POST['empty'];
$subject=$_POST['empty'];
$text=$_POST['empty'];
$html=$_POST['empty'];
$file=$_POST['empty'];
$mimetype=$_POST['empty'];
$host=$_POST['empty'];
$username=$_POST['empty'];
$password=$_POST['empty'];
$Q1=$_POST['Q1'];
$Q2=$_POST['Q2'];
$Q3=$_POST['Q3'];
$Q4=$_POST['Q4'];
$fromsubject = 'sample-subject';
$firstname = $_POST['firstname'];
$mail = $_POST['mail'];
$phonenumber = $_POST['phonenumber'];
$to = 'myemail#gmail.com';
$header = "From: <" . $mail . ">\r\n"; //optional headerfields
$mailsubject = 'Message recived from sample site';
$body = $fromsubject.'
The person that contacted you is '.$firstname.'
Phone number: '.$phonenumber.'
E-mail: '.$mail.'
Q1: '.$Q1.'
Q2: '.$Q2.'
Q3: '.$Q3.'
Q4: '.$Q4.'
|---------END MESSAGE----------|';
mail($to, $mailsubject, $body, $header);
if ($Q3 == "yes") {
header('Location: http://example.com/success.php');
} else {
header('Location: http://example.com/resources.php');
}
?>
I apologize for the confusion. My form has 4 questions in it. If they answer no to one of them, they do not qualify for our offer. If they answer yes to all, they qualify. The all yes users need to be sent to our call center email address while the other respondents who did not answer all yes go to our recovery department. –
I'm trying to use this mailer and have it redirect to a success/fail page depending on the fields a user enters. It works and sends the mail and also redirects to a success page when all the fields are entered, but when nothing is entered it just goes to a blank page but still sends the mail?
How could I make this work as intended? Ideally I would like it to just direct to the same page and show a success or error message within the page but I don't know how to do it.
My code for my mailer is below:
<?php
$name = $_POST['name'];
$company = $_POST['company'];
$email = $_POST['email'];
$phone = $_POST['phone'];
$website = $_POST['website'];
$features = $_POST['features'];
$budget = $_POST['budget'];
$timeline = $_POST['timeline'];
$content = $_POST['content'];
$additional = $_POST['additional'];
$to = "hello#phnx-creative.co";
$subject = "Project Req: $company";
$body = "Name: $name \n\n Company Name: $company \n\n Email: $email \n\n Phone Number: $phone \n\n Website: $website \n\n Features: $features \n\n Budget: $budget \n\n Timeline: $timeline \n\n Content: $content \n\n Additional Info: $additional";
$from = $email;
if(!empty($_POST['name']) || !empty($_POST['email']) || !empty($_POST['phone']) || !empty($_POST['features']) || !empty($_POST['budget']) || !empty($_POST['timeline']) || !empty($_POST['content'])){
if (mail($to, $subject, $body, $headers)) {
header("Location: success.php");
} else {
header("Location: error.php");}
}
?>
You don;'t appear to have $headers set. That may be the issue, set it up so that it sends it with $headers
In your if statement where you check that you received everything through POST , you should use the "and" comparator && and not the "or" comparator ||. In your case, the condition will be true if only one of the POST variable is not empty - unless this is what you want?
You should also check the content of the POST variables before assigning their value to your variables at the top. You could do something like suggested by Tibbers.
I have a form in my webpage that sends data submitted by the user to an email address. i.e. a contact form. I know how to open a new page to inform the user that the data has been fired off to the email address. However I do not want to open a new page, I just want to inject a simple Email Sent! text below the actual form for the user; instead of redirecting to a new page.
I have absolutely no idea how to achieve this in PHP. I have all the basics of the process script set up here;
<?php
/*--/ subject & email variables /--*/
$emailSubject = 'Email Title';
$webMaster = 'php.test#outlook.com';
/*--/ gathering data variables /--*/
$firstField = $_POST['first_Name'];
$lastField = $_POST['last_Name'];
$emailField = $_POST['email'];
$telField = $_POST['phone'];
$selectField = $_POST['select'];
$enquiryField = $_POST['enquiry'];
$body = <<<EOD
<br><hr><br>
First Name: $first_Name <br>
Last Name: $last_Name <br>
Email: $email <br>
Tel: $phone <br>
I heard about you from; $select <br>
Enquiry: $enquiry <br>
EOD;
$headers = "From: $email\r\n";
$headers .= "Content-type: text/html\r\n";
$success = mail($webMaster,$emailSubject, $body, $headers);
?>
If anyone can help I would be thankful.
Hello Fellow Stackers,
New to PHP and I am putting together a multipage form from pre-built code.
Basically the user selects as many checkboxes as they want... then the form submits to this secondary page. This secondary page echo's the checkboxes they chose at the top of the page via $check.. then they can enter their contact information and all of the information gets submitted via form, along with the $check information.
Everything is working perfectly except $check isn't being entered into the form message, but it works up at the top of the page, displaying which options the user inputted.
Any help is appreciated!
<?php
$emailOut = '';
if(!empty($_POST['choices'])) {
foreach($_POST['choices'] as $check) {
echo $check; //echoes the value set in the HTML form for each checked checkbox.
//so, if I were to check 1, 3, and 5 it would echo value 1, value 3, value 5.
//in your case, it would echo whatever $row['Report ID'] is equivalent to.
$emailOut .= $check."\n"; //any output you want
}
}
$errors = '';
$myemail = 'test#myemailHERE.com';//<-----Put Your email address here.
if(empty($_POST['name']) ||
empty($_POST['email']) ||
empty($_POST['message']))
{
$errors .= "\n Error: all fields are required";
}
$name = $_POST['name'];
$email_address = $_POST['email'];
$message = $_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 submission: $name";
$email_body = "You have received a new message. $check ".
" Here are the details:\n Name: $name \n Email: $email_address \n Message \n $message \n $emailOut";
$headers = "From: $myemail\n";
$headers .= "Reply-To: $email_address";
mail($to,$email_subject,$email_body,$headers);
//redirect to the 'thank you' page
header('Location: contact-form-thank-you.html');
}
?>
The thing in this situation is that when you get down to the email, $check is the last option displayed. You need to use the foreach statment to build the array or email output such as
$emailOut = "";
foreach($_POST['choices'] as $check) {
$emailOut .= $check."\n"; //any output you want
}
Then use your email variable in the same way
$email_body = "You have received a new message. Here are the details:\n Name: $name \n Email: $email_address \n Message \n $message \n $emailOut";
UPDATE
From further investigation and more code submitted, it appears that you are working with a multi-form submssion issue. The issue is you have form 1 (checkboxes) that submits to form 2 (email).
Since when doing the checks after the checkbox submission, no name, email, etc was given so $errors were given and no email sent. When filling out the email form, the checkboxes were not sent again so $check or even $_POST['choices'] had values.
You can either put the two forms into one, or you can look into a way to save the values by passing them and filling a 'hidden' field (<input type='hidden' value='...'>) or use a session with PHP.
I've been using the same php script to send emails from contact forms for years. But when my web server upgraded to php 5.3 the call to eregi was causing deprecated errors to display.
After a Google search I learned that I could use stristr instead of eregi.
When I make this simple switch everything works just fine, but I'm no php wizard so I want to know if my script is still secure from header injections.
Can someone please put my mind at ease and confirm that this script is safe (or at least safe enough) to use for sending emails from a contact form?
Here is an example of the current script with stristr in use:
<?
$to="myemail#gmail.com";
// the $Name is the PHP variable, the _Post['Name'] should match the name of the input boxes in the form
$Name=$_POST['Name'];
$Email=$_POST['Email'];
$Phone=$_POST['Phone'];
$Message=$_POST['Message'];
// you can format the email anyway you want.
$message="Form submitted by $Name
Applicant Information:\n
Name: $Name
Email: $Email
Phone: $Phone
Message: $Message";
// Check for script HiJack
$arBadStr = array("Content-Type:", "MIME-Version:", "Content-Transfer-Encoding:", "bcc:", "cc:");
foreach($_POST as $tName => $tVal){
foreach($arBadStr as $tStr){
if(stristr($tStr, $tVal)){
$fSub = "Failed: Header Injection.";
reportError($fSub);
}}}
if(mail($to,"mywebsite.com contact Form Submission",$message,"From: $Name <$Email>")) {
echo "Thank you $Name for your interest. We will contact you shortly";
} else {
echo "There was a problem sending the mail. Please check that you filled in the form correctly.";
}
// Report error function called when test detects hijacking. Mails report to webmaster and kills process.
function reportError($fSub) {
while(list($name, $value) = each($_POST)) {
$eBody .= "$name : $value \n\r"; }
mail( "myemail#gmail.com", $fSub, $eBody, "From: Webmaster <myemail#gmail.com>");
exit(header("Location: http://www.mywebsite.com")); }
?>
UPDATE
Based on the ever-so-gracious help from cryptic this is what my new script looks like. As you can see I've stripped out some of the header validation functions in place of simply sanitizing the input fields.
<?
$to="myemail#gmail.com";
// the $Name is the PHP variable, the _Post['Name'] should match the name of the input boxes in the form
$Name = str_replace(array("\n", "\r"), '', $_POST['Name']);
$Email = str_replace(array("\n", "\r"), '', $_POST['Email']);
$Phone = str_replace(array("\n", "\r"), '', $_POST['Phone']);
$Message = str_replace(array("\n", "\r"), '', $_POST['Message']);
function clean_string($string) {
$bad = array("content-type","bcc:","to:","cc:","href");
return str_replace($bad,"",$string);
}
$Name = clean_string($Name);
$Email = clean_string($Email);
$Phone = clean_string($Phone);
$Message = clean_string($Message);
// you can format the email anyway you want.
$message="Form submitted by $Name
Applicant Information:\n
Name: $Name
Email: $Email
Phone: $Phone
Message: $Message";
if(mail($to,"mywebsite.com contact Form Submission",$message,"From: $Name <$Email>")) {
echo "Thank you $Name for your interest. We will contact you shortly";
} else {
echo "There was a problem sending the mail. Please check that you filled in the form correctly.";
}
?>
You try to blacklist headers like BCC, CC but fail to block TO, FROM.
RFC 822 on page 16 in section 4.1 it states:
This specification permits multiple occurrences of most fields. Except
as noted, their interpretation is not specified here, and their use
is discouraged.
So an attacker would be able to manipulate the message to add additional recipients and senders. You should really just be checking for newlines and carriage returns or just sanitize all the $_POST values by stripping out \r and \n characters.
<?php
function clean_string($string)
{
return str_replace(array("\n", "\r"), '', $string);
}
$to = 'myemail#gmail.com';
// the $Name is the PHP variable, the _Post['Name'] should match the name of the input boxes in the form
$Name = clean_string($Name);
$Email = clean_string($Email);
$Phone = clean_string($Phone);
$Message = clean_string($Message);
// you can format the email anyway you want.
$message = "Form submitted by $Name
Applicant Information:\n
Name: $Name
Email: $Email
Phone: $Phone
Message: $Message";
if (mail($to, 'mywebsite.com contact Form Submission', $message, "From: $Name <$Email>"))
{
echo 'Thank you ' . htmlspecialchars($Name) . ' for your interest. We will contact you shortly';
}
else
{
echo "There was a problem sending the mail. Please check that you filled in the form correctly.";
}
?>