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.
CODE
<?php
define ('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;
}
}
?>
define ('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
// 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
* 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)
CODE
$test_email = new DV;
$test1 = $test_email->email_works($s['app_email']);
$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
CODE
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)\b)\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;
}
//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)\b)\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.

