I put together a simple PHP email form for a website, but it keeps sending blank emails every so often. Most of the the fields are "required" and I was using a captcha system for a while, but the blank emails kept coming.
HTML markup:
<form action="mail_send.php" method="post">
<input name="name" type="text" required="required" size="40" />
<input name="email" type="text" required="required" size="40" />
<input name="company" type="text" size="40" />
<textarea name="message" cols="80" rows="7" required="required"></textarea>
<input type="submit" value="Submit" />
</form>
PHP:
$name = $_POST['name'];
$email = $_POST['email'];
$company = $_POST['company'];
$message = $_POST['message'];
$formcontent=" FROM:\n $name \n\n COMPANY:\n $company \n\n MESSAGE:\n $message";
$recipient = "email address";
$subject = "Subject";
$mailheader = "From: $email \r\n";
mail($recipient, $subject, $formcontent, $mailheader) or die("Error!");
echo "<script>window.location = 'confirmation.php'</script>";
Everything works fine when I test it, I receive the emails from the form with no problems at all, but for some reason I keep getting blank emails often (possibly from robots).
Any ideas?
Thanks!
That could happen if your HTML form and PHP are inside the same file while you're not checking if any of those inputs are empty or not. And if not in the same file, not checking for emptyness, still applies.
You could be the victim of bots, or some joker visiting your site ever so often just to tick you off.
Or that the form's method's URL is being accessed directly by someone or something, which is what I feel may be the issue here, since you do have required for your inputs.
Check your access logs.
So, use a conditional !empty() against all your inputs.
http://php.net/manual/en/function.empty.php
I.e.:
Sidenote: || checks to see if one or any are empty.
if( !empty($_POST['name']) || !empty($_POST['email']) ){
$name = $_POST['name'];
$email = $_POST['email'];
// process mail
}
You can add the other ones in.
Or give your submit a name attribute:
<input name="submit" type="submit" value="Submit" />
Then check if the button is set and that the inputs are not empty:
if(isset(_POST['submit'])){
if(!empty($_POST['name']) || !empty($_POST['email']) ){
$name = $_POST['name'];
$email = $_POST['email'];
// process mail
}
}
You should also use filters, for the email input:
http://php.net/manual/en/function.filter-var.php
http://php.net/manual/en/filter.examples.validation.php
Plus, if you decide to use radios/checkboxes later on, use isset() against those.
Sidenote:
You could add a checkbox to your form to check if it was checked or not, and handle it with a conditional statement.
Footnotes:
"Most of the the fields are "required" and I was using a captcha system for a while, but the blank emails kept coming."
There isn't any captcha code in your question to support this.
N.B.:
The required attribute only works in HTML5 supported browsers. Therefore, if any of those bots or visitors to your site are using a browser that doesn't support HTML5, or technology that can bypass it, then that too could be another (contributing) factor.
You will want to do validation on your PHP.
http://www.w3schools.com/php/php_form_validation.asp
Basically you will want to do the following:
Security
<?php
// define variables and set to empty values
$name = $email = $gender = $comment = $website = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$name = test_input($_POST["name"]);
$email = test_input($_POST["email"]);
$website = test_input($_POST["website"]);
$comment = test_input($_POST["comment"]);
$gender = test_input($_POST["gender"]);
}
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
Validation
if (!empty($email)){
//your code to send email
}
You could make it a little more complex if you want to check more than one thing.
$fail_validation = FALSE;
if (empty($email)){
$fail_validation = TRUE;
}
if (empty($phone)){
$fail_validation = TRUE;
}
if ($fail_validation == FALSE){
//code to send mail goes here
}
Please note, this is very basic, and you may want to consider looking into some extra functions to secure the PHP. I would also suggest using a honeypot as an extra layer of security.
https://stackoverflow.com/a/22103646/2547075
<textarea name="message" cols="80" rows="7" required="required"></textarea>
should be
<textarea name="message" cols="80" rows="7" required></textarea>
Are you writing XHTML or HTML?
Validation on the server side is also recommended. See answers below on how to do it.
But for some reason you're getting blank emails, possibly from robots
pretty much answered your question. Robots can be pretty advanced and break certain Captcha'a as well to post blank post requests. You should check if the post requests are not empty.
The unbreakable captcha's are the ones you've written yourself (and not spread be-hound your website until it becomes popular) or the recently introduced one from Google. give it a try (once you've checked for empty values)
Related
I am doing a school project which require me to create a buy & sell website.
I have a form for user to input values such as name, email, etc. After it is filled up, they will press "submit" button, and the values will be written to my txt file.
However, I realized that, empty data are being written into the txt file as well, causing my text file to look like this
It happens when user click on the navigation button to access the form. Even when no values are entered. Empty spaces are written to my txt just by accessing the form.
Below is my code.
<?php
// define variables and set to empty values
$sellerNameErr = $emailErr = "";
$sellerName = $email = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (empty($_POST["sellerName"])) {
$sellerNameErr = "Name is required";
}else {
$sellerName = test_input($_POST["sellerName"]);
}
if (empty($_POST["email"])) {
$emailErr = "Email is required";
}else {
$email = test_input($_POST["email"]);
// check if e-mail address is well-formed
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$emailErr = "Invalid email format";
}
}
}
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
<form name="sell" action="" method="post">
<p><span class = "error">* required field.</span></p>
<p>Seller Name: <input type="text" name="sellerName" />
<span class = "error">* <?php echo $sellerNameErr;?></span></p>
<p>Email: <input type="text" name="email" />
<span class = "error">* <?php echo $emailErr;?></span></p>
<input type="submit" name="Submit" value="Submit" />
<?php
$fp=fopen("buynsell.txt", "ab");
fwrite($fp,"$sellerName\t $email\r\n");
fclose($fp);
?>
</form>
How can I prevent empty data from being added to my log file?
Before writing to the file, you need to verify that $sellerName and $email have values and that there were no errors.
if ($sellerName && $email && !$sellerNameErr && !$emailErr) {
$fp=fopen("buynsell.txt", "ab");
fwrite($fp,"$sellerName\t $email\r\n");
fclose($fp);
}
The way you have it written now you don't need to do anything to check that those variables are set because you're initializing them all to empty strings, but if you change that, you should use empty()/!empty() instead to avoid undefined variable notices.
If you move the file writing PHP code inside the post handling code at the top so that it will only run when the form has been posted, after the validation code that checks if the inputs are empty, then you should be able to just check for errors only. if (!$sellerNameErr && !$emailErr) { .... Personally, I think it makes more sense for it to be there anyway. It's easier to read if all your PHP code is together, and there's no need for that code to be down there in the form.
Mark, there are many ways to prevent that empty data does not get into your business logic.
As for your project the most simple way to achieve this would be to set an additional attribute within your html markup.
As for HTML5 this could by your first solution:
<input type="text" name="usrname" required>
https://www.w3schools.com/tags/att_input_required.asp
Not that really efficient as only on client side, so you should also implement this on your server side.
empty($_POST['user']) will not work as you are never posting that value, therefore you must add an value attribute to your input field:
<input type="text" name="user" value="" />
My question might be quite a simple one, but I am very new to PHP and have tried to piece everything together after reading, but have run into some problems. I have read through possible duplicates of this post and tried as much as possible to put those solutions into my code but to no avail.
Objective:
Name and email validation (just not empty and in email format)
Details sent to indicated email
Basic sanitizing of code (mysqli escape and htmlspecialchars) (Understand that there is PDO, but would like to stick to this).
After successful submission, reload page with same website (fields empty) but with message in indicating message sent or error. Am trying header("Location: "). Would prefer not to introduce AJAX as I have no knowledge of it. Is this possible? Have also read about using action:"" to stay on same page, but how do I run my mail.php if my action is ""? Have also tried include: mail.php, or renaming my mail.php to index.php, but still did not succeed.
Current problems faced:
I do receive an email but with empty fields, i.e. inputs are not reflected although I did enter some values in the form. These are the values I received:
From:
Phone:
etc....
Page does direct to header location. But div not updated with $success variable, i.e. no message updated to show in div.
Please refer to my php and html file below:
PHP:
<?php
$link = mysqli_connect("host", "username", "password", "dbname");
$NameErr=$EmailErr=$Success="";
$Name=$Email=$Company=$JobTitle=$Phone=$Message="";
function sanitize($link,$entry) {
$entry = mysqli_real_escape_string($link,$entry);
$entry = htmlspecialchars($entry);
return $entry;
}
if (empty($_POST["Name"])) {
$nameErr = "Name is required";
}
else if (!preg_match("/^[a-zA-Z ]+$/", $Name)) {
$NameErr = "Only letters and spaces allowed";
}
else {
$Name = sanitize($link, $_POST["Name"]);
}
if (empty($_POST["Email"])) {
$EmailErr = "Email is required";
}
else if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$EmailErr = "Invalid email format";
}
else {
$Email = sanitize($link, $_POST["Email"]);
}
$Company = sanitize($link, $_POST["Company"]);
$JobTitle = sanitize($link, $_POST["JobTitle"]);
$Phone = sanitize($link, $_POST["Phone"]);
$Message = sanitize($link, $_POST["Message"]);
$formcontent=" From: $Name \n Phone: $Phone \n Company: $Company \n Job Title: $JobTitle \n Phone: $Phone \n Message: $Message";
$recipient = "myemail#gmail.com";
$subject = "Contact Form";
$mailheader = "From: $Email \r\n";
if (mail($recipient, $subject, $formcontent, $mailheader)){
$Success = "Message sent, thank you for contacting us!";
header("location:Contact.Us.html");
}
else($Success = "Sorry, we are unable to process your submission.");
?>
HTML form:
<form action="mail.php" method="POST">
<ul class="contact">
<li>
<label for="Name">Name<span class="red">*</span></label>
<p><input id="Name" name="Name" type="text" required/></p>
</li>
<li>
<label for="Email">Email<span class="red">*</span></label>
<p><input id="Email" name="Email" type="email" required/></p>
</li>
<li>
<label for="Company">Company</label>
<p><input id="Company" name="Company"/></p>
</li>
<li>
<label for="JobTitle">Job Title</label>
<p><input id="JobTitle" name="JobTitle"/></p>
</li>
<li>
<label for="Phone">Phone</label>
<p><input id="Phone" name="Phone"/></p>
</li>
<li>
<label for="Message">Message</label>
<p><textarea id="Message" wrap="soft" name="Message"></textarea></p>
</li>
</ul>
<br>
<p><input id="submit" type="submit" value="Send!" /></p>
<div class="success"><? =$Success; ?></div>
</form>
Would appreciate your reply to resolve any of the problems mentioned above. Would also appreciate if you could highlight other areas of possible security concerns. Thanks!
Also, upon implementing recommendation of sanitize($link,$entry), I am receiving inputs in my email for the variables: Company and Job Title.
Hence, I further changed all my variables name to first letter capital i.e. $message to $Message and aligned it throughout my form's input 'id', 'name' and 'for'. After which, I managed to receive input for the additional variables of Phone and Message.
Currently, am only not receiving values in my email for variables Name and Email. Perhaps there is an error with my 'if else if' portion of the php code. Will figure and update again. In the meantime, if any recommendation, please continue to update too. Thanks for your help!
As #headmax pointed, you need to also pass the link parameter to the sanitize function
function sanitize ($link, $entry) {
}
Reason is without passing it as a parameter, the $link variable becomes undefined. If you had error reporting on, you would have gotten a notice on $link.
For future purposes, whenever in development environment, always turn on error reporting as
error_reporting(E_ALL);//place this at the top of the script
EDIT
In order for you to display the success message and perform a redirect, you'd be better off using Ajax.
setTimeOut();//use this to display the success message for a while(pass number of seconds)
Then perform a redirect using javascript as
window.location.href ='URL';
Using your approach, just declare the success variable as
$success = '';//add this before you use the variable
im using this contact form below. When I was running it on my local machine it was working. But on my server if the form fails it does the right thing and goes to fail.php but when all the fields are filled it goes to send_contact2.php after clicking send instead of success.php
This is the send_contact2.php
if (empty($_POST['name'])
|| empty($_POST['number'])
|| empty($_POST['email'])
|| empty($_POST['messagearea'])
){
header('Location: fail.php');
}
else {
$name = $_POST['name'];
$number = $_POST['number'];
$email = $_POST['email'];
$messagearea = $_POST['messagearea'];
$to = 'example#gmail.com';
$subject = "Website Message: Contact form";
$message = '$messagearea';
$headers = "From: WebsiteMessage";
mail($to, $subject, $message, $headers);
header("Location: success.php");
}
?>
This is my form
<form name="form1" method="post" action="send_contact2.php">
<input name="name" type="text" placeholder="Your Name"/> <br/>
<input name="email" type="email" placeholder="Your Email"/> <br/>
<input name="number" type="tel" placeholder="Your Number"/> <br />
<textarea name="messagearea" cols="" rows="" id="messagearea" placeholder="Your Message"/></textarea> <br/>
<input name="sumbit" type="submit" value="SEND" id="button2" />
</form>
I have this setting in my cPanel
Any help would be greatly appreciated
if the page stay on send_contact2.php it is because, header("Location: success.php") do not redirect. read this post, it could help. Php header location redirect not working
In my opinion PHP must be outputing some text (char, error or warning?) or you have used a char before <?php in your send_contact2.php file. That's why header is not working. Remember that header() must be called before any actual output is sent.
OP here, managed to sort it in the end
Was a mail server issue, so if anyone in the future gets this problem check your php settings on your hosting and make sure it allows mail() and make sure you set up an email address where you're sending the email to on your server.
thanks to everyone that helped me debug
I have a form that I am trying to add some steps that will minimize spam without forcing the end user to input some random number text series.
here’s an example of my form code:
<form action="form.php" method="post">
<label for="Name" style="some style">Enter your name:</label>
<input type="text" name="name">
<label for="Email" style="some style">Your email address:</label>
<input type="text" name="email">
<label for="City" style="some style">City:</label>
<select id="some ID" name="city" value="PQS" >
<option value="" selected disabled>Choose A City</option>
<option value="City1">City1</option>
<option value="City2">City2</option>
<input type="submit" value="Sign Up Now" class="button" id="subscribe">
</form>
<p id="error" style="some style">OOPS! Something went wrong. Please try again.</p>
<p id="success" style="some style">Success! We’ll contact you shortly</p>
My current form.php looks somewhat like this:
<?php
$emailmanager = 'me#myemail.com';
$name = $_POST['name'];
$visitor_email = $_POST['email'];
$city = $_POST['city'];
error_reporting(0);
$email = trim($_POST['email']);
$Ok = ereg("^([a-zA-Z0-9_\.-]+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+)) ([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", $email);
if ($Ok) {
mail($emailmanager,'New Contact Request','You have a new contact request for homes in '.$_POST['city'].' from '.$_POST['name'].' ','From: '.$_POST['email'].' ');
if( !ereg("^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$",$UNameFrm) )
{
echo 1;
}
}
else
{
echo 0;
}
What I am trying to incorporate is a blank field that can deter the spambots, and I found an awesome code to use but I would like to incorporate it into my code above. See below the code i found:
<?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 ?>
This code i found requires me to create a class
.antispam { display:none;}
...and add some html in my form
<label for="url" class="anti spam">Leave This Empty:</label>
<input type="text" name="url" />
how do I incorporate these 2 together? There are some things that are obvious to me, like adding
$url = $_POST['url'];
to my form.php on the next line following $city. My challenge is where to incorporate
// if the url field is empty
if(isset($_POST['url']) && $_POST['url'] == '')
and
if( $_POST['email'] && !preg_match( "/[\r\n]/", $_POST['email']) ) {
$headers = "From: $_POST[email]";
} else {
$headers = "From: $youremail";
}
into my form.php without screwing up my form function entirely. Any help would be appreciated, and I hope I made my question clear
You generate a random token for each guest session (or even user's login or form page) and save in database.
When printing forms, add one hidden input.
<input type="hidden" name="token" value="token_value_RANDOM1234567890">
When user submits form, then you check if given token is valid (or belongs to authenticated user, in login case). If belongs, then he's a valid user, else is a bot (not so simple as that). By the way, it complicates the process of spamming, do not block all ways of spamming. And you get an improvement on your website security.
Hope it helps.
You should put the class on the input, not the label, since labels aren't sent to the server.
<input type="text" class="antispam" name="antispam" value="">
Browsers won't send inputs that have display: none;, so if you receive this input, it means it came from an automated spammer.
if (isset($_POST['antispam'])) {
// Reject as spam
}
I use this honeypot tactic all the time. The trick is to create a field on the form that will not be visible to humans with eyes, but will be seen by bots. I usually give it an attractive name like "url" like your example does.
<input class="honeypot" name="url" value="url" />
Then you use CSS to push it off the screen:
input.honeypot {
position:absolute;
left:-5000px;
}
That can go anywhere in your stylesheet, or in a <style> tag in your html, or right on the input
<input style="position:absolute; left:-5000px;" name="url" value="url" />
Then you need a test in the validation code which is the action PHP:
if (isset($_POST['url'] && 'url' != $_POST['url']) {
header("location:/routing-error");
}
This gives the bot a 404 for the page "routing-error"
I have designed the comments box for getting comments. Instead of using captcha plugins, i have prepared custom captcha with 5 digit number. When I submit the details, still I getting error page. I have checked various sites in Google but could not find the correct answer.
comments.html - Comment box for comments
captcha.php - Custom captcha with 5 digit code
submit.php - for processing the code
error.html - error page for wrong entry
thank.html - Page on submitting successful
I am unable to sort-out where the mistake is. Kindly help me in this regards.
The sources codes of comments.html and submit.php is given below.
=========COMMENTS.HTML==============
<form action="submit.php" method="post">
Name: <input type="text" name="name" /> <br>
Email: <input type="text" name="email" /> <br>
Comments: <textarea name="coments" /> <br>
Enter Captcha <img src="captcha.php"><input type="text" name="vercode" /> <br>
<input type="submit" name='submit' onclick="show_confirm()" value="SUBMIT" />
</form>
=============SUBMIT.PHP=================
<?php
session_start();
if ($_POST["vercode"] != $_SESSION["vercode"] OR $_SESSION["vercode"]=='')
{
//This page should not be accessed directly. Need to submit the form.
header('Location: error.html');
exit;
}
$name = $_POST['name'];
$email = $_POST['email'];
$comments = $_POST['comments'];
if(empty($name) || empty($email)||empty($comments))
{
header('Location:error.html');
exit;
}
if(!eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$", $_POST[email]))
{
header('Location:error.html');
exit;
}
$email_from = 'info#xxxxx.com';
$email_subject = "CONTACT FORM";
$email_body="============================\n".
"FULL NAME: $name\n".
"EMAIL-ID: $email\n".
"COMMENTS: $comments\n".
$to = "info2#xxxxx.com";
$headers = "From: $email_from \r\n";
mail($to,$email_subject,$email_body,$headers);
//done. redirect to thank-you page.
header('Location: thank.html');
?>
You need
session_start()
at the very top of your submit.php, that starts or resume your session so that you can access $_SESSION
You should check if the form was submitted first, then process the code. Example:
if(isset($_POST['submit'])) { // process stuff }
You didn't show what specific error you get, so I'm just going to link you to this simple PHP-GD captcha that I have used previously in some projects and works like a charm. Is really simple and easy to implement.
Simple PHP-GD captcha image
It looks like it may have something to do with your regex verification always returning false.
You may want to test if the rule you set is correct. Also, I have read on php.net that eregi() is now obsolete in 5.3.0, so maybe use preg_match() with PCRE_CASELESS flag instead ?