WPF邮件群发工具开发

WPF邮件群发工具开发 之 实现要点说明(完结篇)附工具下载

       紧接着上一篇文章“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         }
复制代码

 

  工具运行效果图如下:

    WPF邮件群发工具开发

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

  邮件群发工具.rar

 
 
分类:  WPF

你可能感兴趣的:(软件开发,邮件群发,邮件群发工具,配餐系统,WPF邮件群发工具)