void _sendThreadProc(object state)
        {
            SendMailThreadState threadState = (SendMailThreadState)state;
            int recipientIndex = threadState.RecipientIndex;

            RecipientStatus status = new RecipientStatus();

            status.RecipientIndex = recipientIndex;
            status.Recipient      = threadState.Mail.To.ToString();

            try
            {
                SmtpClient smtp = new SmtpClient();
                smtp.Tag = status;

                // Catching the following events is not necessary,
                // just make the application more user friendly.
                // If you use the object in asp.net/windows service or non-gui application,
                // You need not to catch the following events.
                // To learn more detail, please refer to the code in EASendMail EventHandler region
                smtp.OnIdle              += new SmtpClient.OnIdleEventHandler(OnIdle);
                smtp.OnAuthorized        += new SmtpClient.OnAuthorizedEventHandler(OnAuthorized);
                smtp.OnConnected         += new SmtpClient.OnConnectedEventHandler(OnConnected);
                smtp.OnSecuring          += new SmtpClient.OnSecuringEventHandler(OnSecuring);
                smtp.OnSendingDataStream += new SmtpClient.OnSendingDataStreamEventHandler(OnSendingDataStream);

                status.Status = "Connecting server ...";
                _updateRecipientStatus(status);

                smtp.SendMail(threadState.Server, threadState.Mail);

                status.Status    = "Succeeded";
                status.Completed = true;

                _updateRecipientStatus(status);
                _updateResultCounter(true);
            }
            catch (Exception ep)
            {
                status.Status    = ep.Message;
                status.HasError  = true;
                status.Completed = true;

                _updateRecipientStatus(status);
                _updateResultCounter(false);
            }
            finally
            {
                Interlocked.Decrement(ref _threadCounter);
                _trafficController.DecreaseConnection();
            }
        }
        void _updateRecipientStatus(RecipientStatus status)
        {
            lock (this)
            {
                int threadId = Thread.CurrentThread.ManagedThreadId;
                if (!_activeRecipients.ContainsKey(threadId))
                {
                    _activeRecipients.Add(threadId, status);
                }

                if (status.Completed)
                {
                    _activeRecipients.Remove(threadId);
                }
            }
        }