コード例 #1
0
        /// <summary>
        /// Is called when EHLO/HELO command has completed.
        /// </summary>
        /// <param name="op">Asynchronous operation.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>op</b> is null reference.</exception>
        private void ConnectCompleted(TCP_Client.ConnectAsyncOP op)
        {
            if (op == null)
            {
                throw new ArgumentNullException("op");
            }

            try
            {
                // Connect failed.
                if (op.Error != null)
                {
                    try
                    {
                        // Release IP usage.
                        m_pServer.RemoveIpUsage(m_pActiveTarget.Target.Address);
                        m_pActiveTarget = null;

                        // Connect failed, if there are more target IPs, try next one.
                        if (!this.IsDisposed && !this.IsConnected && m_pTargets.Count > 0)
                        {
                            BeginConnect();
                        }
                        else
                        {
                            Dispose(op.Error);
                        }
                    }
                    catch (Exception x1)
                    {
                        Dispose(x1);
                    }
                }
                // Connect suceeded.
                else
                {
                    // Do EHLO/HELO.
                    string hostName = string.IsNullOrEmpty(m_pLocalBindInfo.HostName) ? Dns.GetHostName() : m_pLocalBindInfo.HostName;
                    SMTP_Client.EhloHeloAsyncOP ehloOP = new SMTP_Client.EhloHeloAsyncOP(hostName);
                    ehloOP.CompletedAsync += delegate(object s, EventArgs <SMTP_Client.EhloHeloAsyncOP> e)
                    {
                        EhloCommandCompleted(ehloOP);
                    };
                    if (!m_pSmtpClient.EhloHeloAsync(ehloOP))
                    {
                        EhloCommandCompleted(ehloOP);
                    }
                }
            }
            catch (Exception x)
            {
                Dispose(x);
            }
        }
コード例 #2
0
        /// <summary>
        /// Starts connecting to best target.
        /// </summary>
        private void BeginConnect()
        {
            // No tagets, abort relay.
            if (m_pTargets.Count == 0)
            {
                LogText("No relay target(s) for '" + m_pRelayItem.To + "', aborting.");
                Dispose(new Exception("No relay target(s) for '" + m_pRelayItem.To + "', aborting."));

                return;
            }

            // Maximum connections per IP limited.
            if (m_pServer.MaxConnectionsPerIP > 0)
            {
                // For DNS or load-balnced smart host relay, search free target if any.
                if (m_pServer.RelayMode == Relay_Mode.Dns || m_pServer.SmartHostsBalanceMode == BalanceMode.LoadBalance)
                {
                    foreach (Relay_Target t in m_pTargets)
                    {
                        // Get local IP binding for remote IP.
                        m_pLocalBindInfo = m_pServer.GetLocalBinding(t.Target.Address);

                        // We have suitable local IP binding for the target.
                        if (m_pLocalBindInfo != null)
                        {
                            // We found free target, stop searching.
                            if (m_pServer.TryAddIpUsage(t.Target.Address))
                            {
                                m_pActiveTarget = t;
                                m_pTargets.Remove(t);

                                break;
                            }
                            // Connection per IP limit reached.
                            else
                            {
                                LogText("Skipping relay target (" + t.HostName + "->" + t.Target.Address + "), maximum connections to the specified IP has reached.");
                            }
                        }
                        // No suitable local IP binding, try next target.
                        else
                        {
                            LogText("Skipping relay target (" + t.HostName + "->" + t.Target.Address + "), no suitable local IPv4/IPv6 binding.");
                        }
                    }
                }
                // Smart host fail-over mode, just check if it's free.
                else
                {
                    // Get local IP binding for remote IP.
                    m_pLocalBindInfo = m_pServer.GetLocalBinding(m_pTargets[0].Target.Address);

                    // We have suitable local IP binding for the target.
                    if (m_pLocalBindInfo != null)
                    {
                        // Smart host IP limit not reached.
                        if (m_pServer.TryAddIpUsage(m_pTargets[0].Target.Address))
                        {
                            m_pActiveTarget = m_pTargets[0];
                            m_pTargets.RemoveAt(0);
                        }
                        // Connection per IP limit reached.
                        else
                        {
                            LogText("Skipping relay target (" + m_pTargets[0].HostName + "->" + m_pTargets[0].Target.Address + "), maximum connections to the specified IP has reached.");
                        }
                    }
                    // No suitable local IP binding, try next target.
                    else
                    {
                        LogText("Skipping relay target (" + m_pTargets[0].HostName + "->" + m_pTargets[0].Target.Address + "), no suitable local IPv4/IPv6 binding.");
                    }
                }
            }
            // Just get first target.
            else
            {
                // Get local IP binding for remote IP.
                m_pLocalBindInfo = m_pServer.GetLocalBinding(m_pTargets[0].Target.Address);

                // We have suitable local IP binding for the target.
                if (m_pLocalBindInfo != null)
                {
                    m_pActiveTarget = m_pTargets[0];
                    m_pTargets.RemoveAt(0);
                }
                // No suitable local IP binding, try next target.
                else
                {
                    LogText("Skipping relay target (" + m_pTargets[0].HostName + "->" + m_pTargets[0].Target.Address + "), no suitable local IPv4/IPv6 binding.");
                }
            }

            // We don't have suitable local IP end point for relay target.
            // This may heppen for example: if remote server supports only IPv6 and we don't have local IPv6 local end point.
            if (m_pLocalBindInfo == null)
            {
                LogText("No suitable IPv4/IPv6 local IP endpoint for relay target.");
                Dispose(new Exception("No suitable IPv4/IPv6 local IP endpoint for relay target."));

                return;
            }

            // If all targets has exeeded maximum allowed connection per IP address, end relay session,
            // next relay cycle will try to relay again.
            if (m_pActiveTarget == null)
            {
                LogText("All targets has exeeded maximum allowed connection per IP address, skip relay.");
                Dispose(new Exception("All targets has exeeded maximum allowed connection per IP address, skip relay."));

                return;
            }

            // Set SMTP host name.
            m_pSmtpClient.LocalHostName = m_pLocalBindInfo.HostName;

            // Start connecting to remote end point.
            TCP_Client.ConnectAsyncOP connectOP = new TCP_Client.ConnectAsyncOP(new IPEndPoint(m_pLocalBindInfo.IP, 0), m_pActiveTarget.Target, false, null);
            connectOP.CompletedAsync += delegate(object s, EventArgs <TCP_Client.ConnectAsyncOP> e){
                ConnectCompleted(connectOP);
            };
            if (!m_pSmtpClient.ConnectAsync(connectOP))
            {
                ConnectCompleted(connectOP);
            }
        }