143

I have come across this PHP code to check email address using SMTP without sending an email.

Has anyone tried anything similar or does it work for you? Can you tell if an email customer / user enters is correct & exists?

SagarPPanchal
  • 9,839
  • 6
  • 34
  • 62
php-guy
  • 1,433
  • 2
  • 10
  • 6
  • Similar question: [Can I check if an email address exists using .net?](http://stackoverflow.com/questions/3883518/can-i-check-if-an-email-address-exists-using-net) – sleske Jul 24 '12 at 07:15
  • 3
    Just wondering, why does this have the Telnet tag? – Piccolo Mar 14 '13 at 00:38
  • 2
    There's a PHP library that does exactly that: https://github.com/kickboxio/kickbox-php – Dan Jun 10 '14 at 04:12
  • Kickbox isn't Free. This API is just an wrapper to connect to their service. – Ashit Vora Mar 07 '16 at 11:31

16 Answers16

107

There are two methods you can sometimes use to determine if a recipient actually exists:

  1. You can connect to the server, and issue a VRFY command. Very few servers support this command, but it is intended for exactly this. If the server responds with a 2.0.0 DSN, the user exists.

    VRFY user
    
  2. You can issue a RCPT, and see if the mail is rejected.

    MAIL FROM:<>
    RCPT TO:<user@domain>
    

If the user doesn't exist, you'll get a 5.1.1 DSN. However, just because the email is not rejected, does not mean the user exists. Some server will silently discard requests like this to prevent enumeration of their users. Other servers cannot verify the user and have to accept the message regardless.

There is also an antispam technique called greylisting, which will cause the server to reject the address initially, expecting a real SMTP server would attempt a re-delivery some time later. This will mess up attempts to validate the address.

Honestly, if you're attempting to validate an address the best approach is to use a simple regex to block obviously invalid addresses, and then send an actual email with a link back to your system that will validate the email was received. This also ensures that they user entered their actual email, not a slight typo that happens to belong to somebody else.

Michael
  • 8,362
  • 6
  • 61
  • 88
Joseph Tary
  • 1,391
  • 1
  • 8
  • 5
  • 12
    Some servers will even accept the message but then later send a error message back to the envelope sender, especially if its a large organization with many internal departments with their own mail servers. The border server might not even know all accounts within. – David Mårtensson Feb 27 '11 at 21:25
  • 4
    Then why don't spammers use this method to verify email addies? I mean aside the fact that these methods are supported by very few servers. Or do they? – Gelmir Feb 28 '11 at 21:48
  • 9
    @Shehi: Actually spammers *may* use this method, that's hard to tell. However, because spammers *might* use it, almost all mail servers disable VRFY, so in practice VRFY is probably useless. – sleske Jul 24 '12 at 07:18
  • 2
    Can you give a code example of how to use a RCPT TO: ? Thanks – Papa De Beau Mar 22 '13 at 15:59
  • 6
    To VRFY, gmail responds "Send some mail, I'll try my best" ;-) – Armel Larcier Jun 25 '15 at 21:28
  • Regex that can satisfy requirement: ^[^@\s]+@[^@\s\.]+\.[^@\s\.]+$ The validation statement is: @. Additionally once can also do this: @ For - Follow the guidelines by the "Universal Acceptance Steering Group" - [UASG-026] For , follow any domain validation methodology using standard libraries, depending on your language. Additionally follow the document [UASG-018A] – ThinkTrans Mar 22 '22 at 17:32
56

Other answers here discuss the various problems with trying to do this. I thought I'd show how you might try this in case you wanted to learn by doing it yourself.

You can connect to an mail server via telnet to ask whether an email address exists. Here's an example of testing an email address for stackoverflow.com:

C:\>nslookup -q=mx stackoverflow.com
Non-authoritative answer:
stackoverflow.com       MX preference = 40, mail exchanger = STACKOVERFLOW.COM.S9B2.PSMTP.com
stackoverflow.com       MX preference = 10, mail exchanger = STACKOVERFLOW.COM.S9A1.PSMTP.com
stackoverflow.com       MX preference = 20, mail exchanger = STACKOVERFLOW.COM.S9A2.PSMTP.com
stackoverflow.com       MX preference = 30, mail exchanger = STACKOVERFLOW.COM.S9B1.PSMTP.com

C:\>telnet STACKOVERFLOW.COM.S9A1.PSMTP.com 25
220 Postini ESMTP 213 y6_35_0c4 ready.  CA Business and Professions Code Section 17538.45 forbids use of this system for unsolicited electronic mail advertisements.

helo hi
250 Postini says hello back

mail from: <me@myhost.com>
250 Ok

rcpt to: <fake@stackoverflow.com>
550-5.1.1 The email account that you tried to reach does not exist. Please try
550-5.1.1 double-checking the recipient's email address for typos or
550-5.1.1 unnecessary spaces. Learn more at
550 5.1.1 http://mail.google.com/support/bin/answer.py?answer=6596 w41si3198459wfd.71

Lines prefixed with numeric codes are responses from the SMTP server. I added some blank lines to make it more readable.

Many mail servers will not return this information as a means to prevent against email address harvesting by spammers, so you cannot rely on this technique. However you may have some success at cleaning out some obviously bad email addresses by detecting invalid mail servers, or having recipient addresses rejected as above.

Note too that mail servers may blacklist you if you make too many requests of them.


In PHP I believe you can use fsockopen, fwrite and fread to perform the above steps programmatically:

$smtp_server = fsockopen("STACKOVERFLOW.COM.S9A1.PSMTP.com", 25, $errno, $errstr, 30);
fwrite($smtp_server, "helo hi\r\n");
fwrite($smtp_server, "mail from: <me@myhost.com>\r\n");
fwrite($smtp_server, "rcpt to: <fake@stackoverflow.com>\r\n");
Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
10

The general answer is that you can not check if an email address exists event if you send an email to it: it could just go into a black hole.

That being said the method described there is quite effective. It is used in production code in ZoneCheck except that it uses RSET instead of QUIT.

Where user interaction with his mailbox is not overcostly many sites actually test that the mail arrive somewhere by sending a secret number that must be sent back to the emitter (either by going to a secret URL or sending back this secret number by email). Most mailing lists work like that.

kmkaplan
  • 18,655
  • 4
  • 51
  • 65
8

This will fail (amongst other cases) when the target mailserver uses greylisting.

Greylisting: SMTP server refuses delivery the first time a previously unknown client connects, allows next time(s); this keeps some percentage of spambots out, while allowing legitimate use - as it is expected that a legitimate mail sender will retry, which is what normal mail transfer agents will do.

However, if your code only checks on the server once, a server with greylisting will deny delivery (as your client is connecting for the first time); unless you check again in a little while, you may be incorrectly rejecting valid e-mail addresses.

Piskvor left the building
  • 91,498
  • 46
  • 177
  • 222
  • (personal experience: I had to argue back and forth with my e-mail provider that *yes*, I'm aware what I'm doing, and *yes*, I need the greylisting off - because these checks from a third-party service were failing) – Piskvor left the building May 20 '11 at 17:40
7

I can confirm Joseph's and Drew's answers to use RCPT TO: <address_to_check>. I would like to add some little addenda on top of those answers.

Catch-all providers

Some mail providers implement a catch-all policy, meaning that *@mydomain.com will return positive to the RCPT TO: command. But this doesn't necessarily mean that the mailbox "exists", as in "belongs to a human". Nothing much can be done here, just be aware.

IP Greylisting/Blacklisting

Greylisting: 1st connection from unknown IP is blocked. Solution: retry at least 2 times.

Blacklisting: if you send too many requests from the same IP, this IP is blocked. Solution: use IP rotation.

HTTP requests on sign-up forms

This is very provider-specific, but you sometimes can use well-crafted HTTP requests, and parse the responses of these requests to see if a username already signed up or not with this provider. Headless browser automation on a password recovery page might also do the trick.

Full Inbox

This might be an edge case, but when the user has a full inbox, RCTP TO: will return a 5.1.1 DSN error message saying it's full. This means that the account actually exists!

jeanpaul62
  • 9,451
  • 13
  • 54
  • 94
6

Not really.....Some server may not check the "rcpt to:"

http://www.freesoft.org/CIE/RFC/1123/92.htm

Doing so is security risk.....

If the server do, you can write a bot to discovery every address on the server....

l_39217_l
  • 2,090
  • 1
  • 13
  • 15
5

Some issues:

  1. I'm sure some SMTP servers will let you know immediately if an address you give them does not exist, but some won't as a privacy measure. They'll just accept whatever addresses you give them and silently ignore the ones that don't exist.
  2. As the article says, if you do this too often with some servers, they will blacklist you.
  3. For some SMTP servers (like gmail), you need to use SSL in order to do anything. This is only true when using gmail's SMTP server to send email.
Graeme Perrow
  • 56,086
  • 21
  • 82
  • 121
  • Regarding the third point, this only happen if you want to use it as a relay. I do not know of any mail exchanger that requires SSL. If any did this they would stop receiving email from many users. – kmkaplan Feb 19 '09 at 14:43
  • Sorry, my mistake. If you want to *send* email using gmail's SMTP server, you must use SSL. – Graeme Perrow Feb 19 '09 at 15:07
3
function EmailValidation($email)
{
    $email = htmlspecialchars(stripslashes(strip_tags($email))); //parse unnecessary characters to prevent exploits
    if (eregi('[a-z||0-9]@[a-z||0-9].[a-z]', $email)) {
        //checks to make sure the email address is in a valid format
        $domain = explode( "@", $email ); //get the domain name
        if (@fsockopen ($domain[1],80,$errno,$errstr,3)) {
            //if the connection can be established, the email address is probably valid
            echo "Domain Name is valid ";
            return true;
        } else {
            echo "Con not a email domian";
            return false; //if a connection cannot be established return false
        }
        return false; //if email address is an invalid format return false
    }
}
scrowler
  • 24,273
  • 9
  • 60
  • 92
Sachin
  • 789
  • 5
  • 18
3

Although this question is a bit old, this service tip might help users searching for a similar solution checking email addresses beyond syntax validation prior to sending.

I have been using this open sourced service for a more in depth validating of emails (checking for mx records on the e-mail address domain etc.) for a few projects with good results. It also checks for common typos witch is quite useful. Demo here.

Henkealg
  • 1,466
  • 1
  • 16
  • 19
  • You claim this service is open-source. Could you provide a link to the source? – jeanpaul62 Jun 13 '20 at 17:02
  • I'm sorry @amaurymartiny I cannot. At the time of writing the Mailgun project was open source if I recall correctly but I am unable to find a link to any repo providing the source after thist time. – Henkealg Jun 13 '20 at 20:49
3

About all you can do is search DNS and ensure the domain that is in the email address has an MX record, other than that there is no reliable way of dealing with this.

Some servers may work with the rcpt-to method where you talk to the SMTP server, but it depends entirely on the configuration of the server. Another issue may be an overloaded server may return a 550 code saying user is unknown, but this is a temporary error, there is a permanent error (451 i think?) that can be returned. This depends entirely on the configuration of the server.

I personally would check for the DNS MX record, then send an email verification if the MX record exists.

Astra
  • 10,735
  • 3
  • 37
  • 41
2

"Can you tell if an email customer / user enters is correct & exists?"

Actually these are two separate things. It might exist but might not be correct.

Sometimes you have to take the user inputs at the face value. There are many ways to defeat the system otherwise.

Learning
  • 8,029
  • 3
  • 35
  • 46
2

Assuming it's the user's address, some mail servers do allow the SMTP VRFY command to actually verify the email address against its mailboxes. Most of the major site won't give you much information; the gmail response is "if you try to mail it, we'll try to deliver it" or something clever like that.

Austin Salonen
  • 49,173
  • 15
  • 109
  • 139
1

I think you cannot, there are so many scenarios where even sending an e-mail can fail. Eg. mail server on the user side is temporarily down, mailbox exists but is full so message cannot be delivered, etc.

That's probably why so many sites validate a registration after the user confirmed they have received the confirmation e-mail.

PhiLho
  • 40,535
  • 6
  • 96
  • 134
0

You have many simple online tools like https://mail7.net

This service check the email address format, then make sure the domain name is valid and extracts the MX records. So in 90% you can be sure if it valid. 90% because some mail servers are not involved in the process.

Denis Petrov
  • 117
  • 1
  • 6
-2

I'm a little bit late, but this could help someone.

Here is the code that I'm currently using on my website.

    if(isEmialExist("EMAIL_ADDRESS_THAT"))
{
    echo "email exists, real email";
}
else
{
    echo "email doesn't exist";
}


function isEmialExist($emailAddress)
{
    if (!filter_var($emailAddress, FILTER_VALIDATE_EMAIL)) {
     return false; //invalid format
    }
    //now check if email really exist
    $postdata = http_build_query(array('api_key' => 'YOUR_API_KEY', 'email' => $emailAddress ));
    $url = "https://email-validator.com/api/v1.0/json";
    $opts = array('http' => array( 'method'  => 'POST', 'header'  => 'Content-Type: application/x-www-form-urlencoded', 'content' => $postdata ));
    
    $context  = stream_context_create($opts);
    $result = file_get_contents($url, false, $context);
    $data = json_decode($result, false);
    return $data->is_exists;
}

You can find more details here. https://email-validator.com/tutorial

Deluar Hossen
  • 595
  • 4
  • 6
-12
<?php

   $email = "someone@exa mple.com";

   if(!filter_var($email, FILTER_VALIDATE_EMAIL))
      echo "E-mail is not valid";
   else
      echo "E-mail is valid";

?>
Rohit Suthar
  • 3,528
  • 1
  • 42
  • 48