WPF邮件群发工具开发
WPF邮件群发工具开发 之 实现要点说明(完结篇)附工具下载
紧接着上一篇文章“ WPF邮件群发工具开发 之 进度条(属性改变通知机制)的实现 ”,这篇博文想把在工具开发中的实现要点跟大家交流、分享下,首先要说的是这个工具算是个Demo,实现的方法和功能都比较简单,还有不少细节需要完善...
本文目录 :
如何随机生成真实存在的QQ邮箱帐号? 单线程的使用及注意 群发工具开发综述如何随机生成真实存在的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
分类: WPF
标签: 配餐系统 , 软件开发 , 邮件群发 , 邮件群发工具 , WPF邮件群发工具
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息