紧接着上一篇文章“WPF邮件群发工具开发 之 进度条(属性改变通知机制)的实现”,这篇博文想把在工具开发中的实现要点跟大家交流、分享下,首先要说的是这个工具算是个Demo,实现的方法和功能都比较简单,还有不少细节需要完善...

  本文目录

 

     如何随机生成真实存在的QQ邮箱帐号?

  经过测试,通过C#代码发送邮件(调用SmtpClient类的Send方法,此方法无返回值,只会在发送邮箱账户错误或邮箱账户设置有问题,更多的是你用一个发送邮箱账户做群发,因为每种邮箱都有其这方面的限制,在连续很短时间内,只允许接收同一个邮箱发送的限量的邮件,如:QQ的限制大概50个左右),即使给一个根本不存在的邮箱里发送邮件,不会抛出异常,也更无法知道是否已发送成功,只能默认为发送成功,这样一说,似乎随机生成真实存在的QQ邮箱帐号是无法实现的事。——其实不然,可以用一个或几个qq邮箱账户检测生成的QQ邮箱是否真实存在! 代码实现如下:

  

 1         /// <summary>   2         /// 生成邮箱的事件处理   3         /// </summary>   4         /// <param name="sender"></param>   5         /// <param name="e"></param>   6         void btnGenerate_Email_Click(object sender, RoutedEventArgs e)   7         {   8             #region 判断   9             string str = this.txtGenerateEmailCount.Text.Trim();  10             if (string.IsNullOrEmpty(str))  11             {  12                 MessageBox.Show("请输入要生成的邮箱个数!");  13                 return;  14             }  15             int generate_Email_Count = 0;  16             int.TryParse(str, out generate_Email_Count);  17             if (generate_Email_Count <= 0)  18             {  19                 MessageBox.Show("邮箱个数必须为大于0!");  20                 return;  21             }  22             EmailAccount emailAccount = this._emailAccountList.Find(E => E.Smtp == "smtp.qq.com");  23             if (emailAccount == null)  24             {  25                 MessageBox.Show("qq邮箱账户不存在!");  26                 return;  27             }  28             #endregion  29             this._sendEmailsPropertyChanged.PropertyData += this.GetInfoTip("生成QQ邮箱");  30             EmailInfoEntity emailInfoEntity = new EmailInfoEntity()  31             {  32                 Title = this.txtEmailTitle.Text,  33                 Body = this.txtEmailContent.Text,  34                 DisplayName = this.txtDisplayName.Text.Trim(),  35                 Attachment = _accessoriesFilePath,  36                 Host = emailAccount.Smtp,  37                 From = emailAccount.Email,  38                 Pwd = emailAccount.Pwd  39             };  40             #region 线程处理  41             this.StartSingleThreadWork(() =>  42             {  43                 int i = 0, num;  44                 string email = string.Empty;  45                 System.Random random = new Random();  46                 bool isSuc;  47                 while (i < generate_Email_Count)  48                 {  49                     num = random.Next(123456, 987654321);  50                     email = string.Format("{0}@qq.com", num);  51                     if (this._emailList.Contains(email))  52                         continue;  53                     emailInfoEntity.To = email;  54                     isSuc = EmailHelper.SendEmail(emailInfoEntity);  55                     Thread.Sleep(1000);  56                     if (!isSuc)  57                     {  58                         _sendResult.SendFailEmails += string.Format("【{0}】:发送失败!{1}", email, Environment.NewLine);  59                         continue;  60                     }  61                     this._emailList.Add(email);  62                     this._sendEmailsPropertyChanged.PropertyData += email + Environment.NewLine;  63                     i++;  64                     Console.WriteLine(email);  65                 }  66                 MessageBox.Show("Generate Over");  67             });  68             #endregion  69         }

 

     单线程的使用及注意

  

 1         /// <summary>   2         /// 开始一个单线程工作   3         /// </summary>   4         /// <param name="threadStartHandle"></param>   5         private void StartSingleThreadWork(ThreadStart threadStartHandle)   6         {   7             _thread = new Thread(() =>   8             {   9                 //禁用发送按钮  10                 _sendResult.SendControlIsEnabled = false;  11                 threadStartHandle();  12                 //启用发送按钮  13                 _sendResult.SendControlIsEnabled = true;  14                 _thread.Abort();  15                 _thread = null;  16                 Console.WriteLine(threadStartHandle.Method.Name);//---此行代码不会执行,因为它位于 线程终止Abort方法之后,即Abort方法通知当前线程的使命已完成,其它的后续工作它将不会再执行!  17             });  18             _thread.Start();  19         }

    除了上面代码中的注释说明,还有一点需要重点指出的是:.Net的公用语言运行时(CLR)能区分两种不同类型的线程:前台线程和后台线程。这两者的区别就是:应用程序必须运行完所有的前台线程才可以退出;而对于后台线程,应用程序则可以不考虑其是否已经运行完毕而直接退出,所有的后台线程在应用程序退出时都会自动结束。所以,当应用程序的窗体关闭时,你希望结束所有的线程,你可以把线程设置为后台线程,或在窗体关闭事件中检查是否存在的执行中的线程并对其销毁!

     群发工具开发综述

    为了提高邮件发送的命中率,基于上面所提到的问题,应该采用多个邮箱账户轮发

  核心代码如下:

  1 void btnSend_Click(object sender, RoutedEventArgs e)    2         {    3             #region 判断    4             if (this._emailList == null || this._emailList.Count == 0)    5             {    6                 MessageBox.Show("当前要发送的邮箱为空!");    7                 return;    8             }    9             string eamilTitle = this.txtEmailTitle.Text.Trim();   10             if (string.IsNullOrEmpty(eamilTitle))   11             {   12                 MessageBox.Show("请输入email标题!");   13                 return;   14             }   15             string emailContent = this.txtEmailContent.Text.Trim();   16             if (string.IsNullOrEmpty(emailContent))   17             {   18                 MessageBox.Show("请输入email内容!");   19                 return;   20             }   21             if (!string.IsNullOrEmpty(_accessoriesFilePath))   22             {   23                 if (!System.IO.File.Exists(_accessoriesFilePath))   24                 {   25                     MessageBox.Show("请确认所选附件是否存在!");   26                     return;   27                 }   28             }   29             #endregion   30             string displayName = this.txtDisplayName.Text.Trim();   31             int count = this._emailList.Count;   32             this.progressBar.Maximum = count;   33             #region 发送处理   34             this.StartSingleThreadWork(() =>   35             {   36                 Console.WriteLine("The send count is :" + count);   37                 bool isSuc;   38                 int failCount = 0, i = 1;   39                 string failTip = string.Empty;   40                 foreach (string email in this._emailList)   41                 {   42                     _sendResult.CurrentSendNum = i;   43                     _sendResult.ProgressBarNumShow = i + "/" + count;   44                     _sendCount = 0;   45                     _sendAccountLastIndex = -1;   46                     isSuc = SendEmail(new EmailInfoEntity()   47                     {   48                         DisplayName = displayName,   49                         Body = emailContent,   50                         Title = eamilTitle,   51                         Attachment = _accessoriesFilePath,   52                         To = email   53                     });   54                     i++;   55                     if (!isSuc)   56                     {   57                         failTip = string.Format("【{0}】:发送失败!{1}", email, Environment.NewLine);   58                         _sendResult.SendResultMes += failTip;   59                         _sendResult.SendFailEmails += failTip;   60                         failCount++;   61                     }   62                     System.Threading.Thread.Sleep(1000);   63                 }   64                 string tipStr = ("failCount is :" + failCount);   65                 _sendResult.SendResultMes += tipStr;   66                 MessageBox.Show(tipStr);   67             });   68             #endregion   69         }   70    71 private bool SendEmail(EmailInfoEntity emailInfoEntity)   72         {   73             if (emailInfoEntity == null)   74                 throw new ArgumentNullException("emailInfoEntity is Null");   75             int sendAccountIndex = GetSendAccountIndex();   76             EmailAccount emailAccount = _emailAccountList[sendAccountIndex];   77             emailInfoEntity.Host = emailAccount.Smtp;   78             emailInfoEntity.From = emailAccount.Email;   79             emailInfoEntity.Pwd = emailAccount.Pwd;   80             bool isSuc = EmailHelper.SendEmail(emailInfoEntity);   81             _sendAccountLastIndex = sendAccountIndex;   82             _sendResult.SendResultMes += string.Format("★From:{0}★To:{1}★---isSuc:{2}!{3}", emailInfoEntity.From, emailInfoEntity.To, isSuc, Environment.NewLine);   83             _sendCount++;   84             if (!isSuc)   85             {   86                 //如果发送失败且已发送次数_sendCount小于_emailAccountListCount,则再次发送   87                 if (_sendCount < _emailAccountListCount)   88                 {   89                     //当前线程挂起1s,再次发送   90                     System.Threading.Thread.Sleep(1000);   91                     return SendEmail(emailInfoEntity);   92                 }   93             }   94             return isSuc;   95         }   96    97         /// <summary>   98         /// 获得当前发送邮件的邮箱账户的index   99         /// </summary>  100         /// <returns></returns>  101         private int GetSendAccountIndex()  102         {  103             if (_emailAccountListCount > 1)  104             {  105                 int sendAccountIndex = new Random().Next(_emailAccountListCount);  106                 if (_sendAccountLastIndex >= 0 && sendAccountIndex == _sendAccountLastIndex)  107                     return GetSendAccountIndex();  108                 return sendAccountIndex;  109             }  110             return 0;  111         }

 

  工具运行效果图如下:

    

  好了,本文到此结束,希望有这么经验或更好的建议的朋友,能够多多交流!

  邮件群发工具.rar