How to check if an email address exists without sending an email?

How to check if an email address exists without sending an email?

We have all been doing email address validation for a very long time to make sure that the email is correctly formatted. This is to avoid users entering wrongly formatted email address but still they can accidentally give us a wrong email address.

Example of a correctly formatted email address but still wrong:

iyngaran@oracle.com - VALID format but does not exist

So is there a QUICK solution to really check the email without sending a test message to the user? Yes.

The solution

A quick & simple check below can be implemented in most programming language including PHP, Python etc. It relies on using the same SMTP which is used to send emails.

To check if user entered email iyngaran@oracle.com really exists go through the following in command prompt.

First – Find mail exchanger of oracle.com

COMMAND :

nslookup -q=mx oracle.com

RESPONSE :

Server:     192.168.1.1
Address:    192.168.1.1#53


Non-authoritative answer:

oracle.com    mail exchanger = 200 aserp1020.oracle.com.
oracle.com    mail exchanger = 200 aserp1030.oracle.com.
oracle.com    mail exchanger = 200 aserp1060.oracle.com.
oracle.com    mail exchanger = 200 userp1020.oracle.com.
oracle.com    mail exchanger = 200 userp1030.oracle.com.


Authoritative answers can be found from:

oracle.com    nameserver = u-ns3.oracle.com.
oracle.com    nameserver = u-ns2.oracle.com.
oracle.com    nameserver = u-ns4.oracle.com.
oracle.com    nameserver = u-ns6.oracle.com.
oracle.com    nameserver = u-ns1.oracle.com.
oracle.com    nameserver = ns1.oracle.com.
oracle.com    nameserver = ns4.oracle.com.
oracle.com    nameserver = u-ns5.oracle.com.

aserp1020.oracle.com    internet address = 141.146.126.67
aserp1030.oracle.com    internet address = 141.146.126.68
aserp1060.oracle.com    internet address = 141.146.126.71
userp1020.oracle.com    internet address = 156.151.31.79
userp1030.oracle.com    internet address = 156.151.31.80

ns1.oracle.com    internet address = 148.87.1.20

u-ns1.oracle.com    internet address = 204.74.108.1
u-ns2.oracle.com    internet address = 204.74.109.1
u-ns3.oracle.com    internet address = 199.7.68.1
u-ns4.oracle.com    internet address = 199.7.69.1
u-ns5.oracle.com    internet address = 204.74.114.1
u-ns6.oracle.com    internet address = 204.74.115.1

Second – Connect to mail server aserp1030.oracle.com

COMMAND:

telnet aserp1030.oracle.com 25

RESPONSE:

220 aserp1030.oracle.com ESMTP Sendmail Sentrion-MTA-4.3.1/Sentrion-MTA-4.3.1; Wed, 30 Oct 2013 02:18:08 GMT

COMMAND:

helo hi

RESPONSE: 250 aserp1030.oracle.com Hello

COMMAND:

mail from: <youremailaddress@yahoo.com>

RESPONSE:250 2.1.0 <youremailaddress@yahoo.com>… Sender ok

COMMAND:

rcpt to: <iyngaran@oracle.com>

RESPONSE:503 5.0.0 Need MAIL before RCPT

NOTES:

  1. The 503 response indicates that the email address is not valid and you have caught a valid but wrong email address. This code can be on the server and called on AJAX when user tabs out of the email field. The entire check will take less than 2 seconds to run and you can make sure that the email is correct.
  2. If email was present the server will respond with a 250 instead of 503
  3. There are certain servers with a CATCH ALL email and this means all email address are accepted as valid on their servers (RARE but some servers do have this setting).
  4. Please do not use this method to continuously to check for availability of gmail / yahoo / msn accounts etc as this may cause your IP to be added to a blacklist.
  5. This is to supplement the standard email address javascript validation.

How we can do this using a script ?

We can do this using any programming languages such as PHP, Java, .Net and etc. But here, I am going to do this using PHP.

Here, I have created a class. The class name is – IyngaranMailCheck

This class is meant check the existence of an email address in three levels:

  1. Via regular expression validation
  2. Using domain rules by checking a white list of well known email address provides (ie yahoo.com)
  3. Via SMTP request to simulate a delivery to the address being checked.

define('DEBUG_OK', false);

class IyngaranMailCheck
{
    var $timeout = 10;
    var $domain_rules = [
        "aol.com", "bigfoot.com", "brain.net.pk", "breathemail.net",
        "compuserve.com", "dialnet.co.uk", "glocksoft.com", "home.com",
        "msn.com", "rocketmail.com", "uu.net", "yahoo.com", "yahoo.de"
    ];

    function _is_valid_email($email = "")
    {
        return preg_match('/^[.\w-]+@([\w-]+\.)+[a-zA-Z]{2,6}$/', $email);
    }

    function _check_domain_rules($domain = "")
    {
        return in_array(strtolower($domain), $this->domain_rules);
    }

    function execute($email = "")
    {
        if (!$this->_is_valid_email($email)) {
            return false;
        }

        $host = substr(strstr($email, '@'), 1);

        if ($this->_check_domain_rules($host)) {
            return false;
        }

        $host .= ".";
        
        if (getmxrr($host, $mxhosts[0], $mxhosts[1])) {
            array_multisort($mxhosts[1], $mxhosts[0]);
        } else {
            $mxhosts[0] = [$host];
            $mxhosts[1] = [10];
        }
        
        if (DEBUG_OK) {
            print_r($mxhosts);
        }

        $port = 25;
        $localhost = $_SERVER['HTTP_HOST'];
        $sender = 'info@' . $localhost;

        $result = false;
        $id = 0;
        
        while (!$result && $id < count($mxhosts[0])) {
            if (function_exists("fsockopen")) {
                if (DEBUG_OK) {
                    print_r($id . " " . $mxhosts[0][$id]);
                }
                
                if ($connection = fsockopen($mxhosts[0][$id], $port, $errno, $error, $this->timeout)) {
                    fputs($connection, "HELO $localhost\r\n");
                    $data = fgets($connection, 1024);
                    $response = substr($data, 0, 1);

                    if (DEBUG_OK) {
                        print_r($data);
                    }

                    if ($response == '2') {
                        fputs($connection, "MAIL FROM:<$sender>\r\n");
                        $data = fgets($connection, 1024);
                        $response = substr($data, 0, 1);
                        
                        if (DEBUG_OK) {
                            print_r($data);
                        }

                        if ($response == '2') {
                            fputs($connection, "RCPT TO:<$email>\r\n");
                            $data = fgets($connection, 1024);
                            $response = substr($data, 0, 1);

                            if (DEBUG_OK) {
                                print_r($data);
                            }

                            if ($response == '2') {
                                fputs($connection, "DATA\r\n");
                                $data = fgets($connection, 1024);
                                $response = substr($data, 0, 1);

                                if (DEBUG_OK) {
                                    print_r($data);
                                }

                                if ($response == '2') {
                                    $result = true;
                                }
                            }
                        }
                    }

                    fputs($connection, "QUIT\r\n");
                    fclose($connection);

                    if ($result) {
                        return true;
                    }
                }
            } else {
                break;
            }
            
            $id++;
        }
        
        return false;
    }
}

On row 41 of IyngaranMailCheck.php substitute the following line

function getmxrr_win($hostname = "", &$mxhosts, &$weight)
{
    $weight = [];
    $mxhosts = [];
    $result = [];

    $command = "nslookup -type=mx " . escapeshellarg($hostname);
    exec($command, $result);

    $nslookup = [];
    foreach ($result as $value) {
        if (strpos($value, "mail exchanger") !== false) {
            $nslookup[] = $value;
        }
    }

    $mx = [];
    foreach ($nslookup as $key => $value) {
        $temp = explode(" ", $value);
        $mx[$key][0] = substr($temp[3], 0, -1);
        $mx[$key][1] = $temp[7];
        $mx[$key][2] = gethostbyname($temp[7]);
    }

    array_multisort($mx);

    foreach ($mx as $value) {
        $mxhosts[] = $value[1];
        $weight[] = $value[0];
    }

    return count($mxhosts) > 0;
}

function getmxrr_portable($hostname = "", &$mxhosts, &$weight)
{
    if (function_exists("getmxrr")) {
        return getmxrr($hostname, $mxhosts, $weight);
    }
    return getmxrr_win($hostname, $mxhosts, $weight);
}

Done. Now we need to test.

include ("IyngaranMailCheck.php");

$checkmail = new IyngaranMailCheck ();

$emails = array ("iyngaran55@gmail.com","info@yahoo.com", "invalid#email.com", "setec@freemail.it", "thisdoesentexist@google.com");

foreach ($emails as $email)
{
    if ($checkmail->execute ($email))
    { 
        print ("The email address $email exists! \n"); 
    }
    else
    { 
        print ("The email address $email <strong>doesn't</strong> exists!"); 
    }
}

The Response: