I am new to PHP so sorry if my question seems a bit noobish. I am creating a contact form which is working great but I need to validate two fields; the phone number and the email address, I need it to check that the phone number field has only numbers and is 11 digits long. The email field needs to be "something"#"something"."something".
If possible I would prefer to do it using only html or php (whichever is easiest), I guess that if there is a way to put the validation into the field properties, that would be the easiest way? eg: in here:
<input type="text" name="email" id="email" class="text" form="contact_form" required/>
If that is not possible then maybe in my PHP file which looks like so:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Submitting...</title>
</head>
<body>
<?php
$Name = $_POST ['full_name'];
$Email = $_POST['email'];
$Number = $_POST['phone_number'];
$Company = $_POST['company_name'];
$Message = $_POST['message'];
$formcontent="Name: $Name
\n Email: $Email
\n Number: $Number
\n Company: $Company
\n Message: $Message";
$recipient = "info#vicarage-support.com";
$subject = "Contact";
$mailheader = "From: $Email \r\n";
ini_set("sendmail_from","info#vicarage-support.com");
mail($recipient, $subject, $formcontent, $mailheader) or die("Please try again.");
echo("Form Submitted.");
?>
<script type="text/JavaScript">
<!--
setTimeout("location.href = 'http://www.vicarage-support.com/contact_us.html';",3000);
-->
</script>
</body>
</html>
Thank you in advance.
There are two ways to check form data before submission, i.e. client-side: using JavaScript, and using new (HTML5) HTML attributes for the input element. They can be used together if desired. Neither of them guarantees valid data; client-side checking should be regarded as convenience to the user, not as a way of ensuring data validity (which you need to check server-side, in this case in PHP code).
The HTML way can be exemplified this way:
<input type="email" name="email" id="email" class="text" form="contact_form"
required>
<input type="tel" name="tel" id="tel" class="text" form="contact_form"
required pattern="\d{11}" label="11 digits">
Using type="email" means that conforming browsers will check the email address format. This is a nontrivial task. Using type="tel" does not impose format restrictions (and the format varies by country and authority), but it may make browsers use a better user interface (such as a numeric keypad in touchscreen devices). The restriction is imposed by the pattern attribute. The value \d{11} means exactly 11 digits. (This is bad usability. I think you should allow spaces, and possibly parentheses and other characters as well, and strip them on the server. It is just too difficult to input an 11-digit number without any grouping. And 11 digits sounds arbitrary.)
There are several approaches to implementing the same in JavaScript. The pattern check is simple, whereas email format checks are very tough, and there are different library routines for it. In general, the check should be fairly permissive, basically just checking that there is an “#” character.
If you want to validate this form before it is submitted, that will have to be done with javascript. However, you should still check in your server side code, as javascript could be disabled, which would render javascript validation useless.
I've used this in the past, worked well for my needs.
http://validval.frebsite.nl/
Try adding three variables. First add a $pattern variable, then add two variables and use the switch function.
Sort of like...
<?php
$what = what you are checking (phone, email, etc)
$data = the string you want to check
function isValid( $what, $data ) {
switch( $what ) {
case 'Number':
$pattern = "/^([1]-)?[0-9]{3}-[0-9]{3}-[0-9]{4}$/i";
break;
//Change to a valid pattern, or configure it the way you want.
case 'Email':
$pattern = "/^[_a-z0-9-]+(.[_a-z0-9-]+)*#[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z]{2,3})$/i";
break;
default:
return false;
break;
This shows you what you want. Now try to validate it like...
}
return preg_match($pattern, $data) ? true : false;
}
$errors = array();
if( isset($_POST['btn_submit']) ) {
if( !isValid( 'phone', $_POST['Number'] ) ) {
$errors[] = 'Please enter a valid phone number';
}
if( !isValid( 'email', $_POST['Email'] ) ) {
$errors[] = 'Please enter a valid email address';
}
}
if( !empty($errors) ) {
foreach( $errors as $e ) echo "$e <br />";
}
?>
As you can see, this will validate your form. You may have to configure it so the $pattern is set ti what you want it to be. This may not be the best way to do so, and I reccomend Javascript, but this is how you could do it with PHP and HTML.
Related
I have a simple PHP form that I'd like to improve validation to help fight empty form submissions from bots.
I have the following array that houses input names from another page.
$expected = array('Project-Inquiry','Name','Company-Name','Phone-Number','Email');
I'd like to verify that these elements, in fact, do contain content, as they're already verified with JS on the previous page. JS is only good when it's enabled, so I'd like to add an extra layer of validation here for when it's disabled.
I tried the following:
$expected = array_filter($expected);
if (!empty($expected)) {
// Do Something
}
And I have also tried the following:
$error = false;
foreach($expected as $field) {
if (empty($_POST[$field])) {
$error = true;
}
}
if ($error) {
// Do Something
}
I seem to be falling short. Any suggestions?
If you want to fight against bots
Create a hidden input that human doesn't see and bots will fill it. You need to check that input before doing anything. If that input filled, it means that form sent by bot not human.
Create a session with current time when you are showing form, when post happening check the time difference. if it is less than 3 sec it's a bot.
use captcha system.
If you want to validate inputs
Don't do validation like what you did on your question. You should try to validate each one of them with proper validation method. for example how you should validate email is completely different from name.
for example do this for email:
$email = (isset($_POST['email']) && is_string($_POST['email']))? trim($_POST['email']) : '';
$email_error = (filter_var($email,FILTER_VALIDATE_EMAIL))? true : false;
for name is different:
$name = (isset($_POST['name']) && is_string($_POST['name']))? trim($_POST['name']) : '';
$name_error = (strlen($name)>20 || strlen($name)<3)? true : false;
You can add more filter to my examples.
Have you considered about using a library to validate?
I recommend you to use https://laravel.com/docs/5.5/validation, so you can validate more complex rules also, and it is very clear.
Let your expected data be array be
$expected = ['name', 'email', 'mobile'];
let form post values be $_POST
foreach($_POST as $key => $value) {
if (empty($value) && in_array($key, $expected)) {
if ($value=='') {
echo $key. ' is should not be empty'."<br/>";
}
}
}
you can get result as expected
HTML FORM
<form action="" method="post">
Name <input type="text" name="name"><br>
email <input type="text" name="email"><br>
mobile<input type="text" name="mobile">
<input type="submit" value="Submit">
</form>
I have this form by which a user sends me an email. I don't know if it is secured, or if issues with security appear only if sql is involved...
html:
<form id="form4" action="send_mic.php" name="form4" method="post" >
<textarea name="message4" cols="4" rows="4" id="message4" ></textarea><br />
<input type="text" id="name4" name="name4" value="" /><br />
<input type="text" id="email4" name="email4" value="" /><br />
<input type="submit" value="" id="submit" />
</form>
jquery:
<script type="text/javascript">
$(document).ready(function () {
$('#form4').ajaxForm({
beforeSubmit: validate
});
function validate(formData, jqForm, options) {
var name = $('input[name=name4]').fieldValue();
var email = $('input[name=email4]').fieldValue();
var message = $('textarea[name=message4]').fieldValue();
if (!name[0]) {
alert('Please enter a value for name');
return false;
}
if (!email[0]) {
alert('Please enter a value for email');
return false;
}
if (!message[0]) {
alert('Please enter a value for message');
return false;
}
else {
$("#content").fadeOut(1000, function () {
$(this).html("<img src='images/postauto3.png'/>").fadeIn(2000);
});
var message = $('textarea[name=message4]').val('');
var name = $('input[name=name4]').val('');
var email = $('input[name=email4]').val('');
}
}
});
</script>
php:
<?php
if($_POST){
$email = $_POST['email4'];
$name = $_POST ['name4'];
$message = $_POST ['message4'];
// response hash
$ajaxresponse = array('type'=>'', 'message4'=>'');
try {
// do some sort of data validations, very simple example below
$all_fields = array('name4', 'email4', 'message4');
foreach($all_fields as $field){
if(empty($_POST[$field])){
throw new Exception('Required field "'.ucfirst($field).'" missing input.');
}
}
// ok, if field validations are ok
// now Send Email, ect.
// let's assume everything is ok, setup successful response
$subject = "New Contact";
//get todays date
$todayis = date("l, F j, Y, g:i a") ;
$message = " $todayis \n
Attention: \n\n
Please see the message below: \n\n
Email Address: $email \n\n
Message: $message \n\n
";
$from = "From: $email\r\n";
//put your email address here
mail("contact#....ro", $subject, $message, $from);
//prep json response
$ajaxresponse['type'] = 'success';
$ajaxresponse['message'] = 'Thank You! Will be in touch soon';
} catch(Exception $e){
$ajaxresponse['type'] = 'error';
$ajaxresponse['message'] = $e->getMessage();
}
// now we are ready to turn this hash into JSON
print json_encode($ajaxresponse);
exit;
}
?>
So, are there any security problems when using forms to send emails? Is this ok?
Thanks!
In general, rule of the thumb should always be: NEVER trust user provided data. And no, your code is not bullet proof. Since you do not verify nor sanitize user input and you use mail() at the same time you are vulnerable. User can easily feed you with crafted value for email4 filed. Since you use form data directly, then email4 can be used to inject additional mail headers to your outgoing mail. It these headers would be BCC: or CC: or even TO: then then you would be simply acting as spam relay. For example if I post this
some#address.com
CC: spamvictim1#foo.com, spamvictim2#foo.com, spamvictim3#foo.com,
X-Spam-Owned: Whoa
as your email4 then your header would end looking like this:
To: some#address.com
CC: spamvictim1#foo.com, spamvictim2#foo.com, spamvictim3#foo.com,
X-Spam-Owned: Whoa
to post multiline data you simply glue texts with CRLFs.
To avoid security holes like this you should consider dropping mail() and use something more clever that would take care of something like this too (not that mail() is bad, but you need to know what you are doing as it is rather low than high level function). I suggest using PHPMailer or similar package. You should always verify user provided data (especially ensure that single-line fields, like subject are really single line - stripping CRLFs suffice). Add captcha as you are open to automated form submission.
You could add a captcha to prevent spam.
You could protect against email injections by using:
filter_var($email, FILTER_VALIDATE_EMAIL)
I think this form is safe, mean that no one can really h#ck your website throught this form.
But you need to add somethings for better result:
1. You should also check the post variable in php server side, mean that you should check if email / name / message is valid of not
2. You should add some captcha to prevent spam
You can additionally wrap your server side code with
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
/* special ajax here */
die($content);
}
This will ensure the ajax request is coming on the server.
And please mind your ID that you are using in one of your jQuery selector in your question.
Even if you are not working with database, there could be security problems in email sending. Of course you can't be hacked by this form, but the problems will occure when the user will input something like this in EMail field:
email-address1#example.com // there is a new line here
CC:email-address2#example.com,email-addresses3#example.com,.............................email-addressesn#example.com
so the best you can do is sanitizing all the input fields for mail function, to prevent such spam delivery. And as #WebnetMobile.com has already sad, never trust user inputs
I don't see a security issue in there, since you are not modifying anything on your server side. Might be an issue with spam though. Add some captcha to it. The rest looks ok.
You should add captcha , client side and server side validation in form
I'm trying to work out how to go about checking a text area to see if it contains a certain phrase.
I believe I could maybe use .indexOf?
It's just I have a validation script to check the contents of a contact form. Lately I have been receiving a fair bit of spam through. I have noticed that all these spam messages contain the phrase [url= and I thought, if I could perhaps add a small script to check if the text area contained such a phrase and, if so, stop the message being sent.
At present I have this simple snippet of javascript to check whether the text area is blank:
if (message.val()=='') {
message.addClass('highlight');
message.focus();
return false;
} else message.removeClass('highlight');
Any good ways to add something to check if the message field contains [url=
I also have a similar php validation script:
if (!$message) $errors[count($errors)] = 'Please click back and enter your message.';
Any ideas how I could add a similar validation script to check if message contains [url= in php too?
Any help would be greatly appreciated! :o)
It's unlikely that you'll stop spam by checking the contents of your textarea at the client side:- the spammer is more than likely POSTing directly to your server side script, so you'll need to do your filtering there. Also checking for a particular pattern will only work until the pattern changes and then you'll have to update your script.
A common solution to this problem is the use of a One-Time Form Token.
When you serve the form you generate a random string of characters and place that token in a hidden field in the form. You also store the token on the server in a session or in a database. When the form is submitted you match the stored and submitted tokens. This way you can be more sure that the form itself was filled in and submitted and that you aren't receiving data from a bot.
For extra security you can only allow each token to be used once only, guarding against multiple submissions.
UPDATE
A very simple, one page example
<?php
session_start();
/**
* Process the form if we have a token that we recognise
* otherwise just present the form again, you probably want to handle this a bit better
*/
if( isset( $_POST['token'] ) && isset( $_SESSION['token'] )
&& $_POST['token'] === $_SESSION['token'] ) {
// no more submissions using this token
unset( $_SESSION['token'] );
$name = clean( $_POST['name'] );
$comment = clean( $_POST['comment'] );
// process the input and redirect to a confirmation
// just echoing data for example
echo "$name said $comment";
die();
} else {
$token = uniqid();
$_SESSION['token'] = $token;
}
/**
* Stub function that cleans user input
* #param String $str
*/
function clean( $str ) {
return $str;
}
?>
<html>
<head>
<title>Form token example</title>
</head>
<body>
<form method="post">
<label>
Name<br/>
<input type="text" name="name"/>
</label>
<br/>
<label>
Comment<br/>
<textarea name="comment"></textarea>
</label>
<br/>
<label>
<input type="submit"/>
</label>
<br/>
<br/>
The token field would normally be hidden, it's displayed here so that the user can change it for testing<br/>
<input type="text" name="token" value="<?php echo $token ?>"/><br/>
</form>
</body>
</html>
check out the javascript search method and javascript match method. I prefer search becuase if you only care if it does exist then you do something like this.
var stringToSearch = "stackoverflow";
if (stringToSearch.search("over") >= 0){
//exists
}
By the way your question didn't do something right. I don't know php so i can't help you there
message.val().match('your phrase here')
Is there a good method of form security that does not involve CAPTCHA? CAPTCHA is so annoying, but I need security because I am getting form spam. My form is PHP.
Here's what I've found to be very effective (and dead simple):
Put a hidden field on your form. Give it a name like "phone" or something similar/common and put in a default junk value.
Put another regular text input field on your form, but hide it with CSS. Make that one empty. Again, give it a "real" sounding name (first_name, phone_number, whatever).
When the form is posted, verify that the hidden field still has the default value and the field you hid with CSS is still empty.
You're basicly taking advantage of the fact that most spam bots will simply fill in every field in the form in order to avoid failing any required field validation checks. Some might be smart enough to ignore hidden fields, but I've never seen one that was smart enough to ignore fields hidden with CSS.
ETA:
To address some comments - Is this a truly "secure" system? no, it certainly isn't. It would be trivially broken by anybody who wanted to specifically target your site. That said, it is still remarkably effective against the automated form spamming bots that most "low value" sites will see.
If you want to stop a determined attacker, you'll need something a bit more invasive. Another poster mentioned Akismet, which is a good option. Re-Captcha would be another. Stopping determined, targeted spammers is hard though. Even Yahoo and Google have a hard time with it.
Try akismet. It's great at flagging spam. The API is easy to use and completely transparent to your users.
This kind of validator is cute and quick!
Obviously, you will want to display one of a many possible animal images, and the list should be randomized as well.
I understand it will only work X% of the time, but adding more options to the list will help reduce spam.
I have already worked something similar.
When you open a form generate one md5() string and put it in session (for example $_SESSION['captha'])
Your form sould have one hidden field and when you open this form write this data from $_SESSION['captha'] into this hidden field
When you receive this post request compare value in session and value which come with this hidden field. If it is same everithing is ok and vice versa. Of course, after you handle this request just delete variable $_SESSION['captha'].
This work for me.
If all you are doing is avoiding spam bots (automated programs that seek <form> tags, fill in all <input> fields, then submit the form), then a simple solution is to do as Paolo said: use JavaScript to add a hidden field. The disadvantage is for people who disable JavaScript.
Feel free to use this:
<form method="post" action="contact.php" id="commentForm">
<label for="name">Name</label>
<input type="text" name="name" id="name" maxlength="64" /><br />
<label for="email">Email</label>
<input type="text" name="email" id="email" maxlength="320" /><br />
<label for="message">Message</label>
<textarea name="message" rows="10" cols="40" id="Message"></textarea><br />
<label for="human">40 + 2 =</label>
<input type="text" name="human" id="human" size="10" maxlength="3" /><br />
<p align="center">
<input type="submit" name="submit" value="Send" class="submit-button" />
</p>
</form>
Then place the following as "contact.php" in the same directory:
<?php
require_once 'lib/swift_required.php';
// Reason for not contacting.
//
$reason = 'default';
error_reporting( 0 );
ini_set( 'display_errors', 0 );
function not_contacted() {
global $reason;
header( 'Location: error.html' );
}
function wms_error_handler($errno, $errstr, $errfile, $errline) {
not_contacted();
return true;
}
function wms_shutdown() {
if( is_null( $e = error_get_last() ) === false ) {
not_contacted();
}
}
set_error_handler( "wms_error_handler" );
register_shutdown_function( 'wms_shutdown' );
$name = trim( $_POST["name"] );
$email = trim( $_POST["email"] );
$message = trim( $_POST["message"] );
$human = trim( $_POST["human"] );
$subject = 'FormSpam';
$contacted = false;
if( is_null( $name ) || empty( $name ) ) {
$reason = 'name';
$human = false;
}
else if( is_null( $email ) || empty( $email ) ) {
$reason = 'email';
$human = false;
}
else if( is_null( $message ) || empty( $message ) ) {
$reason = 'message';
$human = false;
}
else if( is_null( $human ) || empty( $human ) || $human !== '42' ) {
$reason = 'computer';
$human = false;
}
if( $human === '42' ) {
$subject = 'YourCustomSubject - '.$name;
$transport = Swift_SmtpTransport::newInstance( 'localhost', 25 );
$mailer = Swift_Mailer::newInstance( $transport );
$message = stripslashes( $message );
$message = Swift_Message::newInstance()
->setSubject( $subject )
->setFrom( array( $email => $name ) )
->setTo( array( 'YourEmailAddress' => 'Your Name' ) )
->setPriority( 1 )
->setBody( $message )
;
if( $mailer->send( $message ) ) {
header( 'Location: contacted.html' );
$contacted = true;
}
}
if( $contacted === false ) {
not_contacted();
}
?>
Should prevent 99% of spam.
I have not added constants, but I'm sure you can figure out where to change the script. I've removed the part where it redirects to different pages depending on what was (or was not) entered by the user (e.g., missing full name, e-mail address, message, and such). If you want a full version of the script, let me know and I'll fix the code to be more new-developer-friendly.
Note the Swift Mailer dependency.
Yes, I invented and developed a method many years ago called nocaptcha.
I tested employed it in my sites for a year then noticed google also using it.
I released it for Joomla (see
http://shop.ekerner.com/index.php/shop/joomla-nocaptcha-detail )
and since it has been copied by many platforms (see https://www.google.com.au/search?q=nocaptcha ).
I believe the git hosted version via the above link can be deployed to any site, and if you cant find a version for your site then perhaps ask my dev team for a custom solution (see: http://www.ekerner.com/ ).
Math questions are interesting alternative. You can even write your own simple math checker by using random numbers.
Here are couple of plugins:
http://www.codegravity.com/projects/mathguard
http://sw-guide.de/wordpress/plugins/math-comment-spam-protection/
Depends on the type of form spam, general bots made for spamming any form it finds can easily be foiled by a lot less obstructive measures (like "what is the name of this site?"), but if someone has made a bot targeting your site specifically you will need captchas or something equally annoying.
If cutting down spam is the immediate need, putting the form in an iframe has been effective for me.
<iframe src="contactform.php" scrolling="no" height="*" width="*"></iframe>
Set the frame's height and width a little bigger than your form's width and height. Use CSS to make the frame border 0 so users won't notice they're looking at the form within frame.
I have a simple PHP mailer script that takes values from a form submitted via POST and mails them to me:
<?php
$to = "me#example.com";
$name = $_POST['name'];
$message = $_POST['message'];
$email = $_POST['email'];
$body = "Person $name submitted a message: $message";
$subject = "A message has been submitted";
$headers = 'From: ' . $email;
mail($to, $subject, $body, $headers);
header("Location: http://example.com/thanks");
?>
How can I sanitize the input?
Sanitize the post variable with filter_var().
Example here. Like:
echo filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
Since you're not building an SQL query or anything here, the only relevant validation that I can see for those inputs is an email validation for $_POST["email"], and maybe an alphanumeric filter on the other fields if you really want to limit the scope of what the message can contain.
To filter the email address, simply use filter_var:
$email = filter_var($email, FILTER_SANITIZE_EMAIL);
As per Frank Farmer's suggestion, you can also filter out newlines in the email subject:
$subject = str_replace(array("\r","\n"),array(" "," "),$subject);
As others have noted, filter_var is great. If it's not available, add this to your toolchest.
The $headers variable is particularly bad security-wise. It can be appended to and cause spoofed headers to be added. This post called Email Injection discusses it pretty well.
filter_var is great, but another way to assure that something is an email address and not something bad is to use an isMail() function. Here's one:
function isEmail($email) {
return preg_match('|^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]{2,})+$|i', $email);
};
So to use this, you could do:
if (isset($_POST['email']) && isEmail($_POST['email'])) {
$email = $_POST['email'] ;
} else {
// you could halt execution here, set $email to a default email address
// display an error, redirect, or some combination here,
}
In terms of manual validation, limiting the length using substr(), running strip_tags() and otherwise limiting what can be put in.
You need to remove any newlines from input provided by users in $headers, which gets passed to mail() ($email in your case)! See Email injection.
PHP should take care of sanitizing $to and $subject, but there are versions of PHP with bugs (Affected are PHP 4 <= 4.4.6 and PHP 5 <= 5.2.1, see MOPB-34-2007).
You can use the code from artlung's answer above to validate email..
I use this kind of code to prevent header injection ..
// define some mail() header's parts and commonly used spam code to filter using preg_match
$match = "/(from\:|to\:|bcc\:|cc\:|content\-type\:|mime\-version\:|subject\:|x\-mailer\:|reply\-to\:|\%0a|\%0b)/i";
// check if any field's value containing the one or more of the code above
if (preg_match($match, $name) || preg_match( $match, $message) || preg_match( $match, $email)) {
// I use ajax, so I call the string below and send it to js file to check whether the email is failed to send or not
echo "failed";
// If you are not using ajax, then you can redirect it with php header function i.e: header("Location: http://example.com/anypage/");
// stop the script before it reach or executing the mail function
die();
}
The mail()'s header filtering above is too strict, since some users may be using the filtered strings in their message without any intention to hijack your email form, so redirect it to a page that is explaining what kind of strings that is not allowed in the form or explain it on your form page.