Example #1
0
        /// <summary>
        /// 取消异步邮件发送
        /// </summary>
        public void SendAsyncCancel()
        {
            // 因为此类为非线程安全类,所以 SendAsyncCancel 和发送邮件方法中操作MessageQueue部分的代码肯定是串行化的。
            // 所以不存在一边入队,一边出队导致无法完全取消所有邮件发送

            // 1、清空队列。
            // 2、取消正在异步发送的mail。
            // 3、设置计划数量=完成数量
            // 4、执行 AutoDisposeSmtp()

            if (m_IsAsync)
            {
                // 1、清空队列。
                MailUserState tempMailUserState = null;
                while (MessageQueue.TryDequeue(out tempMailUserState))
                {
                    Interlocked.Decrement(ref m_messageQueueCount);
                    MailMessage message = tempMailUserState.CurMailMessage;
                    this.InnerDisposeMessage(message);
                }
                tempMailUserState = null;
                // 2、取消正在异步发送的mail。
                m_SmtpClient.SendAsyncCancel();
                // 3、设置计划数量=完成数量
                PrepareSendCount = CompletedSendCount;
                // 4、执行 AutoDisposeSmtp()
                this.AutoDisposeSmtp();
            }
            else
            {
                throw new Exception(MailValidatorHelper.EMAIL_ASYNC_CALL_ERROR);
            }
        }
Example #2
0
        /// <summary>
        /// 声明在 SmtpClient.SendAsync() 执行完后释放相关对象的回调方法   最后触发的委托
        /// </summary>
        protected void SendCompleted4Dispose(object sender, AsyncCompletedEventArgs e)
        {
            MailUserState state = e.UserState as MailUserState;

            if (state.CurMailMessage != null)
            {
                MailMessage message = state.CurMailMessage;
                this.InnerDisposeMessage(message);
                state.CurMailMessage = null;
            }

            if (state.IsSmpleMail)
            {
                if (state.AutoReleaseSmtp && state.CurSmtpClient != null)
                {
#if DEBUG
                    Debug.WriteLine("释放SmtpClient");
#endif
                    state.CurSmtpClient.Dispose();
                    state.CurSmtpClient = null;
                }
            }
            else
            {
                if (!e.Cancelled)   // 取消的就不计数
                {
                    CompletedSendCount++;
                }

                if (state.AutoReleaseSmtp)
                {
                    this.AutoDisposeSmtp();
                }

                // 若批量异步发送,需要设置信号
#if DEBUG
                Debug.WriteLine("Set" + Thread.CurrentThread.ManagedThreadId);
#endif
                AutoResetEvent.Set();
            }

            // 先释放资源,处理错误逻辑
            if (e.Error != null && !state.IsErrorHandle)
            {
                throw e.Error;
            }
        }
Example #3
0
        /// <summary>
        /// 发送Email
        /// </summary>
        private void InnerSendMessage()
        {
            bool        hasError     = false;
            MailMessage mMailMessage = null;

            #region 构建 MailMessage
            try
            {
                mMailMessage = new MailMessage();

                mMailMessage.From = new MailAddress(From, FromDisplayName);

                this.InnerSetAddress(EmailAddrType.To, mMailMessage);
                this.InnerSetAddress(EmailAddrType.CC, mMailMessage);
                this.InnerSetAddress(EmailAddrType.Bcc, mMailMessage);

                mMailMessage.Subject = Subject;
                mMailMessage.Body    = Body;

                if (m_Attachments != null && m_Attachments.Count > 0)
                {
                    foreach (Attachment attachment in m_Attachments)
                    {
                        mMailMessage.Attachments.Add(attachment);
                    }
                }

                mMailMessage.SubjectEncoding = Encoding.UTF8;
                mMailMessage.BodyEncoding    = Encoding.UTF8;
                // SmtpClient 的 Headers 中会根据 MailMessage 默认设置些值,所以应该为 UTF8 。
                mMailMessage.HeadersEncoding = Encoding.UTF8;

                mMailMessage.IsBodyHtml = IsBodyHtml;

                if (m_AlternateViews != null && m_AlternateViews.Count > 0)
                {
                    foreach (AlternateView alternateView in AlternateViews)
                    {
                        mMailMessage.AlternateViews.Add(alternateView);
                    }
                }

                mMailMessage.Priority = (MailPriority)Priority;
            }
            catch (ArgumentNullException argumentNullEx)
            {
                hasError = true;
                throw argumentNullEx;
            }
            catch (ArgumentException argumentEx)
            {
                hasError = true;
                throw argumentEx;
            }
            catch (FormatException formatEx)
            {
                hasError = true;
                throw formatEx;
            }
            finally
            {
                if (hasError)
                {
                    if (mMailMessage != null)
                    {
                        this.InnerDisposeMessage(mMailMessage);
                        mMailMessage = null;
                    }
                    this.InnerDisposeSmtp();
                }
            }

            #endregion

            if (!hasError)
            {
                if (m_IsAsync)
                {
                    #region 异步发送邮件

                    if (PrepareSendCount == 1)
                    {
                        // 情况一:不重用 SmtpClient 实例会将PrepareSendCount设置为1
                        // 情况二:计划发送只有一条

                        // PrepareSendCount 是发送单条邮件。
                        MailUserState state = new MailUserState()
                        {
                            AutoReleaseSmtp = m_autoDisposeSmtp,
                            CurMailMessage  = mMailMessage,
                            CurSmtpClient   = m_SmtpClient,
                            IsSmpleMail     = true,
                            UserState       = AsycUserState,
                        };
                        if (m_autoDisposeSmtp)
                        {
                            // 由发送完成回调函数根据 IsSmpleMail 字段进行释放
                            m_SmtpClient = null;
                        }

                        ThreadPool.QueueUserWorkItem((userState) =>
                        {
                            // 无需 catch 发送异常,因为是异步,所以这里 catch 不到。
                            MailUserState curUserState = userState as MailUserState;
                            curUserState.CurSmtpClient.SendAsync(mMailMessage, userState);
                        }, state);
                    }
                    else
                    {
                        // 情况一:重用 SmtpClient 逻辑,即我们可以直接操作全局的 m_SmtpClient
                        // 情况二:批量发送邮件 PrepareSendCount>1
                        // 情况三:PrepareSendCount 还未设置,为0。比如场景在循环中做些判断,再决定发邮件,循环完才调用 SetBatchMailCount 设置计划邮件数量

                        MailUserState state = new MailUserState()
                        {
                            AutoReleaseSmtp = m_autoDisposeSmtp,
                            CurMailMessage  = mMailMessage,
                            CurSmtpClient   = m_SmtpClient,
                            UserState       = AsycUserState,
                        };

                        MessageQueue.Enqueue(state);
                        Interlocked.Increment(ref m_messageQueueCount);

                        if (m_SendMailThread == null)
                        {
                            m_SendMailThread = new Thread(() =>
                            {
                                // noItemCount 次获取不到元素,就抛出线程异常
                                int noItemCount = 0;
                                while (true)
                                {
                                    if (PrepareSendCount != 0 && PrepareSendCount == CompletedSendCount)
                                    {
                                        // 已执行完毕。
                                        this.AutoDisposeSmtp();
                                        break;
                                    }
                                    else
                                    {
                                        MailUserState curUserState = null;

                                        if (!MessageQueue.IsEmpty)
                                        {
#if DEBUG
                                            Debug.WriteLine("WaitOne" + Thread.CurrentThread.ManagedThreadId);
#endif
                                            // 当执行异步取消时,会清空MessageQueue,所以 WaitOne 必须在从MessageQueue中取到元素之前
                                            AutoResetEvent.WaitOne();

                                            if (MessageQueue.TryDequeue(out curUserState))
                                            {
                                                Interlocked.Decrement(ref m_messageQueueCount);
                                                m_SmtpClient.SendAsync(curUserState.CurMailMessage, curUserState);
                                            }
                                        }
                                        else
                                        {
                                            if (noItemCount >= 10)
                                            {
                                                // 没有正确设置 PrepareSendCount 值。导致已没有邮件但此线程出现死循环
                                                this.InnerDisposeSmtp();

                                                throw new Exception(MailValidatorHelper.EMAIL_PREPARESENDCOUNT_NOTSET_ERROR);
                                            }

                                            Thread.Sleep(1000);
                                            noItemCount++;
                                        }
                                    }
                                    // SmtpClient 为null表示异步预计发送邮件数已经发送完,在 OnSendCompleted 进行了 m_SmtpClient 释放
                                    if (m_SmtpClient == null)
                                    {
                                        break;
                                    }
                                }

                                m_SendMailThread = null;
                            });
                            m_SendMailThread.Start();
                        }
                    }

                    #endregion
                }
                else
                {
                    #region  步发送邮件
                    try
                    {
                        m_SmtpClient.Send(mMailMessage);
                        m_CompletedSendCount++;
                    }
                    catch (ObjectDisposedException smtpDisposedEx)
                    {
                        throw smtpDisposedEx;
                    }
                    catch (InvalidOperationException smtpOperationEx)
                    {
                        throw smtpOperationEx;
                    }
                    catch (SmtpFailedRecipientsException smtpFailedRecipientsEx)
                    {
                        throw smtpFailedRecipientsEx;
                    }
                    catch (SmtpException smtpEx)
                    {
                        throw smtpEx;
                    }
                    finally
                    {
                        if (mMailMessage != null)
                        {
                            this.InnerDisposeMessage(mMailMessage);
                            mMailMessage = null;
                        }
                        this.AutoDisposeSmtp();
                    }
                    #endregion
                }
            }
        }