2010-04-19 82 views
36

.NET庫中是否有任何內置方法會返回給定域的所有MX記錄?我看到你如何得到CNAMES,但不是MX記錄。如何使用System.Net.DNS獲取dns名稱的mx記錄?

+0

參見[這](http://www.csharphelp.com/2005/12/dns-client-utility/)博客文章 - 這個傢伙寫了使用原始UDP的MX客戶端端口。單個文件類,所以你應該能夠按原樣使用它。 – Oded 2010-04-19 18:34:56

+0

另一個簡單的解決方案是執行nslookup -q = mx命令並讀取響應。此處的工作代碼http://www.c-sharpcorner.com/uploadfile/40e97e/verify-email-online/ – shrutyzet 2013-04-02 08:22:14

+0

此頁面上的代碼使用'DLLImport'來調用本地Windows功能,並可在32/64位環境中工作。完整的源代碼包括:http://pinvoke.net/default.aspx/dnsapi.DnsQuery – 2011-10-28 19:37:48

回答

37

ARSoft.Tools.Net庫由亞歷山大·賴納特似乎做的工作相當不錯。

這是從的NuGet:

PM> Install-Package ARSoft.Tools.Net 

導入命名空間:

using ARSoft.Tools.Net.Dns; 

然後又做了同步查找,就這麼簡單:

var resolver = new DnsStubResolver(); 
var records = resolver.Resolve<MxRecord>("gmail.com", RecordType.Mx); 
foreach (var record in records) { 
    Console.WriteLine(record.ExchangeDomainName?.ToString()); 
} 

這給我們的輸出:

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. 
alt4.gmail-smtp-in.l.google.com. 

在引擎蓋下面,它看起來像庫構造了發送到解析器所需的UDP(或TCP)數據包,就像您所期望的那樣。該庫甚至具有邏輯(通過DnsClient.Default調用)來發現要查詢哪個DNS服務器。

完整的文檔可以發現here

+1

不錯。如果我再次需要這樣做,我會使用它。 – Segfault 2014-08-25 18:14:13

+0

ARSoft.Tools.Net非常棒! – Tohid 2015-03-11 15:45:32

9

我花了整天搞清楚如何發送/接收DNS請求,並提出了這個問題。它是一個完整的通用處理器你只需要設置DNS服務器並通過'D'例如。 my.website.com?d=itmanx.com

<%@ WebHandler Language="C#" Class="Handler" %> 

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

public class Handler : IHttpHandler 
{ 
    string dns = "dc1"; //change to your dns 
    string qtype = "15"; //A=1 MX=15 
    string domain = ""; 
    int[] resp; 

    public void ProcessRequest(HttpContext context) 
    { 
     context.Response.ContentType = "text/plain"; 

     try 
     { 
      if (context.Request["t"] != null) qtype = context.Request["t"]; 
      if (context.Request["d"] != null) domain = context.Request["d"]; 

      if (string.IsNullOrEmpty(domain)) throw new Exception("Add ?d=<domain name> to url or post data"); 

      Do(context); 
     } 
     catch (Exception ex) 
     { 
      string msg = ex.Message; 
      if (msg == "1") msg = "Malformed packet"; 
      else if (msg == "5") msg = "Refused"; 
      else if (msg == "131") msg = "No such name"; 

      context.Response.Write("Error: " + msg); 
     } 
    } 

    public void Do(HttpContext context) 
    { 
     UdpClient udpc = new UdpClient(dns, 53); 

     // SEND REQUEST-------------------- 
     List<byte> list = new List<byte>(); 
     list.AddRange(new byte[] { 88, 89, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 }); 

     string[] tmp = domain.Split('.'); 
     foreach (string s in tmp) 
     { 
      list.Add(Convert.ToByte(s.Length)); 
      char[] chars = s.ToCharArray(); 
      foreach (char c in chars) 
       list.Add(Convert.ToByte(Convert.ToInt32(c))); 
     } 
     list.AddRange(new byte[] { 0, 0, Convert.ToByte(qtype), 0, 1 }); 

     byte[] req = new byte[list.Count]; 
     for (int i = 0; i < list.Count; i++) { req[i] = list[i]; } 

     udpc.Send(req, req.Length); 


     // RECEIVE RESPONSE-------------- 
     IPEndPoint ep = null; 
     byte[] recv = udpc.Receive(ref ep); 
     udpc.Close(); 

     resp = new int[recv.Length]; 
     for (int i = 0; i < resp.Length; i++) 
      resp[i] = Convert.ToInt32(recv[i]); 

     int status = resp[3]; 
     if (status != 128) throw new Exception(string.Format("{0}", status)); 
     int answers = resp[7]; 
     if (answers == 0) throw new Exception("No results"); 

     int pos = domain.Length + 18; 
     if (qtype == "15") // MX record 
     { 
      while (answers > 0) 
      { 
       int preference = resp[pos + 13]; 
       pos += 14; //offset 
       string str = GetMXRecord(pos, out pos); 
       context.Response.Write(string.Format("{0}: {1}\n", preference, str)); 
       answers--; 
      } 
     } 
     else if (qtype == "1") // A record 
     { 
      while (answers > 0) 
      { 
       pos += 11; //offset 
       string str = GetARecord(ref pos); 
       context.Response.Write(string.Format("{0}\n", str)); 
       answers--; 
      } 
     } 
    } 

    //------------------------------------------------------ 
    private string GetARecord(ref int start) 
    { 
     StringBuilder sb = new StringBuilder(); 

     int len = resp[start]; 
     for (int i = start; i < start + len; i++) 
     { 
      if (sb.Length > 0) sb.Append("."); 
      sb.Append(resp[i + 1]); 
     } 
     start += len + 1; 
     return sb.ToString(); 
    } 
    private string GetMXRecord(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) 
      { 
       int newpos = resp[start + 1]; 
       if (sb.Length > 0) sb.Append("."); 
       sb.Append(GetMXRecord(newpos, out newpos)); 
       start++; 
       break; 
      } 
     } 
     pos = start + 1; 
     return sb.ToString(); 
    } 

    //------------------------------------------------------ 
    public bool IsReusable { get { return false; } } 
} 
+1

一些虛擬主機提供商不允許System.Net.SocketPermission。如果你得到「請求類型'System.Net.SocketPermission ...失敗'的權限,說出你的託管服務提供商很好:) – Christian 2011-09-25 16:26:44

+0

不錯的一個..謝謝你的努力:) – nonintanon 2012-01-17 18:15:04

+0

這是偉大的 - 感謝張貼這個。 – Ethan 2012-10-10 16:08:11

1

以下是我僅用於查找MX記錄的類。

using System; 
    using System.Text; 
    using System.Net; 
    using System.Net.Sockets; 
    using System.Collections.Specialized; 

    namespace Mx.Dns 
    { 
     public class Query 
     { 
      //Build a DNS query buffer according to RFC 1035 4.1.1 e 4.1.2 
      private readonly int id; 
     private readonly int flags; 
     private readonly int QDcount; 
     private readonly int ANcount; 
     private readonly int NScount; 
     private readonly int ARcount; 
     private readonly string Qname; 
     private readonly int Qtype; 
     private readonly int Qclass; 
     public byte[] buf; 

     public Query(int ID, string query, int qtype) 
     { 
      //init vectors with given + default values 
      id = ID; 
      flags = 256; 
      QDcount = 1; 
      ANcount = 0; 
      NScount = 0; 
      ARcount = 0; 
      Qname = query; 
      Qtype = qtype; 
      Qclass = 1; //Internet = IN = 1 

      //build a buffer with formatted query data 

      //header information (16 bit padding 
      buf = new byte[12 + Qname.Length + 2 + 4]; 
      buf[0] = (byte)(id/256); 
      buf[1] = (byte)(id - (buf[0] * 256)); 
      buf[2] = (byte)(flags/256); 
      buf[3] = (byte)(flags - (buf[2] * 256)); 
      buf[4] = (byte)(QDcount/256); 
      buf[5] = (byte)(QDcount - (buf[4] * 256)); 
      buf[6] = (byte)(ANcount/256); 
      buf[7] = (byte)(ANcount - (buf[6] * 256)); 
      buf[8] = (byte)(NScount/256); 
      buf[9] = (byte)(NScount - (buf[8] * 256)); 
      buf[10] = (byte)(ARcount/256); 
      buf[11] = (byte)(ARcount - (buf[10] * 256)); 
      //QNAME (RFC 1035 4.1.2) 
      //no padding 
      string[] s = Qname.Split('.'); 
      int index = 12; 
      foreach (string str in s) { 
       buf[index] = (byte)str.Length; 
       index++; 
       byte[] buf1 = Encoding.ASCII.GetBytes(str); 
       buf1.CopyTo(buf, index); 
       index += buf1.Length; 
      } 
      //add root domain label (chr(0)) 
      buf[index] = 0; 

      //add Qtype and Qclass (16 bit values) 
      index = buf.Length - 4; 
      buf[index] = (byte)(Qtype/256); 
      buf[index + 1] = (byte)(Qtype - (buf[index] * 256)); 
      buf[index + 2] = (byte)(Qclass/256); 
      buf[index + 3] = (byte)(Qclass - (buf[index + 2] * 256)); 
     } 
    } 
    public class C_DNSquery 
    { 
     public StringCollection result = new StringCollection(); 
     public int Error = 0; 
     public string ErrorTxt = "undefined text"; 
     public bool Done = false; 
     public UdpClient udpClient; 
     private string DNS; 
     private string Query; 
     private int Qtype; 
     public bool IS_BLACKLIST_QUERY = false; 
     public C_DNSquery(string IPorDNSname, string query, int type) 
     { 
      DNS = IPorDNSname; 
      Query = query; 
      Qtype = type; 
     } 
     public void doTheJob() 
     { 
      //check if provided DNS contains an IP address or a name 
      IPAddress ipDNS; 
      IPHostEntry he; 
      try { 
       //try to parse an IPaddress 
       ipDNS = IPAddress.Parse(DNS); 
      } catch (FormatException) { 
//    Console.WriteLine(e); 
       //format error, probably is a FQname, try to resolve it 
       try { 
        //try to resolve the hostname 
        he = Dns.GetHostEntry(DNS); 
       } catch { 
        //Error, invalid server name or address 
        Error = 98; 
        ErrorTxt = "Invalid server name:" + DNS; 
        Done = true; 
        return; 
       } 
       //OK, get the first server address 
       ipDNS = he.AddressList[0]; 
      } 

      //Query the DNS server 
      //our current thread ID is used to match the reply with this process 

      Query myQuery = new Query(System.Threading.Thread.CurrentThread.ManagedThreadId, Query, Qtype); 
      //data buffer for query return value 
      Byte[] recBuf; 

      //use UDP protocol to connect 
      udpClient = new UdpClient(); 
      do { 
       try { 
        //connect to given nameserver, port 53 (DNS) 
        udpClient.Connect(DNS, 53); 
        //send query 
        udpClient.Send(myQuery.buf, myQuery.buf.Length); 
        //IPEndPoint object allow us to read datagrams.. 
        //..selecting only packet coming from our nameserver and port 
        IPEndPoint RemoteIpEndPoint = new IPEndPoint(ipDNS, 53); 
        //Blocks until a message returns on this socket from a remote host. 
        recBuf = udpClient.Receive(ref RemoteIpEndPoint); 
        udpClient.Close(); 
       } catch (Exception e) { 
        //connection error, probably a wrong server address 
        udpClient.Close(); 
        Error = 99; 
        ErrorTxt = e.Message + "(server:" + DNS + ")"; 
        Done = true; 
        return; 
       } 
       //repeat until we get the reply with our threadID 
      } while (System.Threading.Thread.CurrentThread.ManagedThreadId != ((recBuf[0] * 256) + recBuf[1])); 

      //Check the DNS reply 
      //check if bit QR (Query response) is set 
      if (recBuf[2] < 128) { 
       //response byte not set (probably a malformed packet) 
       Error = 2; 
       ErrorTxt = "Query response bit not set"; 
       Done = true; 
       return; 
      } 
      //check if RCODE field is 0 
      if ((recBuf[3] & 15) > 0) { 
       //DNS server error, invalid reply 
       switch (recBuf[3] & 15) { 
        case 1: 
         Error = 31; 
         ErrorTxt = "Format error. The nameserver was unable to interpret the query"; 
         break; 
        case 2: 
         Error = 32; 
         ErrorTxt = "Server failure. The nameserver was unable to process the query."; 
         break; 
        case 3: 
         Error = 33; 
         ErrorTxt = "Name error. Check provided domain name!!"; 
         break; 
        case 4: 
         Error = 34; 
         ErrorTxt = "Not implemented. The name server does not support the requested query"; 
         break; 
        case 5: 
         Error = 35; 
         ErrorTxt = "Refused. The name server refuses to reply for policy reasons"; 
         break; 
        default: 
         Error = 36; 
         ErrorTxt = "Unknown. The name server error code was: " + Convert.ToString((recBuf[3] & 15)); 
         break; 
       } 
       Done = true; 
       return; 
      } 
      //OK, now we should have valid header fields 
      int QDcnt, ANcnt, NScnt, ARcnt; 
      int index; 
      QDcnt = (recBuf[4] * 256) + recBuf[5]; 
      ANcnt = (recBuf[6] * 256) + recBuf[7]; 
      NScnt = (recBuf[8] * 256) + recBuf[9]; 
      ARcnt = (recBuf[10] * 256) + recBuf[11]; 
      index = 12; 
      //sometimes there are no erros but blank reply... ANcnt == 0... 
      if (ANcnt == 0) { // if blackhole list query, means no spammer !!//if ((ANcnt == 0) & (IS_BLACKLIST_QUERY == false)) 
       //error blank reply, return an empty array 
       Error = 4; 
       ErrorTxt = "Empty string array"; 
       Done = true; 
       return; 
      } 

      //Decode received information 
      string s1; 
      // START TEST 
      s1 = Encoding.ASCII.GetString(recBuf, 0, recBuf.Length); 
      // END TEST 

      if (QDcnt > 0) { 
       //we are not really interested to this string, just parse and skip 
       s1 = ""; 
       index = parseString(recBuf, index, out s1); 
       index += 4; //skip root domain, Qtype and QClass values... unuseful in this contest 
      } 
      if (IS_BLACKLIST_QUERY) { 
       // get the answers, normally one ! 
       // int the four last bytes there is the ip address 
       Error = 0; 
       int Last_Position = recBuf.Length - 1; 
       result.Add(recBuf[Last_Position - 3].ToString() + "." + recBuf[Last_Position - 2].ToString() + "." + recBuf[Last_Position - 1].ToString() + "." + recBuf[Last_Position].ToString()); 
       Done = true; 
       return; 
      } 
      int count = 0; 
      //get all answers 
      while (count < ANcnt) { 
       s1 = ""; 
       index = parseString(recBuf, index, out s1); 
       //Qtype 
       int QType = (recBuf[index] * 256) + recBuf[index + 1]; 
       index += 2; 
       s1 += "," + QType.ToString(); 
       //QClass 
       int QClass = (recBuf[index] * 256) + recBuf[index + 1]; 
       index += 2; 
       s1 += "," + QClass.ToString(); 
       //TTL (Time to live) 
       int TTL = (recBuf[index] * 16777216) + (recBuf[index + 1] * 65536) + (recBuf[index + 2] * 256) + recBuf[index + 3]; 
       index += 4; 
       s1 += "," + TTL.ToString(); 
       int blocklen = (recBuf[index] * 256) + recBuf[index + 1]; 
       index += 2; 
       if (QType == 15) { 
        int MXprio = (recBuf[index] * 256) + recBuf[index + 1]; 
        index += 2; 
        s1 += "," + MXprio.ToString(); 
       } 
       string s2; 
       index = parseString(recBuf, index, out s2); 
       s1 += "," + s2; 
       result.Add(s1); 
       count++; 
      } 
      Error = 0; 
      Done = true; 
     } 
     private int parseString(byte[] buf, int i, out string s) 
     { 
      int len; 
      s = ""; 
      bool end = false; 
      while (!end) { 
       if (buf[i] == 192) { 
        //next byte is a pointer to the string, get it.. 
        i++; 
        s += getString(buf, buf[i]); 
        i++; 
        end = true; 
       } else { 
        //next byte is the string length 
        len = buf[i]; 
        i++; 
        //get the string 
        s += Encoding.ASCII.GetString(buf, i, len); 
        i += len; 
        //check for the null terminator 
        if (buf[i] != 0) { 
         //not null, add a point to the name 
         s += "."; 
        } else { 
         //null char..the string is complete, exit 
         end = true; 
         i++; 
        } 
       } 
      } 
      return i; 
     } 
     private string getString(byte[] buf, int i) 
     { 
      string s = ""; 
      int len; 
      bool end = false; 
      while (!end) { 
       len = buf[i]; 
       i++; 
       s += Encoding.ASCII.GetString(buf, i, len); 
       i += len; 
       if (buf[i] == 192) { 
        i++; 
        s += "." + getString(buf, buf[i]); 
        return s; 
       } 
       if (buf[i] != 0) { 
        s += "."; 
       } else { 
        end = true; 
       } 
      } 
      return s; 
     } 
    } 
} 

這裏是你如何使用它。

/// <summary> 
     /// Get the MX from the domain address. 
     /// </summary> 
     public static string getMXrecord(string domain) 
     { 
      domain = domain.Substring(domain.IndexOf('@') + 1); 
      string LocalDNS = GetDnsAdress().ToString(); 
      Console.WriteLine("domain: " + domain); 

      // resolv the authoritative domain (type=2) 
      C_DNSquery DnsQry = new C_DNSquery(LocalDNS, domain, 2); 
      Thread t1 = new Thread(new ThreadStart(DnsQry.doTheJob)); 
      t1.Start(); 
      int timeout = 20; 
      while ((timeout > 0) & (!DnsQry.Done)) { 
       Thread.Sleep(100); 
       timeout--; 
      } 
      if (timeout == 0) { 
       if (DnsQry.udpClient != null) { 
        DnsQry.udpClient.Close(); 
       } 
       t1.Abort(); 
       DnsQry.Error = 100; 
      } 

      string[] ns1; 
      string MyNs = ""; 
      if (DnsQry.Error == 0) { 
       ns1 = DnsQry.result[0].Split(','); 
       MyNs = ns1[4]; 
       t1.Abort(); 
      } else { 
       t1.Abort(); 
       MyNs = LocalDNS; 
      } 

      // Resolve MX (type = 15) 
      DnsQry = new C_DNSquery(MyNs, domain, 15); 
      Thread t2 = new Thread(new ThreadStart(DnsQry.doTheJob)); 
      t2.Start(); 
      timeout = 20; 
      string TTL = ""; 
      string MXName = ""; 
      Int32 preference = 9910000; 
      while ((timeout > 0) & (!DnsQry.Done)) { 
       Thread.Sleep(100); 
       timeout--; 
      } 
      if (timeout == 0) { 
       if (DnsQry.udpClient != null) { 
        DnsQry.udpClient.Close(); 
       } 
       t2.Abort(); 
       DnsQry.Error = 100; 
      } 
      if (DnsQry.Error == 0) { 

       if (DnsQry.result.Count == 1) { 
        string[] ns2 = DnsQry.result[0].Split(','); 
        MXName = ns2[5]; 
        TTL = ns2[3]; 
        preference = Int32.Parse(ns2[4]); 
        Console.WriteLine("domaine: {0} MX: {1} time: {2} pref: {3} ttl: {4}", domain.Substring(domain.IndexOf('@') + 1), MXName, 
         DateTime.Now, preference, TTL); 


       } else { 
        for (int indns = 0; indns <= DnsQry.result.Count - 1; indns++) { 
         string[] ns2 = DnsQry.result[indns].Split(','); 
         if (Int32.Parse(ns2[4]) < preference) { 
          MXName = ns2[5]; 
          TTL = ns2[3]; 
          preference = Int32.Parse(ns2[4]); 
Console.WriteLine("domain: {0} MX: {1} time: {2} pref: {3} ttl: {4}", domain.Substring(domain.IndexOf('@') + 1), MXName, 
           DateTime.Now, preference, TTL); 

          } 
        } 
       } 
      } 
      return MXName; 
     } 
3

樂雷只是我自己的圖書館,因爲沒有什麼對.NET的核心/ xplat支持... https://github.com/MichaCo/DnsClient.NET

它的工作原理非常偉大的,如果你想給你喜歡的日誌信息。

簡單易用

var lookup = new LookupClient(); 
var result = await lookup.QueryAsync("google.com", QueryType.ANY); 

和作品與任何端口,多臺服務器,運行等定製服務器...

DnsClient Website詳見

3

接受的答案沒有按」 t工作於.NET框架< 4.5,所以會建議那些不能使用ARSOFT.Tools的人可以使用DNDNs https://dndns.codeplex.com

下面給出的是一個控制檯應用程序,它返回給定域的MX記錄,修改它們的示例。

using System; 
using System.Net.Sockets; 
using DnDns.Enums; 
using DnDns.Query; 
using DnDns.Records; 

namespace DnDnsExamples 
{ 
class Program 
{ 
    static void Main(string[] args) 
    { 
     DnsQueryRequest request3 = new DnsQueryRequest(); 
     DnsQueryResponse response3 = request3.Resolve("gmail.com", NsType.MX, NsClass.INET, ProtocolType.Tcp); 
     OutputResults(response3); 
     Console.ReadLine(); 
    } 

    private static void OutputResults(DnsQueryResponse response) 
    { 
     foreach (IDnsRecord record in response.Answers) 
     { 
      Console.WriteLine(record.Answer); 
      Console.WriteLine(" |--- RDATA Field Length: " + record.DnsHeader.DataLength); 
      Console.WriteLine(" |--- Name: " + record.DnsHeader.Name); 
      Console.WriteLine(" |--- NS Class: " + record.DnsHeader.NsClass); 
      Console.WriteLine(" |--- NS Type: " + record.DnsHeader.NsType); 
      Console.WriteLine(" |--- TTL: " + record.DnsHeader.TimeToLive); 
      Console.WriteLine(); 
     }    
    } 
} 
} 
1

我的方法是使用nslookup.exe來檢索MX記錄。

該解決方案不如重寫整個DNS或使用系統DLL - >但它的工作原理,少量的線。

把事情做好,這個代碼>只是工作<它不是的ressource效率,也不快,有大量的空間,改良效果(多主機名,異步更多有用的返回值,將優先級):

static List<string> GetMxRecords(string host){ 
    ProcessStartInfo nslookup_config = new ProcessStartInfo("nslookup.exe"); 
    nslookup_config.RedirectStandardInput = true; 
    nslookup_config.RedirectStandardOutput = true; 
    nslookup_config.RedirectStandardError = true; 
    nslookup_config.UseShellExecute = false; 
    var nslookup = Process.Start(nslookup_config); 
    nslookup.StandardInput.WriteLine("set q=mx"); 
    nslookup.StandardInput.WriteLine(host); 
    nslookup.StandardInput.WriteLine("exit"); 
    List<string> lines = new List<string>(); 
    while (!nslookup.StandardOutput.EndOfStream) 
    { 
     string l = nslookup.StandardOutput.ReadLine(); 
     if (l.Contains("internet address =")) 
     { 
      while (l.Contains("\t\t")) 
      { 
       l = l.Replace("\t\t", "\t"); 
      } 
      lines.Add(l.Replace("\tinternet address = ","=")); 
     } 
    } 
    nslookup.Close(); 
} 

應該是國際性的,因爲nslookup不支持任何翻譯(我在德國的機器上工作,我得到英文輸出)。

結果是字符串這樣的:

alt4.gmail-smtp-in.l.google.com=74.125.28.27 
alt2.gmail-smtp-in.l.google.com=74.125.200.27 
alt1.gmail-smtp-in.l.google.com=209.85.233.26 
gmail-smtp-in.l.google.com=66.102.1.27 
alt3.gmail-smtp-in.l.google.com=108.177.97.27 
+0

這是一個很好的方法,感謝分享! – Segfault 2017-07-20 13:56:51

-1

您可以使用this open source庫做幾乎任何類型的查詢你通常需要。

用法:

DnsClient dnsClient = new DnsClient(); 
string mxDomain = dnsClient.ResolveMX("example.com"); 
string mxDomainIP = dnsClient.ResolveMX("example.com", true); 
string mxDomainIPv6 = dnsClient.ResolveMX("example.com", true, true);