Verifying email addresses in PHP    

ArticlesA recent discussion in the UPHPU IRC channel (#uphpu on freenode.net) prompted me to submit something I use for validating email addresses. There's only so much you can do without actually sending a message, but this code uses three steps to check the address.

First, it checks it with a regular expression, to verify that it uses valid characters for the various parts of the address, and there is an @ and at least one period, and they're in the right places. Second, it turns to DNS to verify that the domain exists. (DNS calls will probably need tweaking to work on Windows servers.) Best case is that it has an MX record for the domain. Second best is to verify that the domain simply exists and has an address. If it can pass the regular expression test and the DNS test, then it is most likely a valid address. The things we can't easily check are user-related, like user doesn't exist, has exceeded quota, etc.

In places where I've done comparisons with and without this checking in place, I've found very significant reductions (probably around 80%) in the number of bounced messages. While this can be used just before sending, it's often best to use it when accepting the email address from the user, to prevent bad addresses from getting into the system in the first place, and catch typographical errors. In cases where a long time has passed since the email was known to work, it may be helpful to check before sending the message as well.

function ValidateEmail($e,$v=-1) {
  global $verbose;
  /*
   Return codes:
   0: appears to be a valid email
   1: didn't match pattern of a valid email
   2: looks valid by the pattern, but no DNS records found
  
   Try several things to make sure it is most likely valid:
   1.  preg_match it to make sure it looks valid
   2a. If that passes, check for an MX entry for the domain
   2b. If no MX, check for any DNS entry for the domain
  */
  if ($v==-1) { $v=$verbose; }
  if (!preg_match("/^[a-z0-9.+-_]+@([a-z0-9-]+(.[a-z0-9-]+)+)$/i",
		  $e, $grab)) {
    return 1;
  }
  # $grab[0] is the whole address
  # $grab[1] is the domain
  $domain = $grab[1];
  $cmds = array("host -t MX $domain 2>&1 ","host $domain 2>&1 ");
  foreach ($cmds as $cmd) {
    $dns = trim(`$cmd`);
    if ($v) { print "n"; }
    if (strpos($dns,"$domain mail is handled ")!==false ||
	strpos($dns,"$domain has address ")!==false ||
	strpos($dns,"$domain is an alias ")!==false) {
      # It is valid
      return 0;
    }
  }
  # If it didn't return yet, it's invalid, even though it passed the preg.
  return 2;
}

Questions, comments, and suggestions are welcome.

- Mac



 

Verifying email addresses in PHP | 1 comments | , Create New Account
The following comments are owned by whomever posted them. This site is not responsible for what they say.
Verifying email addresses in PHP
Authored by: fungus on Friday, January 07 2005 @ 03:41 PM MST
I personally would prefer to not fork an external command for lookups.
if ($domain != gethostbyname($domain)) {
  if (getmxrr($domain)) {
    // MX record found
    return 0;
  } else {
    // Domain exists and resolves correctly
    return 0;
  }
} else {
  // Domain does not exist
  return 2;
}
[ Reply to This ]
What's Related

Story Options