New to PHP, help with verifying email text field please
Hi everyone, I'm having problems with a free contact form script I found online.
I have some knowledge about code in general, however I'm new to PHP and after a few hours trying to solve the issue I decided to post here asking for help.
The contact script works fine, however it doesn't seem to detect when the e-mail field is left blank and sends the e-mail anyways.
It also sends the e-mail if the e-mail filed is clearly fake (a.k.a. a@b.com), though I'm not sure weather there is a quick fix for that, so the main issue here is fixing the code so to have it return an error if the e-mail field is left blank.
the section of the script about validating the email field (should the script be needed in full please ask and I'll provide it, I just thought I'd keep it short):
Code:
// Validate email field.
if(isset($_REQUEST['email']) && !empty($_REQUEST['email']))
{
if(preg_match("/(%0A|%0D|\n+|\r+|:)/i",$_REQUEST['email'])){$errors[] = "Email address may not contain a new line or a colon";}
$_REQUEST['email'] = trim($_REQUEST['email']);
if(substr_count($_REQUEST['email'],"@") != 1 || stristr($_REQUEST['email']," ")){$errors[] = "Email address is invalid";}
else{$exploded_email = explode("@",$_REQUEST['email']);
if(empty($exploded_email[0]) || strlen($exploded_email[0]) > 64 || empty($exploded_email[1])){$errors[] = "Email address is invalid";}
else{if(substr_count($exploded_email[1],".") == 0){$errors[] = "Email address is invalid";}else{$exploded_domain = explode(".",$exploded_email[1]);
if(in_array("",$exploded_domain)){$errors[] = "Email address is invalid";}
else{foreach($exploded_domain as $value){if(strlen($value) > 63 || !preg_match('/^[a-z0-9-]+$/i',$value)){$errors[] = "Email address is invalid"; break;}}}}}}
}
Adittionally, here's the code on the actual page displaying the contact form:
you could incorporate this function into your script
PHP Code:
function check_valid_email($email){
$isValid = true;
$atIndex = strrpos($email, "@");
if (is_bool($atIndex) && !$atIndex){
$isValid = false;
}else{
$domain = substr($email, $atIndex+1);
$local = substr($email, 0, $atIndex);
$localLen = strlen($local);
$domainLen = strlen($domain);
if ($localLen < 1 || $localLen > 64) {
// local part length exceeded
$isValid = false;
}else if ($domainLen < 1 || $domainLen > 255){
// domain part length exceeded
$isValid = false;
}else if ($local[0] == '.' || $local[$localLen-1] == '.'){
// local part starts or ends with '.'
$isValid = false;
}else if (preg_match('/\\.\\./', $local)){
// local part has two consecutive dots
$isValid = false;
}else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain)){
// character not valid in domain part
$isValid = false;
}else if (preg_match('/\\.\\./', $domain)){
// domain part has two consecutive dots
$isValid = false;
}else if (!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/',str_replace("\\\\","",$local))){
// character not valid in local part unless
// local part is quoted
if (!preg_match('/^"(\\\\"|[^"])+"$/',str_replace("\\\\","",$local))){
$isValid = false;
}
}
if ($isValid && !(checkdnsrr($domain,"MX") || checkdnsrr($domain,"A"))){
// domain not found in DNS
$isValid = false;
}
}
return $isValid;
}
it's a fairly exhaustive check that also does a dns lookup to check it's on a valid domain...
hmm.. not sure I agree with felgall.. but hey we are all allowed opinions right?
I tried to test the filter_var option just now alongside the email verification function I listed earlier, on my local machine against a couple thousand email addresses I have and straight away got the error:
Fatal error: Call to undefined function filter_var() in xxxx
It seems php has to be compiled with specific PECL extension to use filter_var so straight away that makes it harder for me to use anyway...
Anyway, I tidied up the verification function and added an option to bypass the dns checking...
PHP Code:
// Validate an email address with dns lookup function check_is_valid_email($email,$chkdns=true){ $isValid = true; $atIndex = strrpos($email, "@"); if (is_bool($atIndex) && !$atIndex){ $isValid = false; }else{ $domain = substr($email, $atIndex+1); $local = substr($email, 0, $atIndex); $localLen = strlen($local); $domainLen = strlen($domain); if ($localLen < 1 || $localLen > 64) { // local part length exceeded $isValid = false; }else if ($domainLen < 1 || $domainLen > 255){ // domain part length exceeded $isValid = false; }else if ($local[0] == '.' || $local[$localLen-1] == '.'){ // local part starts or ends with '.' $isValid = false; }else if (preg_match('/\\.\\./', $local)){ // local part has two consecutive dots $isValid = false; }else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain)){ // character not valid in domain part $isValid = false; }else if (preg_match('/\\.\\./', $domain)){ // domain part has two consecutive dots $isValid = false; }else if (!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/',str_replace("\\\\","",$local))){ // character not valid in local part unless // local part is quoted if (!preg_match('/^"(\\\\"|[^"])+"$/',str_replace("\\\\","",$local))){ $isValid = false; } } if($chkdns){ if ($isValid && !(checkdnsrr($domain,"MX") || checkdnsrr($domain,"A"))){ // domain not found in DNS $isValid = false; } } } return $isValid; }
when tested on 2000 email addresses in my db it showed no false positives, it picked out only invalid email addresses... works for me
thanks fellgal, I'll give a go to that one too should I fail miserably at implementing jmj001's suggestion
jmj001, i'm trying to figure out the implementation of the function you suggested and I have one question (baring in mind I speak using my C++ knowledge, so I might be talking rubbish...).
So I've added your function to my php, now I need to make a call to it feeding in the parameters to allow the check to happen, problem I have is:
what should I feed as second variable while calling the function?
This is how my call looks now, as you can see I don't have a second parameter to feed to it (not even sure that the one I fed as first parameter would actually feed it the content of the field "email" from the form in all honesty):
Code:
if (check_is_valid_email($_REQUEST['email'],something)){
any suggestion?
am I doing it totally wrong?
Thanks
the second argument can be left blank.. set it to false if you want to bypass dnschecking
so you could use it like...
PHP Code:
// WITHOUT dns checking if(check_is_valid_email($_REQUEST['email'],false)){ // do whatever you do for a valid email here }else{ // do what you do for a failed email here }
PHP Code:
// WITH dns checking if(check_is_valid_email($_REQUEST['email'])){ // do whatever you do for a valid email here }else{ // do what you do for a failed email here }
yeh.. it seems checkdnsrr is not available on a windows server but it should be included in a linux distro, if it's not on your server you could just leave the dnscheck as false..
checkdnsrr is a built in php library function but it needs to be compiled in with php to work...
no probs.. actually i think you may have read my last post before i edited it.. it seems checkdnsrr is not available on a windows server and i'm guessing you're running this on a windows machine..