如何使用 System.Net.DNS 获取 dns 名称的 mx 记录?

发布于 2024-08-29 02:54:50 字数 1539 浏览 5 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

笑看君怀她人 2024-09-05 02:54:50

更新 2018/5/23

查看 MichaC 的回答,了解具有 .NET 的较新库标准支持。

原始答案:

Alexander 的 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)数据包,例如你可能会期望。该库甚至具有发现要查询哪个 DNS 服务器的逻辑(通过 DnsClient.Default 调用)。

完整文档可以在此处找到。

Update 2018/5/23:

Check out MichaC's answer for a newer library that has .NET standard support.

Original Answer:

The ARSoft.Tools.Net library by Alexander Reinert seems to do the job pretty well.

It's available from NuGet:

PM> Install-Package ARSoft.Tools.Net

Import the namespace:

using ARSoft.Tools.Net.Dns;

Then making a synchronous lookup is as simple as:

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

Which gives us the output:

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.

Underneath the hood, it looks like the library constructs the UDP (or TCP) packets necessary to send to the resolver, like you might expect. The library even has logic (invoked with DnsClient.Default) to discover which DNS server to query.

Full documentation can be found here.

失退 2024-09-05 02:54:50

只是扮演我自己的库,因为没有任何 .net core / xplat 支持... https://github。 com/MichaCo/DnsClient.NET

它工作得非常好,如果你愿意的话,它可以为你提供挖掘之类的日志消息。

使用简单

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

,可与在任何端口、多个服务器等上运行的自定义服务器配合使用...

另请参阅 DnsClient 网站更多细节

Just roled my own library because there was nothing for .net core / xplat support... https://github.com/MichaCo/DnsClient.NET

It works pretty great and gives you dig like log messages if you want.

Simple to use

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

and works with custom servers running on any ports, multiple servers, etc...

see also DnsClient Website for more details

我们只是彼此的过ke 2024-09-05 02:54:50

我花了一整天的时间弄清楚如何发送/接收 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; } }
}

I spent all day figuring out how to send/receive dns requests and came up with this. Its a complete generic handler. You just have to set the dns server and pass in 'd' eg. 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; } }
}
瑾兮 2024-09-05 02:54:50

我的方法是使用 nslookup.exe 来检索 MX 记录。

解决方案并不像重写整个 DNS 或使用系统 DLL 那样奇特 ->但它可以工作,只需少量的线条。

为了让事情正确,这段代码>正常工作<它资源效率不高,速度也不快,并且有很大的改进空间(多个主机名,异步,更有用的返回值,添加优先级):

    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();
        return lines;
    }

应该国际化,因为 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

My approach was to use nslookup.exe to retreive the MX record.

The solution is not as fancy as rewriting whole DNS or using a System DLL -> but it works, with a little amount of lines.

To get things right, this code >just works< it's not ressource efficient nor fast and has a lots of room for improvment (multiple hostnames, async, more usefull return value,adding the priority):

    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();
        return lines;
    }

Should be working international, since nslookup does not support any translation (I'm working on a German machine and I'm getting english output).

The result are strings like this:

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
一萌ing 2024-09-05 02:54:50

接受的答案不适用于 .NET Framework < 4.5,所以建议那些不能使用 ARSOFT.Tools 的人可以使用 https://dndns.codeplex 中的 DNDN .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();
        }            
    }
}
}

The accepted answer doesn't work for .NET framework < 4.5, so would suggest that those of you who can't use ARSOFT.Tools can use DNDNs from https://dndns.codeplex.com

Given below is a console application that returns the MX record for a given domain modifying their examples.

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();
        }            
    }
}
}
2024-09-05 02:54:50

这是我仅用来查找 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)
                uint TTL = (recBuf[index] * 16777216u) + (recBuf[index + 1] * 65536u) + (recBuf[index + 2] * 256u) + 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;
        }
        

Here is a Class I use to look up MX records only.

    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)
                uint TTL = (recBuf[index] * 16777216u) + (recBuf[index + 1] * 65536u) + (recBuf[index + 2] * 256u) + 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;
        }
    }
}

Here is how you use it.

/// <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;
        }
        
感性不性感 2024-09-05 02:54:50

我写了一个简单的 URL,表示

https://devselz.com/social/sign/buttons/dashboard/default.aspx?a=ciee&[email protected]

不要滥用,

如果电子邮件存在或可能存在,则返回 1,如果不存在,则返回 0

非常适合检查:

  • gmail 和 gmail pro(域不是 @gmail)帐户。
  • hotmail

对于像 yahoo 这样的其他人总是返回 1

I wrote a simply URL for that means

https://devselz.com/social/sign/buttons/dashboard/default.aspx?a=ciee&[email protected]

Do not abuse

Return 1 if email exists or may exist, 0 if not

Works great in order to check:

  • gmail and gmail pro (domains not @gmail) accounts.
  • hotmail

For others like yahoo always returns 1

ゞ记忆︶ㄣ 2024-09-05 02:54:50

您可以使用此开源库来几乎可以执行您通常需要的任何类型的查询。

用法:

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);

You can use this open source library to do almost any kind of query you would usually need.

Usage:

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文