<p>I need to send hundreds of newsletters, but would like to check first if email exists on server. It's called <a href="http://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol" rel="noreferrer">SMTP</a> validation, at least I think so, based on my research on Internet.  </p>

<p>There's several libraries that can do that, and also a page with open-source code in <a href="http://en.wikipedia.org/wiki/Active_Server_Pages" rel="noreferrer">ASP Classic</a> (<a href="http://www.coveryourasp.com/ValidateEmail.asp#Result3" rel="noreferrer">http://www.coveryourasp.com/ValidateEmail.asp#Result3</a>), but I have hard time reading ASP Classic, and it seems that it uses some third-party library...  </p>

<p>Is there some code for SMTP validation in C#, and/or general explanation of how it works?</p>

[{'answer_id': 27480, 'author': 'Ishmaeel', 'author_id': 227, 'author_profile': 'https://Stackoverflow.com/users/227', 'pm_score': 2, 'selected': False, 'text': "<p>The Real(TM) e-mail validation is trying to send something to the address, and seeing if it is rejected/bounced. So, you'll just have to send them away, and remove the addresses that fail from your mailing list.</p>\n"}, {'answer_id': 27489, 'author': 'diciu', 'author_id': 2811, 'author_profile': 'https://Stackoverflow.com/users/2811', 'pm_score': 3, 'selected': False, 'text': '<p>SMTP is a text based protocol carried over TCP/IP.</p>\n\n<p>Your validation program needs to open a TCP/IP connection to the server\'s port 25 (SMTP), write in a few lines and read the answer. Validation is done (but not always) on the "RCTP TO" line and on the "VFRY" line.</p>\n\n<p>The  <a href="http://www.ietf.org/rfc/rfc0821.txt" rel="noreferrer">SMTP RFC</a> describes how this works (see Green@Beta.ARPA below, S are lines sent by the client, R are lines received from the server):</p>\n\n<pre>\nExample of the SMTP Procedure\n\n         This SMTP example shows mail sent by Smith at host Alpha.ARPA,\n         to Jones, Green, and Brown at host Beta.ARPA.  Here we assume\n         that host Alpha contacts host Beta directly.\n\n            S: MAIL FROM:\n            R: 250 OK\n\n            S: RCPT TO:\n            R: 250 OK\n\n            S: RCPT TO:\n            R: 550 No such user here\n</pre>\n'}, {'answer_id': 27491, 'author': 'WMR', 'author_id': 2844, 'author_profile': 'https://Stackoverflow.com/users/2844', 'pm_score': 5, 'selected': True, 'text': '<p>Be aware that most MTAs (Mail Transfer Agent) will have the VRFY command turned off for spam protection reasons, they\'ll probably even block you if you try several RCPT TO in a row (see <a href="http://www.spamresource.com/2007/01/whatever-happened-to-vrfy.html" rel="noreferrer">http://www.spamresource.com/2007/01/whatever-happened-to-vrfy.html</a>). So even if you find a library to do that verification, it won\'t be worth a lot. Ishmaeel is right, the only way to really find out, is sending an email and see if it bounces or not.</p>\n\n<p>@Hrvoje: Yes, I\'m suggesting you monitor rejected emails. BUT: not all the bounced mails should automatically end up on your "does not exist"-list, you also have to differentiate between temporary (e.g. mailbox full) and permanent errors.</p>\n'}, {'answer_id': 27560, 'author': 'Dane', 'author_id': 2929, 'author_profile': 'https://Stackoverflow.com/users/2929', 'pm_score': 2, 'selected': False, 'text': "<p>Don't take this the wrong way, but sending newsletters to more than a handful of people these days is a fairly serious matter.  Yes, you need to be monitoring bounces (rejected emails) which can occur synchronously during the SMTP send (typically if the SMTP server you are connected to is authoritative), or asynchronously as a system-generated email message that occurs some amount of time after the SMTP send succeeded.</p>\n\n<p>Also keep the CAN-SPAM Act in mind and abide by the law when sending these emails; you've got to provide an unsub link as well as a physical street address (to both identify you and t0 allow users to send unsub requests via snail-mail if they so choose).</p>\n\n<p>Failure to do these things could get your IP null-routed at best and sued at worst.</p>\n"}, {'answer_id': 291020, 'author': 'Don Worthley', 'author_id': 37225, 'author_profile': 'https://Stackoverflow.com/users/37225', 'pm_score': 2, 'selected': False, 'text': '<p>While it\'s true that many domains will return false positives because of abuse, there are still some great components out there that will perform several levels of validation beyond just the SMTP validation.  For example, it\'s worth it to check first to see if at least the domain exists.  I\'m in the process of compiling my own list of resources related to this question which you can track here:</p>\n<p><a href="http://delicious.com/dworthley/email.validation" rel="nofollow noreferrer">http://delicious.com/dworthley/email.validation</a> (broken link)</p>\n<p>For those who might want to add to this list, I\'ll also include what I currently have here:</p>\n<ul>\n<li><a href="http://www.aspnetmx.com/demo.aspx" rel="nofollow noreferrer">aspNetMX</a></li>\n<li><a href="http://www.seekfordsolutions.com/OnlineDemos/NETEmailValidationWizard/EmailValidationWizardOnlineExample.aspx" rel="nofollow noreferrer">.NET Email Validation Wizard Class Library</a></li>\n<li><a href="http://monoprog.com/prod/asp_net_components/email_validator_net.aspx" rel="nofollow noreferrer">MONOProg Email Validator.Net</a></li>\n</ul>\n<p>For a bulletproof form and a great user experience, it\'s helpful to validate as many aspects of the email address as possible.  I can see from the <a href="http://www.aspnetmx.com/demo.aspx" rel="nofollow noreferrer">aspNetMX</a> validator that they check:</p>\n<ul>\n<li>the syntax</li>\n<li>the email against a list of bad email addresses</li>\n<li>the domain against a list of bad domains</li>\n<li>a list of mailbox domains</li>\n<li>whether or not the domain exists</li>\n<li>whether there are MX records for the domain</li>\n<li>and finally through SMTP whether or not a mailbox exists</li>\n</ul>\n<p>It\'s this last step that can be circumvented by administrators by returning true to basically all account verification requests, but in most cases if the user has intentionally entered a bad address it\'s already been caught.  And if it was user error in the domain part of the address, that will be caught too.</p>\n<p>Of course, a best practice for using this kind of a service for a registration screen or form would be to combine this kind of validation with a verification process to ensure that the email address is valid.  The great thing about using an email validator in front of a verification process is that it will make for a better overall user experience.</p>\n'}, {'answer_id': 2795865, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 1, 'selected': False, 'text': '<p>You may need this <a href="http://www.componentsoft.net/component/emailvalidator.net/" rel="nofollow noreferrer">Email Validator component for .NET</a></p>\n\n<p>Here is the code example:</p>\n\n<pre><code>\n   // Create a new instance of the EmailValidator class.\n   EmailValidator em = new EmailValidator();\n   em.MessageLogging += em_MessageLogging;\n   em.EmailValidated += em_EmailValidationCompleted;\n   try\n   {\n       string[] list = new string[3] { "test1@testdomain.com", "test2@testdomain.com", "test3@testdomain.com" };\n       em.ValidateEmails(list);\n   }\n   catch (EmailValidatorException exc2)\n   {\n       Console.WriteLine("EmailValidatorException: " + exc2.Message);\n   }\n</code></pre>\n'}, {'answer_id': 21849102, 'author': 'Rahul Saraswat', 'author_id': 2810254, 'author_profile': 'https://Stackoverflow.com/users/2810254', 'pm_score': 2, 'selected': False, 'text': '<p>You can try the below code, it works fine for me : </p>\n\n<pre><code>public class EmailTest {\n    private static int hear(BufferedReader in) throws IOException {\n        String line = null;\n        int res = 0;\n\n        while ((line = in.readLine()) != null) {\n            String pfx = line.substring(0, 3);\n            try {\n                res = Integer.parseInt(pfx);\n            } catch (Exception ex) {\n                res = -1;\n            }\n            if (line.charAt(3) != \'-\')\n                break;\n        }\n\n        return res;\n    }\n\n    private static void say(BufferedWriter wr, String text) throws IOException {\n        wr.write(text + "\\r\\n");\n        wr.flush();\n\n        return;\n    }\n\n    @SuppressWarnings({ "rawtypes", "unchecked" })\n    private static ArrayList getMX(String hostName) throws NamingException {\n        // Perform a DNS lookup for MX records in the domain\n        Hashtable env = new Hashtable();\n        env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");\n        DirContext ictx = new InitialDirContext(env);\n        Attributes attrs = ictx.getAttributes(hostName, new String[] { "MX" });\n        Attribute attr = attrs.get("MX");\n\n        // if we don\'t have an MX record, try the machine itself\n        if ((attr == null) || (attr.size() == 0)) {\n            attrs = ictx.getAttributes(hostName, new String[] { "A" });\n            attr = attrs.get("A");\n            if (attr == null)\n                throw new NamingException("No match for name \'" + hostName + "\'");\n        }\n        /*\n         Huzzah! we have machines to try. Return them as an array list\n         NOTE: We SHOULD take the preference into account to be absolutely\n         correct. This is left as an exercise for anyone who cares.\n         */\n        ArrayList res = new ArrayList();\n        NamingEnumeration en = attr.getAll();\n\n        while (en.hasMore()) {\n            String mailhost;\n            String x = (String) en.next();\n            String f[] = x.split(" ");\n            // THE fix *************\n            if (f.length == 1)\n                mailhost = f[0];\n            else if (f[1].endsWith("."))\n                mailhost = f[1].substring(0, (f[1].length() - 1));\n            else\n                mailhost = f[1];\n            // THE fix *************\n            res.add(mailhost);\n        }\n        return res;\n    }\n\n    @SuppressWarnings("rawtypes")\n    public static boolean isAddressValid(String address) {\n        // Find the separator for the domain name\n        int pos = address.indexOf(\'@\');\n\n        // If the address does not contain an \'@\', it\'s not valid\n        if (pos == -1)\n            return false;\n\n        // Isolate the domain/machine name and get a list of mail exchangers\n        String domain = address.substring(++pos);\n        ArrayList mxList = null;\n        try {\n            mxList = getMX(domain);\n        } catch (NamingException ex) {\n            return false;\n        }\n\n        /*\n        Just because we can send mail to the domain, doesn\'t mean that the\n        address is valid, but if we can\'t, it\'s a sure sign that it isn\'t\n        */\n        if (mxList.size() == 0)\n            return false;\n\n        /* \n        Now, do the SMTP validation, try each mail exchanger until we get\n        a positive acceptance. It *MAY* be possible for one MX to allow\n        a message [store and forwarder for example] and another [like\n        the actual mail server] to reject it. This is why we REALLY ought\n        to take the preference into account.\n        */\n        for (int mx = 0; mx &lt; mxList.size(); mx++) {\n            boolean valid = false;\n            try {\n                int res;\n                //\n                Socket skt = new Socket((String) mxList.get(mx), 25);\n                BufferedReader rdr = new BufferedReader(new InputStreamReader(skt.getInputStream()));\n                BufferedWriter wtr = new BufferedWriter(new OutputStreamWriter(skt.getOutputStream()));\n\n                res = hear(rdr);\n                if (res != 220)\n                    throw new Exception("Invalid header");\n                say(wtr, "EHLO rgagnon.com");\n\n                res = hear(rdr);\n                if (res != 250)\n                    throw new Exception("Not ESMTP");\n\n                // validate the sender address\n                say(wtr, "MAIL FROM: &lt;tim@orbaker.com&gt;");\n                res = hear(rdr);\n                if (res != 250)\n                    throw new Exception("Sender rejected");\n\n                say(wtr, "RCPT TO: &lt;" + address + "&gt;");\n                res = hear(rdr);\n\n                // be polite\n                say(wtr, "RSET");\n                hear(rdr);\n                say(wtr, "QUIT");\n                hear(rdr);\n                if (res != 250)\n                    throw new Exception("Address is not valid!");\n\n                valid = true;\n                rdr.close();\n                wtr.close();\n                skt.close();\n            } catch (Exception ex) {\n                // Do nothing but try next host\n                ex.printStackTrace();\n            } finally {\n                if (valid)\n                    return true;\n            }\n        }\n        return false;\n    }\n\n    public static void main(String args[]) {\n        String testData[] = { "rahul.saraswat@techblue.com", "rahul.saraswat@techblue.co.uk", "srswt.rahul12345@gmail.com",\n        "srswt.rahul@gmail.com" };\n        System.out.println(testData.length);\n        for (int ctr = 0; ctr &lt; testData.length; ctr++) {\n            System.out.println(testData[ctr] + " is valid? " + isAddressValid(testData[ctr]));\n        }\n        return;\n    }\n}\n</code></pre>\n\n<p>Thanks &amp; Regards\nRahul Saraswat</p>\n'}]
['https://Stackoverflow.com/questions/27474', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/1407/']