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