tags:

views:

93

answers:

7

Given an email address, how can I verify that it is valid? (That the email's domain will accept email for that address.)

How would this look in PHP?

Note: I don't want to verfify that the email address itself is syntactically valid. I want to know whether the domain will accept email to that address.

I would have thought there was some way to do this with an MX record or something...

+1  A: 

You can't actually check if the server will accept it. Mail server's don't have an API to handle that.

There used to be a script that attempted to connect to the MX server, and looked for some sort of response from the server that indicated that it wanted a password, instead of just rejecting it as a not-in-use mailbox. This however is very bad practice.

The only thing you can pretty much do is to check for a valid email address, and hope for the best:

http://www.linuxjournal.com/article/9585

That is one of the tutorials that actually follow the standards in the RFC.

/**
Validate an email address.
Provide email address (raw input)
Returns true if the email address has the email 
address format and the domain exists.
*/
function validEmail($email)
{
   $isValid = true;
   $atIndex = strrpos($email, "@");
   if (is_bool($atIndex) && !$atIndex)
   {
      $isValid = false;
   }
   else
   {
      $domain = substr($email, $atIndex+1);
      $local = substr($email, 0, $atIndex);
      $localLen = strlen($local);
      $domainLen = strlen($domain);
      if ($localLen < 1 || $localLen > 64)
      {
         // local part length exceeded
         $isValid = false;
      }
      else if ($domainLen < 1 || $domainLen > 255)
      {
         // domain part length exceeded
         $isValid = false;
      }
      else if ($local[0] == '.' || $local[$localLen-1] == '.')
      {
         // local part starts or ends with '.'
         $isValid = false;
      }
      else if (preg_match('/\\.\\./', $local))
      {
         // local part has two consecutive dots
         $isValid = false;
      }
      else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain))
      {
         // character not valid in domain part
         $isValid = false;
      }
      else if (preg_match('/\\.\\./', $domain))
      {
         // domain part has two consecutive dots
         $isValid = false;
      }
      else if
(!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/',
                 str_replace("\\\\","",$local)))
      {
         // character not valid in local part unless 
         // local part is quoted
         if (!preg_match('/^"(\\\\"|[^"])+"$/',
             str_replace("\\\\","",$local)))
         {
            $isValid = false;
         }
      }
      if ($isValid && !(checkdnsrr($domain,"MX") || 
 ↪checkdnsrr($domain,"A")))
      {
         // domain not found in DNS
         $isValid = false;
      }
   }
   return $isValid;
}

In the way of making sure that an email is able to be delivered, validations is about as good as you are going to get.

Chacha102
No, no. I don't want to *validate* the email address, I want to *verify* it. (Make sure that the domain will accept emails sent to it.)
George Edison
I'm not sure this what the OP asked. I got the impression that the question is about checking if the server will accept mail with the address given. Although it does need clarification.
Jakub Hampl
Edited. Please Read.
Chacha102
I reworded the question.
George Edison
@George and my response is still valid :)
Chacha102
Of course, I can always check to see if the delivery was successful. (Like the server accepted the message.)
George Edison
+2  A: 

Since you specifically state

That the email's domain will accept email for that address.

no regular expression is going to help you. The only way to verify that is to try to send an email to the address and see if it bounces. Even so, you could get false positives, since the mail server may not send out failure notifications.

Sending a basic email like this with PHP is reasonably simple; check out the documentation for the mail() function here.

Syntactic
Well, I don't really need regular expressions. (I never mentioned it anywhere.) So what you're saying is check the return value of `mail()` to see if the message was successfully accepted for delivery?
George Edison
I know how to send email with `mail()`. I want to know how to verify an address.
George Edison
Yeah, my comment about regular expressions was more a reaction to another answer than to your question. The return value of `mail()` will tell you whether the delivery was successful at this time, though in practice this may not be a very good indication of whether the email address actually exists. Unfortunately, the nature of how email works makes this a difficult task.
Syntactic
I know. I guess the return value is good enough for now. Probably the only other option is a beacon or something.
George Edison
A: 

An e-mail being (syntactically) valid is not the same as it accepting e-mails. In order to check whether the domain will accept e-mail you have to try sending an e-mail directly to the MX, but even then, if it is accept by the SMTP server, you are not guaranteed it will not be rejected afterwards, i.e. a non delivery report will be sent. And the SMTP server will probably reject your e-mail if you are on a dynamic pool of addresses or have no DNS reverse

Artefacto
+1  A: 

How easy is it to verify that an email address is valid?

Not easy at all. Take a look at Dominic Sayers' email validation in PHP, possibly the most complete email validation library in any language. It also includes DNS checking.

Also see this related article from Jeff Atwood about the checks required to guarantee email arrival.

Mauricio Scheffer
Can you point me to the relevant portion that does the DNS checking? I couldn't find it.
George Edison
@George Edison: search for 'checkDNS' in the page, it's buried in the comments.
Mauricio Scheffer
A: 

If you are using PHP 5.2.x, now there is not need to use custom validation functions. PHP comes with a built in function

Gabriel Sosa
Please read the question - this is not what I'm looking for.
George Edison
A: 

Just thought I'd mention that PHP has a built-in function getmxrr() that retrieves the MX record from a domain.

How this is useful, I don't know... On the page it states:

This function should not be used for the purposes of address verification.

So its use is limited to verifying that a domain even has a mailserver.

George Edison
+3  A: 

I think your only options would be the SMTP RCPT TO or VRFY commands.

RCPT TO could be a way to check, as long as you disconnect after issuing it. However not all servers will boot you if the account doesn't exist(uce prevention, catch-all addresses, etc...).

VRFY can tell you if an account exists on that server, but this is almost always disabled to prevent account probes.

A PHP class that does RCPT TO verification(among other methods) is: http://code.google.com/p/php-smtp-email-validation/

morbidcoder
Thank you! This is more what I'm looking for.
George Edison