Jump to content
xisto Community
Sign in to follow this  
sonesay

Php Email Validation A PHP data validation class with many functions

Recommended Posts

I've been reading through my old php book (PHP 4.1) and came across this data validation class. It can check a number of things ranging from telephone numbers , credit card number formats, email address and some others. I checked out some of the methods although I didnt expect it to work 100% because I've found source code errors thoughout the book and CD. I tested out a few of the methods to check and some of them did return expected results but some didnt either so the data validation class was not perfect and it didnt really bother me. The cool thing I found in the class was a method to validate an email address by contacting the server and asking the server if they were serving that particular email address. So far that seems like the best method to validate an email address before inserting it into your database. Well it turns out unlike some of the other methods that seem to work or just fail this one actually crashes apache so everytime it runs it will somehow make apache hang. I dont know why thats why I'm going to post it here and see if anyone can figure out why.Heres the full class code. the 'email_works' method is the very last one in the class.

<?phpdefine ('DV_ERR_UNKNOWN', 0);define ('DV_ERR_TEL_TOO_SHORT', 1);define ('DV_ERR_TEL_TOO_LONG', 2);define ('DV_ERR_TEL_ILLEGAL_CHARS', 3);class DV {    var $errtype;    var $errstr;    function DV ()    {        $this->errtype = FALSE;        $this->errstr  = '';    }    /*     * method: is_us_tel ($tel)     * args: $tel (value to test)     *     * Tests $tel to see if it looks like a U.S. telephone number (ten digits     * including area code). We ignore any parentheses, dashes, dots or spaces.     */    function is_us_tel ($tel)    {        // replace parentheses, dashes, dots or spaces with ''        $new_tel = ereg_replace ("[\(\)\. -]", "", $tel);        $l = strlen ($new_tel);        if ($l < 10)        {            $this->errtype = DV_ERR_TEL_TOO_SHORT;            $this->errstr = "Telephone numbers must have 10 digits. ('$tel' " .                             "contains $l digits.)";            return false;        }        if ($l > 10)        {            $this->errtype = DV_ERR_TEL_TOO_LONG;            $this->errstr = "Telephone numbers must have 10 digits. ('$tel' " .                             "contains $l digits.)";            return false;        }        // make sure there are only digits left        if (ereg ("[^0-9]", $new_tel))        {            $this->errtype = DV_ERR_TEL_ILLEGAL_CHARS;            $this->errstr = "'$tel' is not valid. Telephone numbers may " .                             "only contain digits, parentheses and dashes.";            return false;        }        return true;    }    /*     * method: is_us_zip ($zip)     * args: $zip (value to test)     *     * Tests $zip to see if it looks like a U.S. zip code (five digits).     */    function is_us_zip ($zip)    {        // match exactly five digits        if (!ereg ("^[0-9]{5}$", $zip))            return false;        return true;    }    /*     * method: is_us_zip_plus_four ($zip)     * args: $zip (value to test)     *     * Tests $zip to see if it looks like a U.S. zip+4 (five digits followed by     * a dash followed by four digits).     */    function is_us_zip_plus_four ($zip) {        // match exactly five digits followed by dash followed by four digits        if (!ereg ("^[0-9]{5}-[0-9][{4}$", $zip))            return false;        return true;    }    /*     * method: is_valid_cc_num ($num, $type)     * args: $num (credit card number to test)     *       $type (type of card)     *     * Checks validity of Visa, Discover, Mastercard, AmEx credit card numbers.     * First arg is the credit card number, second is card type. Card type may be     * one of 'visa', 'discover', 'mastercard', 'amex'.  Uses hard-coded knowledge     * about card numbers (e.g., all Visa card numbers start with 4) and mod10     * algorithm to check validity.     *     * Note that the $num argument must be a string, not a float or integer.     */    function is_valid_cc_num ($num, $type) {        $ndigits = strlen ((string) $num);        switch ($type) {            case ('visa'):                // must begin w/ '4' and be 13 or 16 digits long                if (substr ($num, 0, 1) != '4')                    return false;                if (!(($ndigits == 13) || ($ndigits == 16)))                    return false;                break;            case ('discover'):                // must begin w/ '6011' and be 16 digits long                if (substr ($num, 0, 4) != '6011')                    return false;                if ($ndigits != 16)                    return false;                break;            case ('mastercard'):                // must begin w/ two-digit num between 51 and 55                // and be 16 digits long                if (intval (substr ($num, 0, 2)) < 51)                    return false;                if (intval (substr ($num, 0, 2)) > 55)                    return false;                if ($ndigits != 16)                    return false;                break;            case ('amex'):                // must begin w/ '34' or '37' and be 15 digits long                if (!((susbtr ($num, 0, 2) == '34') ||                      (substr ($num, 0, 2) == '37')))                    return false;                if ($ndigits != 15)                    return false;                break;            default:                return false;        }        // compute checksum using mod10 algorithm        $checksum = 0;        $curpos = $ndigits - 2;        while ($curpos >= 0) {            $double = intval (substr ($num, $curpos, 1)) * 2;            for ($i = 0; $i < strlen ($double); $i++)                $checksum += intval (substr ($double, $i, 1));            $curpos = $curpos - 2;        }        $curpos = $ndigits - 1;        while ($curpos >= 0) {            $checksum += intval (substr ($num, $curpos, 1));            $curpos = $curpos - 2;        }        // see if checksum is valid (must be multiple of 10)        if (($checksum % 10) != 0)            return false;        return true;    }    /*     * method: is_email ($email)     * args: $email (value to test)     *     * Tests $email to see if it looks like an e-mail address. This only works     * for 'simple' email addresses in the format 'user@example.com'.     */    function is_email ($email)    {        $tmp = split ("@", $email);        if (count ($tmp) < 1)            return false;        if (count ($tmp) > 2)            return false;        $username = $tmp[0];        $hostname = $tmp[1];                // make sure $username contains at least one of the following:        //     letter digit _ + - .        if (!eregi ("^[a-z0-9_\+\.\-]+$", $username))            return false;        // make sure $hostname is valid (see is_hostname() below)        if (!$this->is_hostname ($hostname))            return false;        return true;    }    /*     * method: is_hostname ($host)     * args: $host (value to test)     *     * Tests $host to see if it looks like a valid Internet hostname.     */    function is_hostname ($host)    {        // make sure $h: starts with a letter or digit; contains at least        // one dot; only contains letters, digits, hypehns and dots; and        // ends with a TLD that is a) at least 2 characters and  only        // contains letters        if ( !eregi ("^[a-z0-9]{1}[a-z0-9\.\-]*\.[a-z]{2,}$", $host))            return false;        // make sure the hostname doesn't contain any nonsense sequences        // involving adjacent dots/dashes        if (ereg ("\.\.", $host) || ereg ("\.-", $host) || ereg ("-\.", $host))            return false;        return true;    }    /*     * method: is_email_rfc822 ($email)     * args: $email (address to validate)     *     * We pass $mail off to imap_rfc822_parse_adrlist() and check to see whether a)     * it returned a 1-element array as expected and  if it did, whether any     * errors were caught by imap_rfc822_parse_adrlist() during checking.     */        function is_email_rfc822 ($email) {         $addrs = imap_rfc822_parse_adrlist ($email, '');         if (count ($addrs) != 1)              return false;         if ($s = imap_errors())              $this->errstr = "The following errors were found: ";              for ($i = 0; $i < count ($s); $i++)                   $this->errstr .= $i + 1 . ". " . $s[$i] . " ";              return false;         return true;    }        /*     * function email_works ($email)     * args: $email (address to test)     * We simulate an SMTP session to the server and use the 'RCPT TO'     * to see whether the mail server will accept mail for this user.     */    function email_works ($email) {        // get the list of mail serves for the user's host/domain name        list ($addr, $hostname) = explode ("@", $email);        if (!getmxrr ($hostname, $mailhosts))            $mailhosts = array ($hostname); // if no MX records found                                            // simply try their hostname        $test_from = "me@domain.com"; // replace w/ your address        for ($i = 0; $i < count ($mailhosts); $i++)        {            // open a connection on port 25 to the recipient's mail server            $fp = fsockopen ($mailhosts[$i], 25);            if (!$fp)                continue;            $r = fgets($fp, 1024);            // talk to the mail server            fwrite ($fp, "HELLO " . $_SERVER['SERVER_NAME'] . "\r\n");            $r = fgets ($fp, 1024);            if (!eregi("^250", $r))            {                fwrite ($fp, "QUIT\r\n");                fclose ($fp);                continue;            }            fwrite ($fp, "MAIL FROM: <" . $test_from . ">\r\n");            $r = fgets ($fp, 1024);            if (!eregi("^250", $r))             {                fwrite ($fp, "QUIT\r\n");                fclose ($fp);                continue;           }            fwrite ($fp, "RCPT TO: <" . $email . ">\r\n");            $r = fgets ($fp, 1024);            if (!eregi("^250", $r))            {                fwrite ($fp, "QUIT\r\n");                fclose ($fp);                continue;            }            // if we got here, we can send email from $test_from to $mail            fwrite ($fp, "QUIT\r\n");            $r = fgets($fp, 1024);            fclose ($fp);            return true;        }        return false;    }}?>

I'm using it like this ($s is just short for $_SESSION)

$test_email = new DV;		$test1 = $test_email->email_works($s['app_email']);

Test it out on your server if you have time. I dont really understand the email_works method to be honest but the code isnt throwing any errors and I'm not sure why it isnt working. If there is something similar or better I can use for email validation out there please let me know. I've used a simplier alternative to this in the past but I think its limited in that it doesent check if the email is valid on the server.Heres the code: I think i got it off php.net in the past

function ck_email ($mail) {	//default	$ck_email_result = "Default";		//pattern	$regex = '/\A(?:[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+'	.'(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@'	.'(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2}|'	.'com|org|net|gov|biz|info|name|aero|biz|info|jobs|'	.'museum)\\Z/i';	if ($mail == '') {		$ck_email_result = "<span class='error_header'>Email Required!</span>";		}	else if (preg_match($regex, $mail)) {		$ck_email_result = "<span class='ok_header'>OK!</span>";		}	else {		$ck_email_result = "<span class='error_header'>Invalid Emai!</span>";		}		return $ck_email_result;} 

Again if you have any suggestions for improvment or an alternative to this function please let me know or better yet share your method or way of checking for valid email addresses.

Edited by sonesay (see edit history)

Share this post


Link to post
Share on other sites

Wow this is extremely interesting. If I ever had to validate an email address in the past I would just send them a verification email with some kind of link in it but this seems much more user friendly. I'm not sure if it would work all the time. I am no expert at servers but I would think that some servers might not allow you to check like this.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×
×
  • Create New...

Important Information

Terms of Use | Privacy Policy | Guidelines | We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.