Last week I was thinking of an application that can verify email online. So I thought of sharing the information with the .Net community as well.
The Problem
Let us think of a database of hundreds of emails which were collected over years. The problem here is that some of the email exists, some do not. So while sending notifications to clients, the returned invalid user mail messages require a lot of manual work to clear them. Our idea is to verify whether an email exists before sending the mail. Everything should be automatic and less time consuming.
The Solution
There were two solutions evolved explained below:
- Automate nslookup and SMTP commands using C#
- Use WebClient automation to verify email using a website
Above all, allow multi-threading to be used so that the delays can be shared.
How do the SMTP commands work?
It is worth learning how we can send emails manually using SMTP commands over telnet. For eg: Our interested email id is [email protected]. We can verify the email using the following steps:
- Find the domain name from email. In the above case it is gmail.com
- Find the mail exchange server name from the domain name. Use command nslookup for achieving this: nslookup –q=mx gmail.com
The highlighted line shows that the gmail-smtp-in.l.google.com should be the high preference mail server. The actual preference should be treated as lower for a higher preference value.
- Connect to the mail server using port 25 and verify the email address. The commands would be:
telnet gmail-smtp-in.l.google.com 25
MAIL FROM: <[email protected]>
RCPT TO: <[email protected]>
(If the email exists then the mail server will return 250 – if it doesn't then the value will be 550.)
Note: Our aim is to automate the commands through C#.
How does email verification with website work?
There are many online services which allows us to verify emails online. For eg:
We can enter the email id and click the Verify button on website. If the email id exists it will return Result: Ok as reply.
Note: Our aim is to automate the form filling and submitting through C#. But the site only allows 20 emails to be verified per hour. So we need to find another site providing the service.
Implementation
As we analyzed both cases of verifying email, shall we jump into the implementation part? For implementing the MX Server lookup part we are using the following method:
public IList<MXServer> GetMXServers(string domainName)
{
string command = "nslookup -q=mx " + domainName;
ProcessStartInfo procStartInfo = new ProcessStartInfo("cmd", "/c " + command);
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
Process proc = new Process();
proc.StartInfo = procStartInfo;
proc.Start();
string result = proc.StandardOutput.ReadToEnd();
if (!string.IsNullOrEmpty(result))
result = result.Replace("\r\n", Environment.NewLine);
IList<MXServer> list = new List<MXServer>();
foreach (string line in result.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries))
{
if (line.Contains("MX preference =") && line.Contains("mail exchanger ="))
{
MXServer mxServer = new MXServer();
mxServer.Preference = Int(GetStringBetween(line, "MX preference = ", ","));
mxServer.MailExchanger = GetStringFrom(line, "mail exchanger = ");
list.Add(mxServer);
}
return list.OrderBy(m => m.Preference).ToList();
}
The EmailVerifier Class
The core method in EmailVerifier class is CheckExists() which takes an email as argument. The method used for verification (SMTP or Website) is determined by the parameter passed to EmailVerifier constructor. The body of CheckExists() is given below:
public bool CheckExists(string email)
{
if (_useSMTPMethod)
return IsFormatValid(email) && IsExists_SMTPMethod(email);
else
return IsFormatValid(email) && IsExists_WebClientMethod(email);
}
For checking multiple emails the following method can be used:
public IList<string> CheckExists(IList<string> emailList)
{
_validList = new List<string>();
_count = 0;
foreach (string email in emailList)
{
ParameterizedThreadStart threadStart = new ParameterizedThreadStart(CheckEmailExistsThreaded);
Thread thread = new Thread(threadStart);
thread.Start(email);
}
// Wait for completion
while (_count < emailList.Count)
{
Thread.Sleep(100);
}
return _validList;
}
The above method will validate the emails passed and returns only the existing emails. The method will be using threads to gain the waiting time usage.
Unit Testing
The associated project contains unit tests for testing the core methods. All the Email validation methods and multi-threading tests were executing using it.
Note
Please ensure the antivirus/firewall settings are not hindering the socket communications.
Test Application in Windows
A small test application is also attached for providing the user interface to enter the email address and verify it.