自己动手,一步一步实现邮件群发.NET源码(3)
关键字:.NET、邮件、群发
在前面发布了邮件群发器后,自己使用的过程中,碰到了如下问题。
大量邮件可能存在Excel或文档中,要直接拷贝使用群发过程中, 发件人抄送的邮件,会显示在每个收件人中,这不利于安全群发过程中,由于抄送密送大量邮件,捕获错误后,不知道哪些邮件正确发出哪些有异常

由于发送邮件,可能从文档摘记中来,例如有如下背景,很多网友来电要金质打印通源码,我就记录下来,回复邮件时有的发送失败,我把这些信息临时放记事本中,没有统一存在数据库。我现在想发邮件,如果一个邮件一个邮件的敲键盘,那肯定太原始,一个邮件一个邮件拷贝,虽然聪明点少敲下键盘,但是如果我直接把文件内容复制或打开就能把邮件区分开来发送,那不是一步到位吗?
例如如下记录文档txt:
2006年3月7日,登记XX@yeah.netYY@msn.com...2006年3月4日,发送邮件失败aa@hotmail.combb@163.com...--敬请关注我的BLOG和网站上最新消息!MIS金质打印通 通打天下报表 http://www.webmis.com.cn http://blog.csdn.net/flygoldfish QQ:150439795 长江支流
我Ctrl+C,然后,复制到我的收件人中,结果发送时因为有些不是邮件地址会出错。于是我在收件人中增加了一个双击事件,弹出一个窗口,该窗口有一个大的文本框,用来接收显示文本,并有一个格式化按钮用来去掉回车换行等,将邮件用英文半角逗号分隔。
为了收信人不看到抄送人的邮箱,于是用循环单个发送,在发送时,如果分隔出来的邮件没有@标志那明显不是邮件,跳过发送。
在捕获发送错误时,有时因为发送邮件数量过大,而收到服务器一个返回信息,例如网易的返回是:
正在处理错误。 服务器响应为: MI:SFQ 0,smtp3,DdGowEC5mldx_CBQsc4QFA--.106S3 1344339057http://mail.163.com/help/help_spam_16.htm?ip=111.161.77.192&hostid=smtp3&time=1344339057
打开网页邮箱服务说明,发现了MI:SFQ正是错误代码,再摘录几个:
* 如下经常出会出现,邮件数量超出限制
?450 MI:DMC 当前连接发送的邮件数量超出限制。请减少每次连接中投递的邮件数量;
?451 MI:SFQ 发信人在15分钟内的发信数量超过限制,请控制发信频率;
?450 RP:DRC 当前连接发送的收件人数量超出限制。请控制每次连接投递的邮件数量;
?451 RP:QRC 发信方短期内累计的收件人数量超过限制,该发件人被临时禁止发信。请降低该用户发信频率;
?550 MI:STC 发件人当天的连接数量超出了限定数量,当天不再接受该发件人的邮件。请控制连接次数;
?550 RP:FRL 网易邮箱不开放匿名转发(Open relay);
?550 RP:RCL 群发收件人数量超过了限额,请减少每封邮件的收件人数量;
如果我一个一个的判断,今天是网易,明天是新浪,永远也加不完。最灵活的办法是根据群发人使用的邮箱,自己去设置返回码与处理对策及友好提示,把它们存在配置文件中。
我只做一个简单处理,把由于发送数量太多及暂时限制连接存在配置文件中,当捕获错误时如果是指定的代码,我就暂时停顿一会后再发,当然可以重发。
//发送邮件 private bool SendMail() { #region 实现... //网络设置 SmtpClient smtp = new SmtpClient(); //将smtp的出站方式设为 Network smtp.DeliveryMethod = SmtpDeliveryMethod.Network; smtp.Port = m_Setting.SmtpPort; smtp.Host = m_Setting.SmtpServer; smtp.EnableSsl = m_Setting.SmtpSSL; //邮件认证,即邮箱用户名称密码 smtp.UseDefaultCredentials = false; smtp.Credentials = new NetworkCredential(m_Setting.SenderMail, m_Setting.SenderPassword); //邮件信息 MailMessage mm = new MailMessage(); mm.Priority = MailPriority.Normal; //发件人 mm.From = new MailAddress(m_Setting.SenderMail, m_Setting.SenderDisplay); //接收回复邮件 if (m_Setting.ReplyToMail != null && m_Setting.ReplyToMail != "") { //mm.ReplyTo = new MailAddress("MisGoldPrinter@163.com", "(答复)金质打印通"); mm.ReplyTo = new MailAddress(m_Setting.ReplyToMail, m_Setting.ReplyToDisplay); } //主题 mm.Subject = txtSubject.Text; //内容 //mm.SubjectEncoding = Encoding.Unicode; //mm.BodyEncoding = Encoding.Unicode; //mm.IsBodyHtml = false; mm.IsBodyHtml = chkHtml.Checked; mm.Body = txtBody.Text; //mm.IsBodyHtml = true; //mm.Body = "<font size = \"21\" color=\"blue\">长江支流金质打印通,准备升级</font>"; ////,请http://goldprinter.taobao.com/查看注册 //附件 for (int i = 0; i < this.lstFiles.Items.Count; i++) { mm.Attachments.Add(new Attachment(this.lstFiles.Items[i].ToString())); } //接收人、抄送、密送 //多个邮件英文逗号分开 //mm.CC.Add("FlyGoldFish@163.com,MISGoldPrinter@163.com"); //mm.CC.Add(new MailAddress("FlyGoldFish@163.com", "金质打印通,来自网易测试")); if (chkSplit.Checked) { //单个分离发信,收件人只看到自己,看不到其它群发的收件人 #region 实现... //格式错误、发送失败以及成功的邮件 List<string> arrErrorMails = new List<string>(); List<string> arrFaileErrorMails = new List<string>(); List<string> arrSuccessMails = new List<string>(); int iTotalCount = 0; int iSuccessCount = 0; string strMails = ReplaceMailList(txtTO.Text) + "," + ReplaceMailList(txtCC.Text) + "," + ReplaceMailList(txtBCC.Text); string[] arrMails = strMails.Split(','); this.pnStatus.Visible = true; this.pbSend.Minimum = 1; this.pbSend.Maximum = arrMails.Length; for (int i = 0; i < arrMails.Length; i++) { this.pbSend.Value = i+1; this.lblStatus.Text = string.Format("共{0}封邮件,正在发第{1}封,已发送成功{2}", arrMails.Length.ToString(), (i + 1), i.ToString(), iTotalCount.ToString()); this.lblStatus.Refresh(); this.pnStatus.Refresh(); //跳过只有分隔但没指定邮件的空串 if (arrMails[i].Trim() == "" || arrMails[i].IndexOf('@') < 1) { continue; } //有效数量 iTotalCount++; try { mm.To.Clear(); mm.To.Add(arrMails[i]); } catch (FormatException fe) { //记录错误发送的邮件 arrErrorMails.Add(arrMails[i]); //MessageBox.Show("有非邮件格式,请修正后重试!", MSG_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Information); } try { smtp.Send(mm); //MessageBox.Show("发送成功!", MSG_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Information); arrSuccessMails.Add(arrMails[i]); iSuccessCount++; //发现有的发10个以上,就会失败 if (iSuccessCount > 0 && iSuccessCount % 10 == 0) { System.Threading.Thread.Sleep(5 * 1000); //停几秒再发 } } catch (Exception ex) { //Message = "不允许使用邮箱名称。 服务器响应为: Requested action not taken: Local user only,smtp2,DNGowEDpelx8+SBQp+ZBAQ--.852S2 1344338303" //System.Net.Mail.SmtpException: 事务失败。 服务器响应为: MI:STC 0,smtp3,DdGowECJLV0A+iBQ3TEQFA--.773S2 1344338432 //正在处理错误。 服务器响应为: MI:SFQ 0,smtp3,DdGowEC5mldx_CBQsc4QFA--.106S3 1344339057 http://mail.163.com/help/help_spam_16.htm?ip=111.161.77.192&hostid=smtp3&time=1344339057 //MessageBox.Show("发送错误信息:" + ex.Message, MSG_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Information); //Message = "邮箱不可用。 服务器响应为: User not found: abird70@163.com" for (int m = 0; m < m_Setting.InterimLimitCode.Count; m++) { //网易的 if (ex.Message.IndexOf("服务器响应为: " + m_Setting.InterimLimitCode[m]) > 1) { System.Threading.Thread.Sleep(30 * 1000); } } arrFaileErrorMails.Add(arrMails[i]); //System.Threading.Thread.Sleep(5 * 1000); } } string strResult = ""; frmMailResult frmResult = null; this.pnStatus.Visible = false ; if (iTotalCount == iSuccessCount) { strResult = string.Format("共有{0}封邮件,全部发送成功!", iTotalCount.ToString()); if (MessageBox.Show(strResult + "\r\n是否查看详细反馈信息?", MSG_TITLE, MessageBoxButtons.YesNo, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1) == DialogResult.Yes) { frmResult = new frmMailResult(strResult,arrFaileErrorMails,arrSuccessMails); frmResult.ShowDialog(); frmResult.Dispose(); } return true; } else { strResult = string.Format("共有{0}封邮件,其中发送成功数{1},有{2}封邮件发送失败!", iTotalCount.ToString(), iSuccessCount.ToString(), (iTotalCount - iSuccessCount).ToString()); if (MessageBox.Show(strResult + "\r\n是否查看详细反馈信息?", MSG_TITLE, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1) == DialogResult.Yes) { frmResult = new frmMailResult(strResult, arrFaileErrorMails, arrSuccessMails); frmResult.ShowDialog(); frmResult.Dispose(); } return false; } #endregion 实现... } else { #region 实现... try { mm.To.Add(ReplaceMailList(txtTO.Text)); if (txtCC.Text.Trim() != "") { mm.CC.Add(ReplaceMailList(txtCC.Text)); } if (txtBCC.Text.Trim() != "") { mm.Bcc.Add(ReplaceMailList(txtBCC.Text)); } } catch (FormatException fe) { MessageBox.Show("有非邮件格式,请修正后重试!", MSG_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Information); return false; } try { smtp.Send(mm); MessageBox.Show("发送成功!", MSG_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Information); return true; } catch (Exception ex) { MessageBox.Show("发送错误信息:" + ex.Message, MSG_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Information); txtTO.Focus(); return false; } #endregion 实现... } #endregion 实现... }
相关源码下载信息请访问:
http://blog.csdn.net/flygoldfish
声明:本文版权为周方勇所有,欢迎转载,请保留完整的内容及出处。
flygoldfish@163.com