Пример #1
0
        /// <summary>
        /// Connects to sepcified host.
        /// </summary>
        /// <param name="localEndpoint">Sets local endpoint. Pass null, to use default.</param>
        /// <param name="host">Host name or IP address.</param>
        /// <param name="port">Port where to connect.</param>
        /// <param name="ssl">Specifies if to connected via SSL. Default SMTP port is 25 and SSL port is 465.</param>
        public void Connect(IPEndPoint localEndpoint, string host, int port, bool ssl)
        {
            m_pSocket = new SocketEx();
            if (localEndpoint != null)
            {
                m_pSocket.Bind(localEndpoint);
            }

            // Create logger
            if (SessionLog != null)
            {
                m_pLogger = new SocketLogger(m_pSocket.RawSocket, SessionLog);
                m_pLogger.SessionID = Guid.NewGuid().ToString();
                m_pSocket.Logger = m_pLogger;
            }

            if (host.IndexOf("@") == -1)
            {
                m_pSocket.Connect(host, port, ssl);
            }
            else
            {
                //---- Parse e-domain -------------------------------//
                string domain = host;

                // eg. Ivx <*****@*****.**>
                if (domain.IndexOf("<") > -1 && domain.IndexOf(">") > -1)
                {
                    domain = domain.Substring(domain.IndexOf("<") + 1,
                                              domain.IndexOf(">") - domain.IndexOf("<") - 1);
                }

                if (domain.IndexOf("@") > -1)
                {
                    domain = domain.Substring(domain.LastIndexOf("@") + 1);
                }

                if (domain.Trim().Length == 0)
                {
                    if (m_pLogger != null)
                    {
                        m_pLogger.AddTextEntry("Destination address '" + host + "' is invalid, aborting !");
                    }
                    throw new Exception("Destination address '" + host + "' is invalid, aborting !");
                }

                //--- Get MX record -------------------------------------------//
                Dns_Client dns = new Dns_Client();
                Dns_Client.DnsServers = m_pDnsServers;
                DnsServerResponse dnsResponse = dns.Query(domain, QTYPE.MX);

                bool connected = false;
                switch (dnsResponse.ResponseCode)
                {
                    case RCODE.NO_ERROR:
                        DNS_rr_MX[] mxRecords = dnsResponse.GetMXRecords();

                        // Try all available hosts by MX preference order, if can't connect specified host.
                        foreach (DNS_rr_MX mx in mxRecords)
                        {
                            try
                            {
                                if (m_pLogger != null)
                                {
                                    m_pLogger.AddTextEntry("Connecting with mx record to: " + mx.Host);
                                }
                                m_pSocket.Connect(mx.Host, port, ssl);
                                connected = true;
                                break;
                            }
                            catch (Exception x)
                            {
                                // Just skip and let for to try next host.									
                                if (m_pLogger != null)
                                {
                                    m_pLogger.AddTextEntry("Failed connect to: " + mx.Host + " error:" +
                                                           x.Message);
                                }
                            }
                        }

                        // None of MX didn't connect
                        if (mxRecords.Length > 0 && !connected)
                        {
                            throw new Exception("Destination email server is down");
                        }

                        /* Rfc 2821 5
						 If no MX records are found, but an A RR is found, the A RR is treated as
						 if it was associated with an implicit MX RR, with a preference of 0,
						 pointing to that host.
						*/
                        if (!connected)
                        {
                            // Try to connect with A record
                            IPAddress[] ipEntry = null;
                            try
                            {
                                if (m_pLogger != null)
                                {
                                    m_pLogger.AddTextEntry("No mx record, trying to get A record for: " +
                                                           domain);
                                }
                                ipEntry = Dns_Client.Resolve(domain);
                            }
                            catch
                            {
                                if (m_pLogger != null)
                                {
                                    m_pLogger.AddTextEntry("Invalid domain,no MX or A record: " + domain);
                                }
                                throw new Exception("Invalid domain,no MX or A record: " + domain);
                            }

                            try
                            {
                                if (m_pLogger != null)
                                {
                                    m_pLogger.AddTextEntry("Connecting with A record to:" + domain);
                                }
                                m_pSocket.Connect(domain, port, ssl);
                            }
                            catch
                            {
                                if (m_pLogger != null)
                                {
                                    m_pLogger.AddTextEntry("Failed connect to:" + domain);
                                }
                                throw new Exception("Destination email server is down");
                            }
                        }
                        break;

                    case RCODE.NAME_ERROR:
                        if (m_pLogger != null)
                        {
                            m_pLogger.AddTextEntry("Invalid domain,no MX or A record: " + domain);
                        }
                        throw new Exception("Invalid domain,no MX or A record: " + domain);

                    case RCODE.SERVER_FAILURE:
                        if (m_pLogger != null)
                        {
                            m_pLogger.AddTextEntry("Dns server unvailable.");
                        }
                        throw new Exception("Dns server unvailable.");
                }
            }

            /*
			 * Notes: Greeting may be single or multiline response.
			 *		
			 * Examples:
			 *		220<SP>SMTP server ready<CRLF> 
			 * 
			 *		220-SMTP server ready<CRLF>
			 *		220-Addtitional text<CRLF>
			 *		220<SP>final row<CRLF>
			 * 
			*/

            // Read server response
            string responseLine = m_pSocket.ReadLine(1000);
            while (!responseLine.StartsWith("220 "))
            {
                // If lisne won't start with 220, then its error response
                if (!responseLine.StartsWith("220"))
                {
                    throw new Exception(responseLine);
                }

                responseLine = m_pSocket.ReadLine(1000);
            }

            m_Connected = true;
        }
Пример #2
0
        /// <exception cref="System.IO.IOException"></exception>
        internal virtual void Ssn139()
        {
            Name calledName = new Name(Address.FirstCalledName(), 0x20, null);

            do
            {
                Socket = new SocketEx(AddressFamily.InterNetwork,
                                      SocketType.Stream,
                                      ProtocolType.Tcp);

                //TCPローカルポートは、毎回空いているものを使う。
                //https://blogs.msdn.microsoft.com/dgorti/2005/09/18/only-one-usage-of-each-socket-address-protocolnetwork-addressport-is-normally-permitted/
                Socket.Bind(new IPEndPoint(LocalAddr, 0));

                Socket.Connect(new IPEndPoint(IPAddress.Parse(Address.GetHostAddress()),
                                              139),
                               SmbConstants.ConnTimeout);

                Socket.SoTimeOut = SmbConstants.SoTimeout;

                Out = Socket.GetOutputStream();
                In  = Socket.GetInputStream();
                SessionServicePacket ssp = new SessionRequestPacket(calledName,
                                                                    NbtAddress.GetLocalName());
                Out.Write(Sbuf, 0, ssp.WriteWireFormat(Sbuf, 0));
                if (Readn(In, Sbuf, 0, 4) < 4)
                {
                    try
                    {
                        //Socket.`Close` method deleted
                        //Socket.Close();
                        Socket.Dispose();
                    }
                    catch (IOException)
                    {
                    }
                    throw new SmbException("EOF during NetBIOS session request");
                }
                switch (Sbuf[0] & 0xFF)
                {
                case SessionServicePacket.PositiveSessionResponse:
                {
                    if (Log.Level >= 4)
                    {
                        Log.WriteLine("session established ok with " + Address);
                    }
                    return;
                }

                case SessionServicePacket.NegativeSessionResponse:
                {
                    int errorCode = In.Read() & 0xFF;
                    switch (errorCode)
                    {
                    case NbtException.CalledNotPresent:
                    case NbtException.NotListeningCalled:
                    {
                        //Socket.`Close` method deleted
                        //Socket.Close();
                        Socket.Dispose();
                        break;
                    }

                    default:
                    {
                        Disconnect(true);
                        throw new NbtException(NbtException.ErrSsnSrvc,
                                               errorCode);
                    }
                    }
                    break;
                }

                case -1:
                {
                    Disconnect(true);
                    throw new NbtException(NbtException.ErrSsnSrvc,
                                           NbtException.ConnectionRefused);
                }

                default:
                {
                    Disconnect(true);
                    throw new NbtException(NbtException.ErrSsnSrvc, 0);
                }
                }
            }while ((calledName.name = Address.NextCalledName()) != null);
            throw new IOException("Failed to establish session with " + Address);
        }