[转载]c#实现QQ群成员列表导出及邮件群发之邮件群发 – 狼性法则 – 博客园.
前言
经过前3篇的代码编写我们已经可以通过抓包分析,http协议模拟登陆QQ,并顺利拿到cookie实现获 取群成员等操作,其中重要的算法,如密码算法,gtk算法前文已经毫无保留的给出,通过大家的评论及留言已经看出大家已经能顺利取到群成员,此篇邮件群发 与前几篇关系不大,也是本系列文章的最后一篇,算是补个全。本文将讲述登陆C#利用smtp服务多账号,多协议群发邮件的代码。
软件截图:
本文主要完成添加多个发信服务器账号,单线程及多线程邮件群发功能。
功能分解:
1、设置发信SMTP服务器
首先做个窗体,这个不用说很简单,我们可以将常用的smtp,做成下拉列表,本人只为演示所以只写了一个qq的,前台是得开通smtp服务。
发信邮箱设置代码:
public string sendUser; private void btnEnter_Click(object sender, EventArgs e) { Regex myreg = new Regex(@"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"); //email验证 if (myreg.IsMatch(txtEmail.Text) && txtEmail.Text.Trim() != "" && txtEmaipwd.Text.Trim() != "") { sendUser = txtSmtp.Text + "," + txtEmail.Text.Trim() + "," + txtEmaipwd.Text.Trim(); this.DialogResult = DialogResult.OK; } else { txtSmtp.Text = ""; txtEmail.Text = ""; txtEmaipwd.Text= ""; msg.Text = "添加格式不正确,请重新输入!"; this.DialogResult = DialogResult.None; } } private void txtEmaipwd_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) btnEnter_Click(null, null); } private void btnCanncle_Click(object sender, EventArgs e) { this.Dispose(); }
添加完成并验证同过以后将smtp服务器,邮箱,密码组合成字符串添加的下面的listbox中(添加发信邮箱按钮):
private void button1_Click(object sender, EventArgs e) { AddFrm addSender = new AddFrm(); if (addSender.ShowDialog() == DialogResult.OK && !lstSender.Items.Contains(addSender.sendUser)) { lstSender.Items.Add(addSender.sendUser); } }
这样可以添加多个smtp服务器并设置多个发信账号,从反垃圾邮件的问题来说,还是多添加几个为好。
两种群发短信代码,采用system.net中自带的发信类库中提供的方法:
发送统计类:
class All { public static int success = 0;//发送成功的个数 public static int fail = 0;//发送失败的个数 public static int runing = 0;//运行的线程数 }
发信单元:
class MainUnit { public string smtp; public string from; public string pwd; public string to; public string subject; public string body; public ArrayList paths; public MainUnit(string Psmtp, string Pfrom, string Ppwd, string Pto, string Psubject, string Pbody, ArrayList Ppaths) { smtp = Psmtp; from = Pfrom; pwd = Ppwd; to = Pto; subject = Psubject; body = Pbody; paths = Ppaths; } /*发邮件*/ public bool SendMail() { //创建smtpclient对象 System.Net.Mail.SmtpClient client = new SmtpClient(); client.Host = smtp; client.UseDefaultCredentials = false; client.Credentials = new System.Net.NetworkCredential(from, pwd); client.DeliveryMethod = SmtpDeliveryMethod.Network; //创建mailMessage对象 System.Net.Mail.MailMessage message = new MailMessage(from, to); message.Subject = subject; //正文默认格式为html message.Body = body; message.IsBodyHtml = true; message.BodyEncoding = System.Text.Encoding.UTF8; //添加附件 if (paths.Count != 0) { foreach (string path in paths) { Attachment data = new Attachment(path, System.Net.Mime.MediaTypeNames.Application.Octet); message.Attachments.Add(data); } } try { client.Send(message); //MessageBox.Show("Email successfully sent."); return true; } catch (Exception ex) { MessageBox.Show("Send Email Failed." + ex.ToString()); return false; } } /*发邮件:线程中使用*/ public void SendMail2() { All.runing++; //创建smtpclient对象 System.Net.Mail.SmtpClient client = new SmtpClient(); client.Host = smtp; client.UseDefaultCredentials = false; client.Credentials = new System.Net.NetworkCredential(from, pwd); client.DeliveryMethod = SmtpDeliveryMethod.Network; //创建mailMessage对象 System.Net.Mail.MailMessage message = new MailMessage(from, to); message.Subject = subject; //正文默认格式为html message.Body = body; message.IsBodyHtml = true; message.BodyEncoding = System.Text.Encoding.UTF8; //添加附件 if (paths.Count != 0) { foreach (string path in paths) { Attachment data = new Attachment(path, System.Net.Mime.MediaTypeNames.Application.Octet); message.Attachments.Add(data); } } try { client.Send(message); All.success++; All.runing--; } catch (Exception ex) { All.fail++; All.runing--; } } }
下面看下发信界面的设置:
添加附件代码,我们可以将附件地址放在一个ArrayList中动态添加,同时将附件的名称显示在文本框中:
private void addfujian_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { openFujiandialog.Filter = "所有文件(*.*)|*.*"; if (openFujiandialog.ShowDialog() == DialogResult.OK) { string[] files = openFujiandialog.FileNames; foreach (string file in files) { paths.Add(files); txtFujian.Text += Path.GetFileName(file) + " "; } } }
清空附件代码;
private void clearfujian_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { txtFujian.Text = ""; paths.Clear(); }
发信标题及内容检测代码:
public bool CheckEmail() { string err = "注意:\n\n"; int errCount = 0; if (txtTitle.Text.Trim().Length == 0) { err += "标题不能为空!\r\n"; errCount++; } if (txtBody.Text.Trim().Length == 0) { err += "正文不能为空!"; errCount++; } Regex myreg = new Regex(@"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"); //email验证 if (errCount == 0) return true; else { MessageBox.Show(err, "提示"); return false; }
一切设置完成后就是群发邮件了,本软件只是给固定群发送邮件,大家可以扩展导入列表群发邮件:
private void button2_Click(object sender, EventArgs e) { if (!CheckEmail()) return; //群成员邮箱集合,可扩展比如导入等 if (toUser.Count < 1) MessageBox.Show("没有群成员!"); //存放发件人的listbox if (lstSender.Items.Count < 1) MessageBox.Show("没有发件人!"); ArrayList alist = new ArrayList(); for (int i = 0; i < toUser.Count; i++) { string mail; if (i < lstSender.Items.Count) { mail = toUser[i].ToString() + "," + lstSender.Items[i].ToString(); } else { mail = toUser[i].ToString() + "," + lstSender.Items[i % lstSender.Items.Count].ToString(); } alist.Add(mail); } for (int j = 0; j < alist.Count; j++) { string senderStr = alist[j].ToString(); string[] str = senderStr.Split(new char[] { ',', ',', ',' }); string smtpStr = str[1]; string fromStr=str[2]; string pwdStr = str[3]; string toMail = str[0]; MainUnit mu = new MainUnit(smtpStr, fromStr, pwdStr, toMail, txtTitle.Text, txtBody.Text, paths); Thread mythread = new Thread(new ThreadStart(mu.SendMail2)); mythread.Start(); } int percentValue = 0; while (All.runing != 0) { //设置滚动条 Application.DoEvents(); this.proBar.Value = All.runing; this.proBar.Maximum = toUser.Count; this.proBar.Minimum = 0; percentValue = 100 * (this.proBar.Value - this.proBar.Minimum) / (this.proBar.Maximum - this.proBar.Minimum);//将当前进度转化为百分比的形式 lblProbar.Text = percentValue.ToString() + "%";//在Label中显示百分比的值 } if (percentValue == 100) { //发送结果提示 DialogResult ok = MessageBox.Show("【结果】发送成功:" + All.success.ToString() + "条 发送失败:" + All.fail.ToString() + "条"); if (ok == DialogResult.OK) { proBar.Value = 0; lblProbar.Text = ""; All.fail = 0; All.success = 0; } } }
导出及过滤列表就是些简单的文件读写操作了,应该有比我更好的办法来实现。
结语:
本系列文章的目的是给大家一个思路,想自己没事研究qq群发,空间日志,游戏等外挂操作的可以参考一下前面几篇文章。QQ的加密算法及参数计算方法 相信会随着时间推移而改变,到时候登陆肯定不成功,有一的那个时效性。本文中存在很多问题,如发垃圾邮件如何解决,群发邮件效率不高,发信正确统计成功失 败等问题,有兴趣的朋友可以自己研究一下。
本系列目录: