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测试数据 " );
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测试数据 " , 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://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息