Exemplo n.º 1
0
Arquivo: Smtp.cs Projeto: aooshi/adf
            /// <summary>
            /// 按域进行无代理发送
            /// </summary>
            /// <param name="domain"></param>
            /// <param name="message"></param>
            /// <exception cref="Adf.SmtpException"></exception>
            public void SendNoPorxy(string domain, MailMessage message)
            {
                const int port = 25;

                //mx
                MXRecordItem mxe    = null;
                DnsRecord    record = DnsRecord.EMPTY;

                //
                lock (this.mxrecords)
                {
                    if (this.mxrecords.TryGetValue(domain, out mxe))
                    {
                        try
                        {
                            record = mxe.recordList[mxe.index];
                            if (Environment.TickCount - record.Expired > 0)
                            {
                                //set null, trigger dns query
                                mxe = null;
                            }
                        }
                        catch
                        {
                            mxe = null;
                        }
                    }
                }

                //query
                if (mxe == null)
                {
                    mxe            = new MXRecordItem();
                    mxe.recordList = DnsHelper.GetMXRecordList(domain);
                    mxe.index      = 0;
                    if (mxe.recordList == null || mxe.recordList.Count == 0)
                    {
                        throw new Adf.SmtpException("dns no found mx record " + domain);
                    }

                    //
                    lock (this.mxrecords)
                    {
                        this.mxrecords[domain] = mxe;
                    }
                }

                Exception firstException;

                try
                {
                    new SmtpClient(record.Value, port).Send(message);
                    //成功发送退出
                    return;
                }
                catch (Exception exception)
                {
                    //当为 socket 异常时,允许使用其它MX
                    if (exception.GetBaseException() is SocketException)
                    {
                        if (mxe.recordList.Count == 1)
                        {
                            throw;
                        }

                        firstException = exception;
                    }
                    else
                    {
                        throw;
                    }
                }

                //首选失败后重新选择mx服务器
                for (int i = 0, l = mxe.recordList.Count; i <= l; i++)
                {
                    try
                    {
                        new SmtpClient(mxe.recordList[i].Value, port).Send(message);
                        //发送成功,修改首选
                        mxe.index = i;
                        //发送成功退出
                        return;
                    }
                    catch (Exception exception)
                    {
                        if (exception.GetBaseException() is SocketException)
                        {
                            //当为 socket 异常时,允许使用其它MX
                            firstException = exception;
                        }
                        else
                        {
                            throw;
                        }
                    }
                }

                //当首选服务器为列表中最后一个服务器且重试失败时将首选异常丢出.
                throw firstException;
            }
Exemplo n.º 2
0
        //public void QueryA(string domain)
        //{
        //    string error = null;
        //    this.Query(domain, DnsQueryType.A, out error);
        //}

        private List <DnsRecord> Query(string domain, DnsQueryType queryType, out string error)
        {
            error = null;

            var id = System.Threading.Interlocked.Increment(ref this.identity);

            byte[] recvBuf = null;
            using (UdpClient udpc = new UdpClient(this.server, 53))
            {
                //
                udpc.Client.ReceiveTimeout = this.timeout;

                // SEND REQUEST--------------------
                var reqBuf = this.BuildQuery(id, domain, (ushort)queryType);
                udpc.Send(reqBuf, reqBuf.Length);

                // RECEIVE RESPONSE--------------
                IPEndPoint ep = null;
                recvBuf = udpc.Receive(ref ep);
            }

            //Check the DNS reply
            //check if bit QR (Query response) is set
            if (recvBuf[2] < 128)
            {
                //response byte not set (probably a malformed packet)
                error = "Query response bit not set";
                return(null);
            }

            //check if RCODE field is 0
            if ((recvBuf[3] & 15) > 0)
            {
                //DNS server error, invalid reply
                var status = recvBuf[3];
                error = "DNS server error, invalid reply (" + status + ")";
                return(null);
            }

            //
            var answers = recvBuf[7];

            if (answers == 0)
            {
                //throw new Exception("No results");
                return(new List <DnsRecord>(0));
            }

            var recordList = new List <DnsRecord>(answers);
            //
            int pos = domain.Length + 18;

            if (queryType == DnsQueryType.MX) // MX record
            {
                while (answers > 0)
                {
                    /*
                     *                                   1  1  1  1  1  1
                     *    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
                     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
                     |                                               |
                     |  /                                               /
                     |  /                      NAME                     /
                     |                                               |
                     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
                     |                      TYPE                     |
                     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
                     |                     CLASS                     |
                     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
                     |                      TTL                      |
                     |                                               |
                     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
                     |                   RDLENGTH                    |
                     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
                     |  /                     RDATA                     /
                     |  /                                               /
                     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
                     */
                    //pos += 2;
                    //ushort recordType = Adf.BaseDataConverter.ToUInt16(recvBuf, pos);
                    //pos += 2;
                    //ushort recordClass = Adf.BaseDataConverter.ToUInt16(recvBuf, pos);
                    //pos += 2;
                    //int recordTTL = Adf.BaseDataConverter.ToInt32(recvBuf, pos);
                    //pos += 4;
                    //ushort blocklen = Adf.BaseDataConverter.ToUInt16(recvBuf, pos);
                    //pos += 2;
                    //ushort preference = 0;
                    //if (recordType == (ushort)DnsQueryType.MX)
                    //{
                    //    preference = Adf.BaseDataConverter.ToUInt16(recvBuf, pos);
                    //    pos += 2;
                    //}

                    int ttl        = Adf.BaseDataConverter.ToInt32(recvBuf, pos + 6);
                    var preference = Adf.BaseDataConverter.ToUInt16(recvBuf, pos + 12);
                    pos += 14; //offset
                    string value = this.GetMXRecord(recvBuf, pos, out pos);

                    //Console.WriteLine("MX:\t{0}\t{1}\t{2}\t{3}\n", domain, ttl, preference, value);

                    var record = new DnsRecord();
                    record.Preference = preference;
                    record.TTL        = ttl;
                    record.Value      = value;
                    record.Expired    = Environment.TickCount + (ttl * 1000);

                    answers--;

                    //
                    recordList.Add(record);
                }

                //else if (queryType == DnsQueryType.A) // A record
                //{
                //    while (answers > 0)
                //    {
                //        pos += 11; //offset
                //        string record = this.GetARecord(recvBuf, ref pos);

                //        Console.WriteLine("A :\t{0}\t{1}\n", domain, record);

                //        answers--;
                //    }
                //}
            }
            //
            return(recordList);
        }