E-mail address validation class : Email Validation : Email PHP Source Code


PHP Source Code » Email » Email Validation »

 

E-mail address validation class


Class that may be used to determine if a given e-mail address is valid.
It features:

- Simple validation just by looking at the e-mail address string.
- Validation of a e-mail address host as a valid mail exchange domain.
- Validation of a e-mail address by connecting to the mail host server to determine if there is really a deliverable mail box.
- Works under Windows or other platforms that do not have the GetMXRR function enabled, using Moriyoshi Koizumi DNS resolver class.
<?php
/*
 * email_validation.php
 *
 * @(#) $Header: /home/mlemos/cvsroot/emailvalidation/email_validation.php,v 1.23 2005/09/16 18:20:58 mlemos Exp $
 *
 */

class email_validation_class
{
    var 
$email_regular_expression="^([-!#\$%&'*+./0-9=?A-Z^_`a-z{|}~&#127;])+@([-!#\$%&'*+/0-9=?A-Z^_`a-z{|}~&#127;]+\\.)+[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)=="\r\n")
            {
                
$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,"$line\r\n"));
    }

    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($linestrlen($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>"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);
    }
};

?>

//GetMXRR function emulation need to make the class work properly under Windows and other platforms without this function (needs DNS.php mentioned in the Related links section).


<?php
/*
 * getmxrr.php
 *
 * @(#) $Header: /home/mlemos/cvsroot/PHPlibrary/getmxrr.php,v 1.1 2002/06/21 05:33:42 mlemos Exp $
 *
 */

/* ------------------------------------------------------------------------

   PHPresolver - PHP DNS resolver library
                 Version 1.1

   Copyright (c) 2001, 2002 Moriyoshi Koizumi <koizumi@ave.sytes.net>
   All Rights Reserved.

   This library is free software; you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as published
   by the Free Software Foundation; either version 2.1 of the License, or any
   later version.

   This library is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public

   License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with this library; if not,
   write to the Free Software Foundation, Inc.,
   59 Temple Place, Suite 330, Boston, MA 02111-1307  USA

  ------------------------------------------------------------------------ */

    
if(IsSet($_NAMESERVERS)
    && (
GetType($_NAMESERVERS)!="array"
    
|| count($_NAMESERVERS)==0))
        Unset(
$_NAMESERVERS);

/***************************************************************************
 Description

  $_NAMESERVER[]

    The array that contains IP addresses or domain names of name servers
    used for DNS resolution.
    If nothing is set before require()'ing this library, the values will
    automatically prepared.

  bool getmxrr( string $hostname, arrayref $mxhosts, arrayref $weight );

    This function works in the same way as getmxrr(), however the
    third parameter cannot be omitted. If you need no MX preference
    information, please do like:


           getmxrr( 'example.com', $mxhosts, ${''} );

 -------------------------------------------------------------------------
 Configuration

  If you are doing with win32 environments and don't set $_NAMESERVER
  manually, make sure that ipconfig.exe is within the PATH.
  ipconfig.exe is generally distributed with any Microsoft(R) Windows
  distributions except for Windows 95.

 ***************************************************************************/

    
require_once( 'DNS.php' );

    
/* rewrite this path to the same as the box's configuration
       if you run scripts on *NIX platforms */
    
define'RESOLV_CONF_PATH''/etc/resolv.conf' );

    if( !isset( 
$_NAMESERVERS ) ) {
        
$_NAMESERVERS = array();
        if( 
strncmpPHP_OS"WIN") == ) {
            unset( 
$res );
            
exec'ipconfig /all'$res );
            
$cnt count$res );
            for( 
$i 0$i $cnt; ++$i ) {
                if( 
strpos$res[$i], 'DNS Servers' ) !== false ) {
                    
$_NAMESERVERS[] = substr$res[$i], strpos$res[$i], ': ' ) + );
                    break;
                }
            }
            while( 
$i<$cnt-&& strpos$res[++$i], ':' ) === false ) {
                
$_NAMESERVERS[] = trim$res[$i] );
            }
        } elseif( 
file_existsRESOLV_CONF_PATH ) ) {
            
$lines fileRESOLV_CONF_PATH );
            
$cnt count$lines );
            for( 
$i 0$i $cnt; ++$i ) {
                list( 
$dr$val ) = split'[ \t]'$lines[$i] );
                if( 
$dr == 'nameserver' ) {
                    
$_NAMESERVERS[] = rtrim$val );
                }
            }
            unset( 
$lines );
        }
    }

    if(
count($_NAMESERVERS))
        
$__PHPRESOLVER_RS = new DNSResolver$_NAMESERVERS[0] );
    else
    {
        Unset(
$_NAMESERVERS);
        Unset(
$__PHPRESOLVER_RS);
    }

    function 
GetMXRR$hostname, &$mxhosts, &$weight ) {
        global 
$__PHPRESOLVER_RS;
        if(!IsSet(
$__PHPRESOLVER_RS))
            return(
false);
        
$dnsname = & DNSName::newFromString$hostname );
        
$answer = & $__PHPRESOLVER_RS->sendQuery(
          new 
DNSQuery(
            new 
DNSRecord$dnsnameDNS_RECORDTYPE_MX )
          )
        );
        if( 
$answer === false || $answer->rec_answer === false ) {
            return 
false;
        } else {
            
$i count$answer->rec_answer );
            
$mxhosts $weight = array();
            while( --
$i >= ) {
                if( 
$answer->rec_answer[$i]->type == DNS_RECORDTYPE_MX ) {
                    
$rec = &$answer->rec_answer[$i]->specific_fields;
                    
$mxhosts[] = substr$rec['exchange']->getCanonicalName(), 0, -);
                    
$weight[] = $rec['preference'];
                }
            }
            return 
true;
        }
    }

?>



//TEST SCRIPT


<?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>





HTML code for linking to this page:

Follow Navioo On Twitter

PHP Source Code

 Navioo Email
» Email Validation