Complete and thorough php email validation and php email verification can be found at PHPClasses.org: Email Validation:
<<This is a PHP class that attempts to validate a given e-mail address at three levels: matching the address against a RFC compliant regular expression, verifing the existence of the destination SMTP server by verifying the respective DNS MX record, and connecting to that server to see if the given address is accepted as a valid recipient. The class also features a debugging output option that lets you see the remote SMTP server connection and data exchange dialog to see the real cause why an apparently valid address may not be accepting messages>>
Here is the code for the class:
<?php
/*
* email_validation.php
*
* @(#) $Header: /home/mlemos/cvsroot/emailvalidation/email_validation.php,v 1.24 2008/12/28 07:29:35 mlemos Exp $
*
*/
class email_validation_class
{
var $email_regular_expression="^([-!#$%&'*+./0-9=?A-Z^_`a-z{|}~])+@([-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+\.)+[a-zA-Z]{2,6}$";
var $timeout=0;
var $data_timeout=0;
var $localhost="";
var $localuser="";
var $debug=0;
var $html_debug=0;
var $exclude_address="";
var $getmxrr="GetMXRR";
var $next_token="";
var $preg;
var $last_code="";
Function Tokenize($string,$separator="")
{
if(!strcmp($separator,""))
{
$separator=$string;
$string=$this->next_token;
}
for($character=0;$character<strlen($separator);$character++)
{
if(GetType($position=strpos($string,$separator[$character]))=="integer")
$found=(IsSet($found) ? min($found,$position) : $position);
}
if(IsSet($found))
{
$this->next_token=substr($string,$found+1);
return(substr($string,0,$found));
}
else
{
$this->next_token="";
return($string);
}
}
Function OutputDebug($message)
{
$message.="n";
if($this->html_debug)
$message=str_replace("n","<br />n",HtmlEntities($message));
echo $message;
flush();
}
Function GetLine($connection)
{
for($line="";;)
{
if(@feof($connection))
return(0);
$line.=@fgets($connection,100);
$length=strlen($line);
if($length>=2
&& substr($line,$length-2,2)=="rn")
{
$line=substr($line,0,$length-2);
if($this->debug)
$this->OutputDebug("S $line");
return($line);
}
}
}
Function PutLine($connection,$line)
{
if($this->debug)
$this->OutputDebug("C $line");
return(@fputs($connection,"$linern"));
}
Function ValidateEmailAddress($email)
{
if(IsSet($this->preg))
{
if(strlen($this->preg))
return(preg_match($this->preg,$email));
}
else
{
$this->preg=(function_exists("preg_match") ? "/".str_replace("/", "\/", $this->email_regular_expression)."/" : "");
return($this->ValidateEmailAddress($email));
}
return(eregi($this->email_regular_expression,$email)!=0);
}
Function ValidateEmailHost($email,&$hosts)
{
if(!$this->ValidateEmailAddress($email))
return(0);
$user=$this->Tokenize($email,"@");
$domain=$this->Tokenize("");
$hosts=$weights=array();
$getmxrr=$this->getmxrr;
if(function_exists($getmxrr)
&& $getmxrr($domain,$hosts,$weights))
{
$mxhosts=array();
for($host=0;$host<count($hosts);$host++)
$mxhosts[$weights[$host]]=$hosts[$host];
KSort($mxhosts);
for(Reset($mxhosts),$host=0;$host<count($mxhosts);Next($mxhosts),$host++)
$hosts[$host]=$mxhosts[Key($mxhosts)];
}
else
{
if(strcmp($ip=@gethostbyname($domain),$domain)
&& (strlen($this->exclude_address)==0
|| strcmp(@gethostbyname($this->exclude_address),$ip)))
$hosts[]=$domain;
}
return(count($hosts)!=0);
}
Function VerifyResultLines($connection,$code)
{
while(($line=$this->GetLine($connection)))
{
$this->last_code=$this->Tokenize($line," -");
if(strcmp($this->last_code,$code))
return(0);
if(!strcmp(substr($line, strlen($this->last_code), 1)," "))
return(1);
}
return(-1);
}
Function ValidateEmailBox($email)
{
if(!$this->ValidateEmailHost($email,$hosts))
return(0);
if(!strcmp($localhost=$this->localhost,"")
&& !strcmp($localhost=getenv("SERVER_NAME"),"")
&& !strcmp($localhost=getenv("HOST"),""))
$localhost="localhost";
if(!strcmp($localuser=$this->localuser,"")
&& !strcmp($localuser=getenv("USERNAME"),"")
&& !strcmp($localuser=getenv("USER"),""))
$localuser="root";
for($host=0;$host<count($hosts);$host++)
{
$domain=$hosts[$host];
if(ereg('^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$',$domain))
$ip=$domain;
else
{
if($this->debug)
$this->OutputDebug("Resolving host name "".$hosts[$host].""...");
if(!strcmp($ip=@gethostbyname($domain),$domain))
{
if($this->debug)
$this->OutputDebug("Could not resolve host name "".$hosts[$host]."".");
continue;
}
}
if(strlen($this->exclude_address)
&& !strcmp(@gethostbyname($this->exclude_address),$ip))
{
if($this->debug)
$this->OutputDebug("Host address of "".$hosts[$host]."" is the exclude address");
continue;
}
if($this->debug)
$this->OutputDebug("Connecting to host address "".$ip.""...");
if(($connection=($this->timeout ? @fsockopen($ip,25,$errno,$error,$this->timeout) : @fsockopen($ip,25))))
{
$timeout=($this->data_timeout ? $this->data_timeout : $this->timeout);
if($timeout
&& function_exists("socket_set_timeout"))
socket_set_timeout($connection,$timeout,0);
if($this->debug)
$this->OutputDebug("Connected.");
if($this->VerifyResultLines($connection,"220")>0
&& $this->PutLine($connection,"HELO $localhost")
&& $this->VerifyResultLines($connection,"250")>0
&& $this->PutLine($connection,"MAIL FROM: <$localuser@$localhost>")
&& $this->VerifyResultLines($connection,"250")>0
&& $this->PutLine($connection,"RCPT TO: <$email>")
&& ($result=$this->VerifyResultLines($connection,"250"))>=0)
{
if($result)
{
if($this->PutLine($connection,"DATA"))
$result=($this->VerifyResultLines($connection,"354")!=0);
}
else
{
if(strlen($this->last_code)
&& !strcmp($this->last_code[0],"4"))
$result=-1;
}
if($this->debug)
$this->OutputDebug("This host states that the address is ".($result ? ($result>0 ? "valid" : "undetermined") : "not valid").".");
@fclose($connection);
if($this->debug)
$this->OutputDebug("Disconnected.");
return($result);
}
if($this->debug)
$this->OutputDebug("Unable to validate the address with this host.");
@fclose($connection);
if($this->debug)
$this->OutputDebug("Disconnected.");
}
else
{
if($this->debug)
$this->OutputDebug("Failed.");
}
}
return(-1);
}
};
?>
Here is the test code for implementing the class:
<?php
/*
* test_email_validation.html
*
* @(#) $Header: /home/mlemos/cvsroot/emailvalidation/test_email_validation.php,v 1.11 2003/12/12 15:25:52 mlemos Exp $
*
*/
?><HTML>
<HEAD>
<TITLE>Test for Manuel Lemos's PHP E-mail validation class</TITLE>
</HEAD>
<BODY>
<H1><CENTER>Test for Manuel Lemos's PHP E-mail validation class</CENTER></H1>
<HR>
<?php
require("email_validation.php");
$validator=new email_validation_class;
/*
* If you are running under Windows or any other platform that does not
* have enabled the MX resolution function GetMXRR() , you need to
* include code that emulates that function so the class knows which
* SMTP server it should connect to verify if the specified address is
* valid.
*/
if(!function_exists("GetMXRR"))
{
/*
* If possible specify in this array the address of at least on local
* DNS that may be queried from your network.
*/
$_NAMESERVERS=array();
include("getmxrr.php");
}
/*
* If GetMXRR function is available but it is not functional, you may
* use a replacement function.
*/
/*
else
{
$_NAMESERVERS=array();
if(count($_NAMESERVERS)==0)
Unset($_NAMESERVERS);
include("rrcompat.php");
$validator->getmxrr="_getmxrr";
}
*/
/* how many seconds to wait before each attempt to connect to the
destination e-mail server */
$validator->timeout=10;
/* how many seconds to wait for data exchanged with the server.
set to a non zero value if the data timeout will be different
than the connection timeout. */
$validator->data_timeout=0;
/* user part of the e-mail address of the sending user
(info@phpclasses.org in this example) */
$validator->localuser="info";
/* domain part of the e-mail address of the sending user */
$validator->localhost="phpclasses.org";
/* Set to 1 if you want to output of the dialog with the
destination mail server */
$validator->debug=1;
/* Set to 1 if you want the debug output to be formatted to be
displayed properly in a HTML page. */
$validator->html_debug=1;
/* When it is not possible to resolve the e-mail address of
destination server (MX record) eventually because the domain is
invalid, this class tries to resolve the domain address (A
record). If it fails, usually the resolver library assumes that
could be because the specified domain is just the subdomain
part. So, it appends the local default domain and tries to
resolve the resulting domain. It may happen that the local DNS
has an * for the A record, so any sub-domain is resolved to some
local IP address. This prevents the class from figuring if the
specified e-mail address domain is valid. To avoid this problem,
just specify in this variable the local address that the
resolver library would return with gethostbyname() function for
invalid global domains that would be confused with valid local
domains. Here it can be either the domain name or its IP address. */
$validator->exclude_address="";
if(IsSet($_GET["email"]))
$email=$_GET["email"];
if(IsSet($email)
&& strcmp($email,""))
{
if(($result=$validator->ValidateEmailBox($email))<0)
echo "<H2><CENTER>It was not possible to determine if <TT>$email</TT> is a valid deliverable e-mail box address.</CENTER></H2>n";
else
echo "<H2><CENTER><TT>$email</TT> is ".($result ? "" : "not ")."a valid deliverable e-mail box address.</CENTER></H2>n";
}
else
{
$port=(strcmp($port=getenv("SERVER_PORT"),"") ? intval($port) : 80);
$site="http://".(strcmp($site=getenv("SERVER_NAME"),"") ? $site : "localhost").($port==80 ? "" : ":".$port).GetEnv("REQUEST_URI");
echo "<H2>Access this page using a URL like: $site?email=<A HREF="$site?email=mlemos@acm.org"><TT>your@test.email.here</TT></A></H2>n";
}
?>
<HR>
</BODY>
</HTML>
