ASP 101 - Active Server Pages 101 - Web01
The Place ASP Developers Go!

Please visit our partners


Windows Technology Windows Technology
15 Seconds
4GuysFromRolla.com
ASP 101
ASP Wire
VB Forums
VB Wire
WinDrivers.com
internet.commerce internet.commerce
Partners & Affiliates














ASP 101 is an
internet.com site
ASP 101 is an internet.com site
IT
Developer
Internet News
Small Business
Personal Technology

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

ASP 101 News Flash ASP 101 News Flash



 Top ASP 101 Stories Top ASP 101 Stories
The Top 10 ASP Links @ Microsoft.com
What is Adovbs.inc and Why Do I Need It?
An Overview of ASP.NET

QUICK TIP:
Avoid unnecessary window switching
Show All Tips >>
ASP 101 RSS Feed ASP 101 Updates


Validating Email Addresses with ASP

by Hojjat Salmasian

Introduction

People submit email addresses as well as other types of information in web forms every day (from the "To:" box of email compose page, to the "Verify email address" field which we complete when registering a pay pal account.) Usually, the information you submit is checked on the server side and you will be asked to fix possible errors, if any. This procedure is called "form validation". But you may have noticed the low level of validation of email addresses you submit in the form, which is usually restricted to only confirming that the email address submitted has "@" and "." signs within.
 

Note: An article about complete form validation in ASP is available here.

Finger is one of TCP/IP services, used to reconfirm the existence of an account on a server. You can finger "hojjat@domain.com" to ensure that "domain.com" mail server has a "hojjat" email account. But for privacy reasons, most mail servers turn this service off. That is why the email address one provides in a web form can not be "completely" verified on the server side. But this is not the end of the story ...!

Note: Finger is actually used to locate people on other Internet sites

There is another service called MX Lookup. By using this we can ensure that "domain.com" is a mail server. (Actually MX stands for Mail eXchange and MX Lookup means to look for registered MX records on a DNS.) This way we can at least prevent fake/misspelled email addresses at host level.

What we are going to do in this article is to design a page that can get an email address, validate it by performing a MX lookup, and return an error message if the email address failed to pass the MX lookup test.

Strategy

Obviously we have to perform some server side checking. Unfortunately ASP does not have a built-in feature to be used for MX lookup. But you can find this feature on all NT based Windows operating systems (which of course includes the server versions, Windows 2000 and Windows 2003, as well as your own Windows XP Home Edition, etc.) On the command prompt you can run nslookup.exe to perform Name Server lookups, and by setting some options, you can restrict this tool to only look for MX records on the name server. So one strategy can be to develop a code which can run nslookup, get the results, process them, and report the validity of email address.

The above strategy is fast and reliable, but many web hosts prevent users from executing programs from inside ASP, because of security reasons. If this is the case, we can change our strategy: There are several web sites on the Internet which perform MX lookups for free. All you do is to enter the email address, and the site will automatically perform the lookup, and report the results to you. Thus the second strategy is to develop an ASP solution capable to connect to such a web site, send the required information, receive the reports, process it, and finally report the validity of email address.

Each of the above two strategies are explained below, separately. But before we start I have to state the both services use some Microsoft features commonly found on Windows based web hosts, thus, unfortunately, these may not work on Unix/Linux based web hosts.

Strategy #1: Running nslookup.exe

Lets get familiar with nslookup.exe first.
 

First of all we go to Command Prompt by clicking on Start, then Run..., then typing %comspec% and hitting OK. Then we can test nslookup.exe to get the MX records for a mail server (here yahoo.com) by typing:

nslookup -type=mx yahoo.com

Note: %comspec% is a substitute for cmd.exe (windows 2000 and above) or command.com (windows 98 and ME.)

What we get is like this:


 

If the ASP user has enough permissions set to execute programs on the server, then it can run nslookup.exe just as above with such a code:

FUNCTION MXLookup(host)
  SET objShell = Server.CreateObject("Wscript.Shell")
  DIM objExec, strResult

  SET objExec = objShell.Exec("%comspec% /c nslookup -type=MX yahoo.com")
  WHILE objExec.Status <> WshFinished
    'Wait for the command to be run completely 
  WEND
  strResult = objExec.StdOut.ReadAll
  Response.Write replace(strResult,Chr(13),"<br>")
END FUNCTION

Note: On Windows servers, the ASP user is actually the Internet Guest Account. Its name is IUSR_computername and in our case, it must at least have "Read and Execute" permission on cmd.exe or command.exe file in %windir%\system32 or %windir% directory, respectively.

The above code uses Windows Script Host component to create a shell object which allows ASP to run commands, and perform many other useful actions. When nslookup finishes, a string is sent back to the ASP user, which is saved in strResult. This string uses carriage return character ( equal to Chr(13) in ASP) at the end of each line to go to a new line. We use HTML <br> command for new line, so we have to replace carriage returns with <br>, the code of which is placed in the last line of the function.

You may have noticed that function gets a host argument but is not using it. This is our next step: To change the function to lookup for the host given to it, and return "Accepted" if there is a MX records found for the host, or "Denied" if there is not. Here is the code:

FUNCTION MXLookup(host)
  SET objShell = Server.CreateObject("Wscript.Shell")
  DIM objExec, strResult
  SET objExec = objShell.Exec("%comspec% /c nslookup -type=MX " & host)
  WHILE objExec.Status <> WshFinished
    'Wait for the command to be run completely 
  WEND
  strResult = objExec.StdOut.ReadAll
  Reflect(strResult)
END FUNCTION
FUNCTION Reflect(str)
  DIM lines, accepted : accepted = -1
  lines = Split(str,chr(13))
  FOR i = 0 TO UBound(lines)
    IF InStr(lines(i),"MX preference = ") > 0 THEN
     accepted = i
     EXIT FOR
    END IF
  NEXT
  IF accepted > -1 THEN
    Response.Write "Accepted: " & lines(accepted)
  ELSE
    Response.Write "Denied! "
  END IF
END FUNCTION

The second function searches the resulted string for "MX preference = " phrase. If nslookup has found at least one MX record for the given host, it will report it by using the above phrase. (Please look at the example again.) If "MX preference = " phrase is found, the function returns the line with the phrase, otherwise it reports "Denied!". Finally we complete our MX Lookup page as such (naming it MXlookup.asp):

<%@LANGUAGE="VBSCRIPT"%>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>MX Lookup</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<form action="MXlookup.asp" method="get">
<p> Enter the host name for MX lookup:   
<input name="host" type="text" id="host" size="40" value="<%=Request.QueryString("host")%>" />
     
<input type="submit" value=" Lookup " />
</p>
</form>
<%
IF Request.QueryString("host")<>"" THEN MXLookup(Request.QueryString("host"))
FUNCTION MXLookup(host)
  SET objShell = Server.CreateObject("Wscript.Shell")
  DIM objExec, strResult
  SET objExec = objShell.Exec("%comspec% /c nslookup -type=MX "&host)
  WHILE objExec.Status <> WshFinished
    'Wait for the command to be run completely 
  WEND
  strResult = objExec.StdOut.ReadAll
  Reflect(strResult)
END FUNCTION
FUNCTION Reflect(str)
  DIM lines, accepted : accepted = -1
  lines = Split(str,chr(13))
  FOR i = 0 TO UBound(lines)
   IF InStr(lines(i),"MX preference = ") > 0 THEN
     accepted = i
     EXIT FOR
   END IF
  NEXT
  IF accepted > -1 THEN
   Response.Write "Accepted: " & lines(accepted)
  ELSE
   Response.Write "Denied! "
  END IF
END FUNCTION
%>
</body>
</html>

The above code is fast and reliable. How ever, it has restrictions. As we stated above the ASP user must have enough permissions to run %comspec% on the server. Also, there is a probability that Windows Script Host is not available on the server.

Strategy #2: Using free MX lookup web sites

The second strategy uses another feature in ASP named XMLHTTP. An object made from XMLHTTP class is used to connect to other servers, send and receive data, which is used to be processed and/or shown to the user. You can send both GET and POST types of HTTP request, and get the returned code by the server, all in server side. (It is actually like that ASP user is a human, connecting to that web site with a browser, and copy the results and paste it to YOU as it's user!)

Note: If you need more information about the XMLHTTP component, here's a good resource for you.

No parts of our previous code are going to change except the MXLookup function. But before we write the whole code for this function, let's start with a test function that introduces XMLHTTP to you:

FUNCTION MXLookup(host)
  MXLookUp = False
  Dim objXMLHTTP,strResult
  Set objXMLHTTP = Server.CreateObject("Microsoft.XMLHTTP")
  objXMLHTTP.Open "Get","http://www.asp101.com", False
  objXMLHTTP.Send
  strResult = objXMLHTTP.ResponseText
  Response.Write strResult
END FUNCTION

The above code connects to the asp101 web site, retrieves data from it, and then Response.Writes the result to you, so you can see the asp101 page in your self-created ASP page!

Just as simple as you placed "http://www.asp101.com" in the Open method of objXMLHTTP object, you can put a URL with a query string, like "http://www.domain.com?lang=fr" and get the results (the French version of an assumptive domain.com web site) and return it to the user. You can also process the data received from the remote site on you server side, and report the results to your user. And this is the key point in our MXLookup function ....

In the following example, MXLookup function connects to a page in examples.softwaremodeles.com web site, which performs MX lookups. The IntraDns.asp file on that site needs a query string like domainname=hostname and returns several DNS records for that site. There is an option named t_mx which, if checked, can make the IntraDns.asp understand that it must only return MX records. We use this to get faster responses from that server. So what we are going to send to the remote server is like: http://examples.softwaremodules.com/IntraDns.asp?domainname=host&Submit=Submit&t_mx=1 where host is substituted by the host name sent to our MXLookup function. Here is the code:

FUNCTION MXLookup(host)
  MXLookUp = False
  Dim objXMLHTTP,strResult
  Set objXMLHTTP = Server.CreateObject("Microsoft.XMLHTTP")
  objXMLHTTP.Open "Get", _
    "http://examples.softwaremodules.com/IntraDns.asp?domainname=" & host & "&Submit=Submit&t_mx=1", False
  objXMLHTTP.Send
  strResult = objXMLHTTP.ResponseText
  strResult = Mid(strResult,InStr(strResult,"(MX) for <strong>"),100)
  strResult = Mid(strResult,Instr(strResult,"</strong>. Items Returned: <strong>")+35,1)
  IF CInt(strResult) > 0 THEN
    MXLookUp = TRUE
  ELSE
    MXLookUp = FALSE
  END IF
END FUNCTION

As you may have noticed, the above code processes the returned string too. Actually, the IntraDns.asp file on the remote server returns the MX records, if any in such format:

DNS Lookup (MX) for yahoo.com. Items Returned: 4
  • mx4.mail.yahoo.com - MX Priority: 5

  • mx1.mail.yahoo.com - MX Priority: 1

  • mx2.mail.yahoo.com - MX Priority: 1

  • mx3.mail.yahoo.com - MX Priority: 1

  • Therefore, our MXLookup function looks for phrase "(MX) for <strong>" in the returned HTML, and if it is found, it looks for the number of MX records found by IntraDns.asp somewhere more than 35 characters after the "MX for <strong>" phrase. To be more precise, it only read the FIRST digit from the LEFT side, of that number. This digit is "0" only if the number of MX records was zero. If three records are found, the first digit from the left side is "3". If twenty MX records are found, the first left digit is "2".

    I used the double-quotes wisely in the last three sentences! Yes, the first left digit is a String now! We have to change it to an integer (using CInt() method), and then compare it with 0. If it is greater than 0, our function returns TRUE, else it returns FALSE.

    We can use this function in our code to report "Accepted." or "Denied!", just like our first strategy. Here is the code:

    <%@LANGUAGE="VBSCRIPT"%>
    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>MX Lookup</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    </head>
    <body>
    <form action="MXlookup.asp" method="get">
    <p> Enter the host name for MX lookup:   
    <input name="host" type="text" id="host" size="40" value="<%=Request.QueryString("host")%>" />
         
    <input type="submit" value=" Lookup " />
    </p>
    </form>
    <%
    IF Request.QueryString("host")<>"" THEN
      result = MXLookup(Request.QueryString("host"))
      IF result = TRUE THEN
        Response.Write "Accepted."
      ELSE
        Response.Write "Denied!"
      END IF
    END IF
    FUNCTION MXLookup(host)
      MXLookUp = False
      Dim objXMLHTTP,strResult
      Set objXMLHTTP = Server.CreateObject("Microsoft.XMLHTTP")
      objXMLHTTP.Open "Get", _
        "http://examples.softwaremodules.com/IntraDns.asp?domainname=" & host & "&Submit=Submit&t_mx=1", False
      objXMLHTTP.Send
      strResult = objXMLHTTP.ResponseText
      strResult = Mid(strResult,InStr(strResult,"(MX) for <strong>"),100)
      strResult = Mid(strResult,Instr(strResult,"</strong>. Items Returned: <strong>")+35,1)
      IF CInt(strResult) > 0 THEN
        MXLookUp = TRUE
      ELSE
        MXLookUp = FALSE
      END IF
    END FUNCTION
    %>
    </body>
    </html>

    You can change the above code a bit, to let it show the first MX record found for accepted hosts, just as the MXLookup function in our first strategy did.

    This second strategy is not as reliable as the first one. Simply, if the remote web site changes the format of the result returned by IntraDns.asp file, it can hardly affect your ASP code. As it usually takes some time for you to find out such a problem, it means your users will face several problems during that period of time. A possible solution to this is to reach to a consensus with the owner of the remote site, to be informed before any changes happen to their site, or something. This article is not going to teach you how to do this, of course! ;o)

    Another situation in which the second strategy will not work is when XMLHTTP component is not available on the server hosting your ASP codes.

    The second disadvantage of this strategy is it is slow, and uses more resources on the server. So try to manage to use the first strategy if you are planning to validate many email addresses every day.

    Author Notes

    A friend ran my code on his Windows 2000 web server, but the code didn't work for him. He also had problems with opening recordset objects, when they were going to be filled by hand (not from a database.) We made our efforts to solve his issue, and finally found out that some helpful information in this microsoft KB article:

    How to set required NTFS permissions and user rights for an IIS 5.0 Web server.

    If you are facing a similar error, you might want to give it a look!

    Download

    You can download a copy of both versions of the code in a zip file from here: mxlookup.zip (1.8 KB).


    Home |  News |  Samples |  Articles |  Lessons |  Resources |  Forum |  Links |  Search |  Feedback

    Internet.com
    The Network for Technology Professionals

    Search:

    About Internet.com

    Legal Notices, Licensing, Permissions, Privacy Policy.
    Advertise | Newsletters | E-mail Offers