• 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

  • 相关阅读:
    Android 布局中 如何使控件居中
    VGA, QVGA, HVGA, WVGA, FWVGA和iPhone显示分辨率
    [转+整理] Android 分辨率,密度,像素单位说明
    多线程的知识点总结
    集合的相关信息
    spring cloud详解
    iostat实时监控磁盘util
    Jenkins安装过程
    hdfs的block为什么设置成128M
    shell变量自增的几种方式
  • 原文地址:https://www.cnblogs.com/know/p/2944307.html
Copyright © 2020-2023  润新知