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         }

 

  工具運行效果圖如下:

    

  好了,本文到此結束,希望有這么經驗或更好的建議的朋友,能夠多多交流!

  郵件群發工具.rar


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM