Archive

Archive for June, 2019

Enhanced email validation using #DNS #MX

email

If you have a sign-up form, and you are collecting user’s email addresses, then you really want to cut down on the number of typos. I’ve seen as many as 5% of users mistyping “@gmail.com” as “@gmail.con, @gmail.co, @gmai.com, and @gmail.xom etc.”

Many of these email addresses pass basic regex checks, it’s “Gmail.co” is in the correct format for a domain name, but alas, your user will never be able to re-log in.

So, instead of only relying on regexes, you can also use a DNS MX lookup, that can check if there are mail exchanger(s) associated with the domain. This means that “@gmail.com” will work, but “@gmail.co” won’t

Firstly, we have to delve into how to perform a DNS MX lookup in C#, which is a UDP request sent over port 53 to a DNS server, in this case 8.8.8.8, which is Google’s public DNS resolver.

Here’s the class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;

public static class Dns
{
public static IEnumerable<string> MxLookup(string domain)
{
const string strDns = “8.8.8.8”; // Google DNS
var udpClient = new UdpClient(strDns, 53);
// SEND REQUEST——————–
var list = new List<byte>();
list.AddRange(new byte[] { 88, 89, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 });
var tmp = domain.Split(‘.’);
foreach (string s in tmp)
{
list.Add(Convert.ToByte(s.Length));
var chars = s.ToCharArray();
list.AddRange(chars.Select(c => Convert.ToByte(Convert.ToInt32(c))));
}
list.AddRange(new byte[] { 0, 0, Convert.ToByte(15), 0, 1 });
var req = new byte[list.Count];
for (var i = 0; i < list.Count; i++) { req[i] = list[i]; }
udpClient.Send(req, req.Length);
// RECEIVE RESPONSE————–
IPEndPoint ep = null;
var receiveBuffer = udpClient.Receive(ref ep);
udpClient.Close();
var resp = new int[receiveBuffer.Length];
for (var i = 0; i < resp.Length; i++)
resp[i] = Convert.ToInt32(receiveBuffer[i]);
var status = resp[3];
if (status != 128) return null; // throw new Exception(string.Format(“{0}”, status));
var answers = resp[7];
if (answers == 0) return null; // throw new Exception(“No results”);
var pos = domain.Length + 18;
var lRecords = new List<string>();
while (answers > 0)
{
pos += 14; //offset
var str = GetMxRecord(resp, pos, out pos);
lRecords.Add(str);
answers–;
}
return lRecords;
}

private static string GetMxRecord(int[] resp, int start, out int pos)
{
StringBuilder sb = new StringBuilder();
int len = resp[start];
while (len > 0)
{
if (len != 192)
{
if (sb.Length > 0) sb.Append(“.”);
for (int i = start; i < start + len; i++)
sb.Append(Convert.ToChar(resp[i + 1]));
start += len + 1;
len = resp[start];
}
if (len != 192) continue;
var newPosition = resp[start + 1];
if (sb.Length > 0) sb.Append(“.”);
sb.Append(GetMxRecord(resp, newPosition, out newPosition));
start++;
break;
}
pos = start + 1;
return sb.ToString();
}
}

[Credit due to Christian Salway @ccsalway for this code]

This when called as Dns.MxLookup(“gmail.com”), would return a list of strings as follows;

"gmail-smtp-in.l.google.com",
"alt4.gmail-smtp-in.l.google.com",
"alt1.gmail-smtp-in.l.google.com",
"alt2.gmail-smtp-in.l.google.com",
"alt3.gmail-smtp-in.l.google.com"

These correspond to the mail exchange servers used by gmail, and indicate that the domain can receive email, otherwise, this function returns null.

Now, lets create an ASP.NET page that will act as a handler for an Ajax call to validate an email address as follows;

using System;
using System.Collections.Generic;
using Newtonsoft.Json;

public partial class ajax_ValidateEmail : System.Web.UI.Page
{
private class ResponseClass
{
public bool success { get; set; }
public string error { get; set; }
public IEnumerable<string> information { get; set; }
}

protected void Page_Load(object sender, EventArgs e)
{
var response = new ResponseClass();
var email = Request.QueryString[“email”];
if (string.IsNullOrEmpty(email))
{
response.error = “Need on email on querystring”;
}
else
{
var idxAt = email.IndexOf(“@”, StringComparison.CurrentCulture);
if (idxAt == -1)
{
response.error = “Invalid email address”;
}
else
{
var domain = email.Substring(idxAt+1);
var mx = Dns.MxLookup(domain);
if (mx == null)
{
response.error = “Invalid domain”;
}
else
{
response.success = true;
response.information = mx;
}
}
}
var json = JsonConvert.SerializeObject(response, Formatting.Indented);
Response.ContentType = “application/json”;
Response.Write(json);
}
}

This will respond with the following Json in the case of success;

{
  "success": true,
  "error": null,
  "information": [
    "gmail-smtp-in.l.google.com",
    "alt4.gmail-smtp-in.l.google.com",
    "alt1.gmail-smtp-in.l.google.com",
    "alt2.gmail-smtp-in.l.google.com",
    "alt3.gmail-smtp-in.l.google.com"
  ]
}

And, in the case of failure;

{
  "success": false,
  "error": "Invalid domain",
  "information": null
}

This can then be called from Javascript (jquery) as follows;

var strEmail = $(“#tbEmail”).val();
$.get(“/ajax/ValidateEmail.aspx?email=” + strEmail,
function(response) {
if (!response.success) {
$(“#fgEmail”).addClass(“has-error”);
} else {
$(“#fgEmail”).removeClass(“has-error”);
}
});

You can go a step further and prevent the form submission, at the moment, I’m just relaying user feedback, and see what happens.

To see this live, see https://www.regcheck.org.uk

 

Categories: Uncategorized

Using #Electron to call a .NET #API

Screenshot 2019-06-02 at 15.04.30

Electron is a platform that allows you develop desktop applications which are cross-platform, and run on standard HTML , CSS , Javascript and Node. The mix of typically client-and-“server side” javascript is very unusual, but quite liberating.

Here is a simple example of using Electron with an API that typically would be called by server-side Node, in a desktop app here –

https://github.com/infiniteloopltd/ElectronRegCheck

It’s not really that much beyond the “hello world” example, but shows the basics of using a simple user interface, and calling an API.

The code in “renderer.js” is as follows;

var api = require(‘car-registration-api-uk’);
window.$ = window.jQuery = require(‘jquery’);

$(init);
function init()
{
$(“#btnSearch”).bind(“click”,btnSearch_click);
}

function btnSearch_click()
{
var reg = $(“#reg”).val();
api.CheckCarRegistrationUK(reg,”*** your username here***”,function(data){
$(“#output”).html(data.Description);
});
}

You’ll need an account on RegCheck.org.uk for this to work.

Categories: Uncategorized