How to check if an email ID is real without sending email

0 / 270
Check if email is real

Introduction (Check if an email ID is real):

 

We might encounter a situation many times wherein we would like to check if an email ID is real or fake. We would be interested to ascertain that without sending an email to that ID. It’s possible to do that programmatically and this blog will tell you how ?

 

 

Overview:

 

To check if an email exists or not, a fairly simple process is to be followed as below

1) Extract domain name and user from the email ID. For eg abc@xyz.com will equate to user: abc and domain xyz.com.

 

2) Extract MX records (mail exchanger records) corresponding to the domain using standard APIs of the programming language that you choose to use. In this blog, its PHP. But one can choose to use Python,Perl,Ruby or any other language of their choice. Mail exchanger records signify the domain responsible for accepting emails from senders.

 

3) Set a certain connection timeout while trying to connect to the domain through TCP socket.

 

4) Open a socket to the designated MX domain using socket APIs.

 

5) If connection is refused,  straight away it’s concluded that the domain isn’t accepting emails and thus the email ID is fake.

 

6) If connection is established , the next task is to verify if mailbox exists for the user specified by the email ID. For this, open socket connection to the SMTP server , first by sending MAIL FROM command followed by RCPT TO command. If the status code returned by RCPT TO command is either 250, 450,451 or 452, the mail exists and it’s real. If any other status code is returned, that means, mail doesn’t exist.

 

Below is a small TABLE indicating different status codes with their meanings

 

Code Meaning
200                                 (nonstandard success response, see rfc876)
211                                 System status, or system help reply
214                                              Help message
220                                 <domain> Service ready
221                                 <domain> Service closing transmission channel
250                                 Requested mail action okay, completed
251                                 User not local; will forward to <forward-path>
252                                 Cannot VRFY user, but will accept message and attempt delivery
354                                  Start mail input; end with <CRLF>.<CRLF>
421                                  <domain> Service not available, closing transmission channel
450                                  Requested mail action not taken: mailbox unavailable
451                                  Requested action aborted: local error in processing
452                                  Requested action not taken: insufficient system storage
500                                  Syntax error, command unrecognised
501                                  Syntax error in parameters or arguments
502                                  Command not implemented
503                                  Bad sequence of commands
504                                  Command parameter not implemented
521                                  <domain> does not accept mail (see rfc1846)
530                                   Access denied (???a Sendmailism)
550                                   Requested action not taken: mailbox unavailable
551                                   User not local; please try <forward-path>
552                                   Requested mail action aborted: exceeded storage allocation
553                                   Requested action not taken: mailbox name not allowed
554                                   Transaction failed

 

Demo below to see all this in action:-

 

 

Below is the end to end code to achieve the above :-

 

Client code (HTML)

html-email-validation

< !DOCTYPE HTML> 
<html> 
<head> 
<!--<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">--> 
<meta http-equiv="Content-Type" content="text/html; charset=Windows-1251"/> 
<title>Sample</title> 
<style>
#email {
display: inline-block;
margin: 0;
font-family: sans-serif;
font-size: 18px;
appearance: none;
box-shadow: none;
border-radius: none;
}
input:focus { 
background-color: #28AADC;
outline:none;
}
</style>
<script src ='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>
</head> 
<body> 
<b>Email : </b><input id='email' type='email' name='email' size=30 placeholder="Email" autofocus />
<br /><br />
<input type="submit" value="Submit" onclick='validate()' style='font-weight:bold'/><br />
<h3><div id='result'></div></h3>
</body> 
<script>
function validate() {
$('#result').html('');
$.post( "verify.php", $('#email'))
.done(function( data ) {
$('#result').html(data)
});
}
</script></html>

 

Server Side code (PHP)

php-email-verification

< ?php 
include_once 'verifyEmail.php'; 
function checkInput($str) {
$str = strip_tags($str);
$str = stripslashes($str);
return $str;
}
$email = checkInput($_POST['email']); 
$vmail = new verifyEmail(); 
$vmail->setStreamTimeout(5); 
$vmail->Debug= TRUE; 
$vmail->Debugoutput= 'html'; 
$vmail->setEmailFrom('golibrary@gmail.com'); 
if ($vmail->check($email)) { 
echo 'Email &lt;' . $email . '&gt; exists!'; 
} elseif ($vmail->isValid($email)) { 
echo 'Email &lt;' . $email . '&gt; is valid, but doesn\'t exist!'; 
} else { 
echo 'Email &lt;' . $email . '&gt; not valid and doesn\'t exist!'; 
} 
?> 

 

Verify email class PHP (Third party)

verify-email-class

< ?php
/**
* Class to check up e-mail
*
* @author Konstantin Granin <kostya@granin.me>
* @copyright Copyright (c) 2010, Konstantin Granin
*/
class verifyEmail {
/**
* User name
* @var string
*/
private $_fromName;
/**
* Domain name
* @var string
*/
private $_fromDomain;
/**
* SMTP port number
* @var int
*/
private $_port;
/**
* The connection timeout, in seconds.
* @var int
*/
private $_maxConnectionTimeout;
/**
* The timeout on socket connection
* @var int
*/
private $_maxStreamTimeout;
public function __construct() {
$this->_fromName = 'noreply';
$this->_fromDomain = 'localhost';
$this->_port = 25;
$this->_maxConnectionTimeout = 30;
$this->_maxStreamTimeout = 5;
}
/**
* Set email address for SMTP request
* @param string $email Email address
*/
public function setEmailFrom($email) {
list($this->_fromName, $this->_fromDomain) = $this->_parseEmail($email);
}
/**
* Set connection timeout, in seconds.
* @param int $seconds
*/
public function setConnectionTimeout($seconds) {
$this->_maxConnectionTimeout = $seconds;
}
/**
* Set the timeout on socket connection
* @param int $seconds
*/
public function setStreamTimeout($seconds) {
$this->_maxStreamTimeout = $seconds;
}
/**
* Validate email address.
* @param string $email
* @return boolean  True if valid.
*/
public function isValid($email) {
return (false !== filter_var($email, FILTER_VALIDATE_EMAIL));
}
/**
* Get array of MX records for host. Sort by weight information.
* @param string $hostname The Internet host name.
* @return array Array of the MX records found.
*/
public function getMXrecords($hostname) {
$mxhosts = array();
$mxweights = array();
if (getmxrr($hostname, $mxhosts, $mxweights)) {
array_multisort($mxweights, $mxhosts);
}
/**
* Add A-record as last chance (e.g. if no MX record is there).
* Thanks Nicht Lieb.
*/
$mxhosts[] = $hostname;
return $mxhosts;
}
/**
* check up e-mail
* @param string $email Email address
* @return boolean True if the valid email also exist
*/
public function check($email) {
$result = false;
if ($this->isValid($email)) {
list($user, $domain) = $this->_parseEmail($email);
$mxs = $this->getMXrecords($domain);
$fp = false;
$timeout = ceil($this->_maxConnectionTimeout / count($mxs));
foreach ($mxs as $host) {
//                if ($fp = @fsockopen($host, $this->_port, $errno, $errstr, $timeout)) {
if ($fp = @stream_socket_client("tcp://" . $host . ":" . $this->_port, $errno, $errstr, $timeout)) {
stream_set_timeout($fp, $this->_maxStreamTimeout);
stream_set_blocking($fp, 1);
//                    stream_set_blocking($fp, 0);
$code = $this->_fsockGetResponseCode($fp);
if ($code == '220') {
break;
} else {
fclose($fp);
$fp = false;
}
}
}
if ($fp) {
$this->_fsockquery($fp, "HELO " . $this->_fromDomain);
//$this->_fsockquery($fp, "VRFY " . $email);
$this->_fsockquery($fp, "MAIL FROM: < " . $this->_fromName . '@' . $this->_fromDomain . ">");
$code = $this->_fsockquery($fp, "RCPT TO: < " . $user . '@' . $domain . ">");
$this->_fsockquery($fp, "RSET");
$this->_fsockquery($fp, "QUIT");
fclose($fp);
if ($code == '250') {
/**
* http://www.ietf.org/rfc/rfc0821.txt
* 250 Requested mail action okay, completed
* email address was accepted
*/
$result = true;
} elseif ($code == '450' || $code == '451' || $code == '452') {
/**
* http://www.ietf.org/rfc/rfc0821.txt
* 450 Requested action not taken: the remote mail server
*     does not want to accept mail from your server for
*     some reason (IP address, blacklisting, etc..)
*     Thanks Nicht Lieb.
* 451 Requested action aborted: local error in processing
* 452 Requested action not taken: insufficient system storage
* email address was greylisted (or some temporary error occured on the MTA)
* i believe that e-mail exists
*/
$result = true;
}
}
}
return $result;
}
/**
* Parses input string to array(0=>user, 1=>domain)
* @param string $email
* @return array
* @access private
*/
private function _parseEmail(&$email) {
return sscanf($email, "%[^@]@%s");
}
/**
* writes the contents of string to the file stream pointed to by handle $fp
* @access private
* @param resource $fp
* @param string $string The string that is to be written
* @return string Returns a string of up to length - 1 bytes read from the file pointed to by handle.
* If an error occurs, returns FALSE.
*/
private function _fsockquery(&$fp, $query) {
stream_socket_sendto($fp, $query . "\r\n");
return $this->_fsockGetResponseCode($fp);
}
/**
* Reads all the line long the answer and analyze it.
* @access private
* @param resource $fp
* @return string Response code
* If an error occurs, returns FALSE
*/
private function _fsockGetResponseCode(&$fp) {
$reply = stream_get_line($fp, 1);
$status = stream_get_meta_data($fp);
if ($status['unread_bytes']>0)
{
$reply .= stream_get_line($fp, $status['unread_bytes'],"\r\n");
}
preg_match('/^(?<code>[0-9]{3}) (.*)$/ims', $reply, $matches);
$code = isset($matches['code']) ? $matches['code'] : false;
return $code;
}
}
?></code>

 

The above is just a simple demo using PHP. But the same can be implemented using Python,Ruby or any other language of your choice.

 

Comments

comments


An avid reader, responsible for generating creative content ideas for golibrary.co. His interests include algorithms and programming languages. Blogging is a hobby and passion.
loading...