标签:识别 编号 end 邮件内容 上网 保存 提示信息 regular 邮件服务器
C#实现群发邮件
先在网上下一个jmail.dll(google搜一下就有。) 具体代码。 public bool SendMail(string from ,string fromName,string subject ,string body , string attachmentFile1,string attachmentFile2,bool isinline,bool isHtml,string[] mailTo ) { jmail.MessageClass MsgMail = new jmail.MessageClass(); MsgMail.Logging = true; MsgMail.Silent = true; MsgMail.Charset = "GB2312"; MsgMail.Encoding = "Base64"; MsgMail.ISOEncodeHeaders = false; MsgMail.From = from; if (fromName!=""){MsgMail.FromName = fromName;} //加收件人 for (int i=0;i<mailTo.Length;i++) { string emailAddress=mailTo[i].ToString(); i++; string MailToName=mailTo[i].ToString(); if (MailToName=="" ) {MsgMail.AddRecipient(emailAddress,null,null);} else{MsgMail.AddRecipient(emailAddress,MailToName,null);} } MsgMail.Subject = subject; MsgMail.Body = body; // if (isHtml) // { MsgMail.ContentType="text/html"; // } // else // { // MsgMail.ContentType="text/plain"; // } if (attachmentFile1!="") { MsgMail.AddAttachment(attachmentFile1,isinline,null);//例如:text/plain表示txt文档 } if (attachmentFile2!="") { MsgMail.AddAttachment(attachmentFile2,isinline,null);//例如:text/plain表示txt文档 } MsgMail.MailServerUserName = "zhaolidong@51db.com"; //登录邮件服务器所需的用户名 MsgMail.MailServerPassWord = "fhquutuu" ; if(MsgMail.Send("mail.51db.com", false)) {return true;} else { return false; } } }
C#网页 自动登录 提交POST信息 方法
以下就分别用这三种方法来实现: 1、WebBrowser是个"迷你"浏览器,其特点是Post时不用关心Cookie、内置JS等问题 WebBrowser是VS2005新提供的组件(其实就是封装了IE接口),实现POST功能一般在webBrowser的DocumentCompleted中分析HtmlDocument 来实现,代码如下: HtmlElement ClickBtn =null; if (e.Url.ToString().ToLower().IndexOf("http://sandou.cnblogs.com/") > 0) //登陆页面 { HtmlDocument doc = webBrowser1.Document; for (int i = 0; i < doc.All.Count ; i++) { if (doc.All[i].TagName.ToUpper().Equals("INPUT")) { switch (doc.All[i].Name) { case "userCtl": doc.All[i].InnerText = "user01"; break; case "passCt1": doc.All[i].InnerText = "mypass"; break; case "B1": ClickBtn = doc.All[i]; //提交按钮 break; } } } ClickBtn.InvokeMember("Click"); //执行按扭操作 } 2、WebClient封装了HTTP的一些类,操作简单,相较于webBrowser,特点是可以自设代理,缺点是对COOKIE的控制 WebClient的运行全在后台,并且提供了异步操作的能力,这样很方便并发多个任务,然后等待结果的返回,再逐个处理。多任务异步调用的代码如下: private void StartLoop(int ProxyNum) { WebClient [] wcArray = new WebClient[ProxyNum]; //初始化 for (int idArray = 0; idArray< ProxyNum;idArray++) { wcArray[idArray] = new WebClient(); wcArray[idArray].OpenReadCompleted += new OpenReadCompletedEventHandler(Pic_OpenReadCompleted2); wcArray[idArray].UploadDataCompleted += new UploadDataCompletedEventHandler(Pic_UploadDataCompleted2); try { wcArray[idArray].Proxy = new WebProxy(proxy[1], port); wcArray[idArray].OpenReadAsync(new Uri("http://sandou.cnblogs.com/")); //打开WEB; proxy = null; } catch { } } } private void Pic_OpenReadCompleted2(object sender, OpenReadCompletedEventArgs e) { if (e.Error == null) { string textData = new StreamReader(e.Result, Encoding.Default).ReadToEnd(); //取返回信息 .. String cookie = ((WebClient)sender).ResponseHeaders["Set-Cookie"]; ((WebClient)sender).Headers.Add("Content-Type", "application/x-www-form-urlencoded"); ((WebClient)sender).Headers.Add("Accept-Language", "zh-cn"); ((WebClient)sender).Headers.Add("Cookie", cookie); string postData = "" byte[] byteArray = Encoding.UTF8.GetBytes(postData); // 转化成二进制数组 ((WebClient)sender).UploadDataAsync(new Uri("http://sandou.cnblogs.com/"), "POST", byteArray); } } private void Pic_UploadDataCompleted2(object sender, UploadDataCompletedEventArgs e) { if (e.Error == null) { string returnMessage = Encoding.Default.GetString(e.Result); } } 3、HttpWebRequest较为低层,能实现的功能较多,Cookie操作也很简单: private bool PostWebRequest() { CookieContainer cc = new CookieContainer(); string pos tData = "user=" + strUser + "&pass=" + strPsd; byte[] byteArray = Encoding.UTF8.GetBytes(postData); // 转化 HttpWebRequest webRequest2 = (HttpWebRequest)WebRequest.Create(new Uri(http://sandou.cnblogs.com/)); webRequest2.CookieContainer = cc; webRequest2.Method = "POST"; webRequest2.ContentType = "application/x-www-form-urlencoded"; webRequest2.ContentLength = byteArray.Length; Stream newStream = webRequest2.GetRequestStream(); // Send the data. newStream.Write(byteArray, 0, byteArray.Length); //写入参数 newStream.Close(); HttpWebResponse response2 = (HttpWebResponse)webRequest2.GetResponse(); StreamReader sr2=new StreamReader(response2.GetResponseStream(), Encoding.Default); string text2 = sr2.ReadToEnd(); } HttpWebRequest 实现, 这个是从网上COPY 的!我以前用相关的代码登录到WWW.ASP.NET上,并且成功post,可惜代码不知道放什么地方了。 HttpWebRequest自动登录网站并获取网站内容(不包含验证码的网站) 可以使用 Visual Sniffer(百度搜索) 来捕捉提交的数据信息: 1. 访问你需要站外提交的页面,比如 CSDN 登陆页 http://www.csdn.net/member/UserLogin.aspx 2. 填写好需要的资料,比如用户名和密码, 3. 打开 Visual Sniffer, 点“开始拦截” 4. 在访问的页面中提交。 5. 等提交成功之后,在 Visual Sniffer 中“停止拦截” 6. 在 Visual Sniffer 的左侧栏的加号中依次点开,右边是它拦截到的内容: POST http://www.csdn.net/member/UserLogin.aspx HTTP/1.0 Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, ** Referer: http://www.csdn.net/member/UserLogin.aspx Accept-Language: zh-cn UA-CPU: x86 Pragma: no-cache User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; InfoPath.1) Host: www.csdn.net Proxy-Connection: Keep-Alive Cookie: ASPSESSIONIDAAAATBQC=FMEGGCKDBKHAMMCGKPFDMBFG; ASP.NET_SessionId=lusprmnom05lr445tmteaf55; userid=699879 以上为拦截内容,其中提交数据的参数部分(程序中的:strArgs)如: __EVENTTARGET=&__EVENTARGUMENT=&__VIEWSTATE=dDwtMTcwMzgxNjQ2Mjs7bDxDU 0ROVXNlckxvZ2luOmNiX1NhdmVTdGF0ZTtDU0ROVXNlckxvZ2luOkltYWdlX0xvZ2luOz4%2Btu 1q2wmRZoAJTi9L73w1zBleylY%3D&CSDNUserLogin%3Atb_UserName=testusername&CSDN UserLogin%3Atb_Password=testpassword&CSDNUserLogin%3Atb_ExPwd=9232 protected static string cookieHeader; private void Page_Load(object sender, System.EventArgs e) { string strReContent = string.Empty; //登录 strReContent = PostLogin("http://www.mystand.com.cn/login/submit.jsp提交的页面","提交的参数:userid=hgj0000&password=06045369","引用地址:http://www.mystand.com.cn/"); //asp.net登录传递的参数需注意 //strReContent = PostLogin("47bDxcZTs%2BPjs%2BOzs%2BOz4%2BOz6aX2dtqkJTK%2BKbNPsjd7Op%2Fl26Iw%3D%3D&txtUserName=hxf&txtPassword=hxf0000&btnEnter=%E7%99%BB%E5%BD%95","http://www.mystand.com.cn/login.aspx">http://www.mystand.com.cn/login.aspx","__VIEWSTATE=dDwtNjkzMjUyNDczO3Q8O2w8aTwzPjs%2BO2w8dDxwPHA8bDxUZXh0Oz47bDxcZTs%2BPjs%2BOzs%2BOz4%2BOz6aX2dtqkJTK%2BKbNPsjd7Op%2Fl26Iw%3D%3D&txtUserName=hxf&txtPassword=hxf0000&btnEnter=%E7%99%BB%E5%BD%95","http://www.mystand.com.cn/login.aspx"); //获取页面 strReContent = GetPage("http://www.mystand.com.cn/company/getdata.jsp?code=","引用地址:http://www.mystand.com.cn/"); //strReContent = GetPage("http://www.mystand.com.cn/Modules/index.aspx","http://www.mystand.com.cn/login.aspx"); //可以对获得的内容进行处理:strReContent } /// <summary> /// 功能描述:模拟登录页面,提交登录数据进行登录,并记录Header中的cookie /// </summary> /// <param name="strURL">登录数据提交的页面地址</param> /// <param name="strArgs">用户登录数据</param> /// <param name="strReferer">引用地址</param> /// <returns>可以返回页面内容或不返回</returns> public static string PostLogin(string strURL,string strArgs,string strReferer) { string strResult = ""; HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(strURL); myHttpWebRequest.AllowAutoRedirect = true; myHttpWebRequest.KeepAlive = true; myHttpWebRequest.Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, application/x-shockwave-flash, */// <summary> /// 功能描述:在PostLogin成功登录后记录下Headers中的cookie,然后获取此网站上其他页面的内容 /// </summary> /// <param name="strURL">获取网站的某页面的地址</param> /// <param name="strReferer">引用的地址</param> /// <returns>返回页面内容</returns> public static string GetPage(string strURL,string strReferer) { string strResult = ""; HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(strURL); myHttpWebRequest.ContentType = "text/html"; myHttpWebRequest.Method = "GET"; myHttpWebRequest.Referer = strReferer; myHttpWebRequest.Headers.Add("cookie:"+ cookieHeader); HttpWebResponse response = null; System.IO.StreamReader sr = null; response = (HttpWebResponse)myHttpWebRequest.GetResponse(); sr = new System.IO.StreamReader(response.GetResponseStream(), Encoding.GetEncoding("gb2312")); // //utf-8 strResult = sr.ReadToEnd(); return strResult; } 技术应用——网页自动登录(提交Post内容)的用途很多,如验证身份、程序升级、网络投票等,以下是用C#实现的方法. ================================================================================================================== 1.在WebBrowser中获取Cookie CookieContainer myCookieContainer = new CookieContainer(); string cookieStr = webBrowser1.Document.Cookie; string[] cookstr = cookieStr.Split(‘;‘); foreach (string str in cookstr) { string[] cookieNameValue = str.Split(‘=‘); Cookie ck = new Cookie(cookieNameValue[0].Trim ().ToString(), cookieNameValue[1].Trim ().ToString()); ck.Domain = "www.google.com"; myCookieContainer.Add(ck); } WebClient设置cookie! WebClient wc = new WebClient(); wc.Headers.Add("Cookie", "PHPSESSID=" + cookie + ";"); // 注意,这里是Cookie,不是Set-Cookie byte[] re = wc.UploadData(Global.RootPath + "test.php", new byte[0]); System.Text.UTF8Encoding converter = new System.Text.UTF8Encoding(); string str = converter.GetString(re); 2. 在WebBrowser中设置Cookie public partial class WebBrowserControl : Form { private String url; [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool InternetSetCookie(string lpszUrlName, string lbszCookieName, string lpszCookieData); public WebBrowserControl(String path) { this.url = path; InitializeComponent(); // set cookie InternetSetCookie(url, "JSESSIONID", Globals.ThisDocument.sessionID); // navigate webBrowser.Navigate(url); } } 3.将WebBrowser的cookie信息传给HttpWebRequest 先建一个"CookieContainer" 把WebBrowser中的Cookie保存在里面 //在WebBrowser中登录cookie保存在WebBrowser.Document.Cookie中 CookieContainer myCookieContainer = new CookieContainer(); //String 的Cookie 要转成 Cookie型的 并放入CookieContainer中 string cookieStr = webBrowser1.Document.Cookie; string[] cookstr = cookieStr.Split(‘;‘); foreach (string str in cookstr) { string[] cookieNameValue = str.Split(‘=‘); Cookie ck = new Cookie(cookieNameValue[0].Trim().ToString(), cookieNameValue[1].Trim().ToString()); ck.Domain = "www.abc.com";//必须写对 myCookieContainer.Add(ck); } HttpWebRequest hreq = (HttpWebRequest)HttpWebRequest.Create("http://www.abc.com/search.asp"); hreq.Method = "POST"; hreq.ContentType = "application/x-www-form-urlencoded"; //自己创建的CookieContainer hreq.CookieContainer = myCookieContainer; string postdata = "id=2005&action=search&name="; byte[] byte1 = Encoding.ASCII.GetBytes(postdata); hreq.ContentLength = byte1.Length; Stream poststream = hreq.GetRequestStream(); poststream.Write(byte1, 0, byte1.Length); poststream.Close(); HttpWebResponse hres = (HttpWebResponse)hreq.GetResponse();
C#实现SMTP服务器
C#实现SMTP服务器,使用TCP命令实现 using System; using System.Text; using System.IO; using System.Net; using System.Net.Sockets; using System.Collections; namespace SkyDev.Web.Mail { public enum MailFormat{Text,HTML}; public enum MailPriority{Low=1,Normal=3,High=5}; #region Class mailAttachments public class MailAttachments { private const int MaxAttachmentNum=10; private IList _Attachments; public MailAttachments() { _Attachments=new ArrayList(); } public string this[int index] { get { return (string)_Attachments[index];} } /// <summary> /// 添加邮件附件 /// </summary> /// <param name="FilePath">附件的绝对路径</param> public void Add(params string[] filePath) { if(filePath==null) { throw(new ArgumentNullException("非法的附件")); } else { for(int i=0;i<filePath.Length;i++) { Add(filePath[i]); } } } /// <summary> /// 添加一个附件,当指定的附件不存在时,忽略该附件,不产生异常。 /// </summary> /// <param name="filePath">附件的绝对路径</param> public void Add(string filePath) { //当附件存在时才加入,否则忽略 if (System.IO.File.Exists(filePath)) { if (_Attachments.Count<MaxAttachmentNum) { _Attachments.Add(filePath); } } } public void Clear()//清除所有附件 { _Attachments.Clear(); } public int Count//获取附件个数 { get { return _Attachments.Count;} } } #endregion//end Class mailAttachments #region Class MailMessage /// <summary> /// MailMessage 表示SMTP要发送的一封邮件的消息。 /// </summary> public class MailMessage { private const int MaxRecipientNum=10; public MailMessage() { _Recipients=new ArrayList();//收件人列表 _Attachments=new MailAttachments();//附件 _BodyFormat=MailFormat.Text;//缺省的邮件格式为Text _Priority=MailPriority.Normal; _Charset="GB2312"; } /// <summary> /// 设定语言代码,默认设定为GB2312,如不需要可设置为"" /// </summary> public string Charset { get { return _Charset;} set { _Charset=value;} } public string From { get{ return _From;} set { _From=value;} } public string FromName { get { return _FromName;} set { _FromName=value;} } public string Body { get { return _Body;} set { _Body=value;} } public string Subject { get { return _Subject;} set { _Subject=value;} } public MailAttachments Attachments { get {return _Attachments;} set { _Attachments=value;} } public MailPriority Priority { get { return _Priority;} set { _Priority=value;} } public IList Recipients { get { return _Recipients;} } /// <summary> /// 增加一个收件人地址 /// </summary> /// <param name="recipient">收件人的Email地址</param> public void AddRecipients(string recipient) { //先检查邮件地址是否符合规范 if (_Recipients.Count<MaxRecipientNum) { _Recipients.Add(recipient);//增加到收件人列表 } } public void AddRecipients(params string[] recipient) { if (recipient==null) { throw (new ArgumentException("收件人不能为空.")); } else { for (int i=0;i<recipient.Length;i++) { AddRecipients(recipient[i]); } } } public MailFormat BodyFormat { set { _BodyFormat=value;} get { return _BodyFormat;} } private string _From;//发件人地址 private string _FromName;//发件人姓名 private IList _Recipients;//收件人 private MailAttachments _Attachments;//附件 private string _Body;//内容 private string _Subject;//主题 private MailFormat _BodyFormat;//邮件格式 private string _Charset="GB2312";//字符编码格式 private MailPriority _Priority;//邮件优先级 } #endregion #region Class SmtpMail public class SmtpServerHelper { private string CRLF="\r\n";//回车换行 /// <summary> /// 错误消息反馈 /// </summary> private string errmsg; /// <summary> /// TcpClient对象,用于连接服务器 /// </summary> private TcpClient tcpClient; /// <summary> /// NetworkStream对象 /// </summary> private NetworkStream networkStream; /// <summary> /// 服务器交互记录 /// </summary> private string logs=""; /// <summary> /// SMTP错误代码哈希表 /// </summary> private Hashtable ErrCodeHT = new Hashtable(); /// <summary> /// SMTP正确代码哈希表 /// </summary> private Hashtable RightCodeHT = new Hashtable(); public SmtpServerHelper() { SMTPCodeAdd();//初始化SMTPCode } ~SmtpServerHelper() { networkStream.Close(); tcpClient.Close(); } /// <summary> /// 将字符串编码为Base64字符串 /// </summary> /// <param name="str">要编码的字符串</param> private string Base64Encode(string str) { byte[] barray; barray=Encoding.Default.GetBytes(str); return Convert.ToBase64String(barray); } /// <summary> /// 将Base64字符串解码为普通字符串 /// </summary> /// <param name="str">要解码的字符串</param> private string Base64Decode(string str) { byte[] barray; barray=Convert.FromBase64String(str); return Encoding.Default.GetString(barray); } /// <summary> /// 得到上传附件的文件流 /// </summary> /// <param name="FilePath">附件的绝对路径</param> private string GetStream(string FilePath) { //建立文件流对象 System.IO.FileStream FileStr=new System.IO.FileStream(FilePath,System.IO.FileMode.Open); byte[] by=new byte[System.Convert.ToInt32(FileStr.Length)]; FileStr.Read(by,0,by.Length); FileStr.Close(); return(System.Convert.ToBase64String(by)); } /// <summary> /// SMTP回应代码哈希表 /// </summary> private void SMTPCodeAdd() { //[RFC 821 4.2.1.] /* 4.2.2. NUMERIC ORDER LIST OF REPLY CODES 211 System status, or system help reply 214 Help message [Information on how to use the receiver or the meaning of a particular non-standard command; this reply is useful only to the human user] 220 <domain> Service ready 221 <domain> Service closing transmission channel 250 Requested mail action okay, completed 251 User not local; will forward to <forward-path> 354 Start mail input; end with <CRLF>.<CRLF> 421 <domain> Service not available, closing transmission channel [This may be a reply to any command if the service knows it must shut down] 450 Requested mail action not taken: mailbox unavailable [E.g., mailbox busy] 451 Requested action aborted: local error in processing 452 Requested action not taken: insufficient system storage 500 Syntax error, command unrecognized [This may include errors such as command line too long] 501 Syntax error in parameters or arguments 502 Command not implemented 503 Bad sequence of commands 504 Command parameter not implemented 550 Requested action not taken: mailbox unavailable [E.g., mailbox not found, no access] 551 User not local; please try <forward-path> 552 Requested mail action aborted: exceeded storage allocation 553 Requested action not taken: mailbox name not allowed [E.g., mailbox syntax incorrect] 554 Transaction failed */ ErrCodeHT.Add("421","服务未就绪,关闭传输信道"); ErrCodeHT.Add("432","需要一个密码转换"); ErrCodeHT.Add("450","要求的邮件操作未完成,邮箱不可用(例如,邮箱忙)"); ErrCodeHT.Add("451","放弃要求的操作;处理过程中出错"); ErrCodeHT.Add("452","系统存储不足,要求的操作未执行"); ErrCodeHT.Add("454","临时认证失败"); ErrCodeHT.Add("500","邮箱地址错误"); ErrCodeHT.Add("501","参数格式错误"); ErrCodeHT.Add("502","命令不可实现"); ErrCodeHT.Add("503","服务器需要SMTP验证"); ErrCodeHT.Add("504","命令参数不可实现"); ErrCodeHT.Add("530","需要认证"); ErrCodeHT.Add("534","认证机制过于简单"); ErrCodeHT.Add("538","当前请求的认证机制需要加密"); ErrCodeHT.Add("550","要求的邮件操作未完成,邮箱不可用(例如,邮箱未找到,或不可访问)"); ErrCodeHT.Add("551","用户非本地,请尝试<forward-path>"); ErrCodeHT.Add("552","过量的存储分配,要求的操作未执行"); ErrCodeHT.Add("553","邮箱名不可用,要求的操作未执行(例如邮箱格式错误)"); ErrCodeHT.Add("554","传输失败"); /* 211 System status, or system help reply 214 Help message [Information on how to use the receiver or the meaning of a particular non-standard command; this reply is useful only to the human user] 220 <domain> Service ready 221 <domain> Service closing transmission channel 250 Requested mail action okay, completed 251 User not local; will forward to <forward-path> 354 Start mail input; end with <CRLF>.<CRLF> */ RightCodeHT.Add("220","服务就绪"); RightCodeHT.Add("221","服务关闭传输信道"); RightCodeHT.Add("235","验证成功"); RightCodeHT.Add("250","要求的邮件操作完成"); RightCodeHT.Add("251","非本地用户,将转发向<forward-path>"); RightCodeHT.Add("334","服务器响应验证Base64字符串"); RightCodeHT.Add("354","开始邮件输入,以<CRLF>.<CRLF>结束"); } /// <summary> /// 发送SMTP命令 /// </summary> private bool SendCommand(string str) { byte[]WriteBuffer; if(str==null||str.Trim()==String.Empty) { return true; } logs+=str; WriteBuffer = Encoding.Default.GetBytes(str); try { networkStream.Write(WriteBuffer,0,WriteBuffer.Length); } catch { errmsg="网络连接错误"; return false; } return true; } /// <summary> /// 接收SMTP服务器回应 /// </summary> private string RecvResponse() { int StreamSize; string Returnvalue = String.Empty; byte[] ReadBuffer = new byte[1024] ; try { StreamSize=networkStream.Read(ReadBuffer,0,ReadBuffer.Length); } catch { errmsg="网络连接错误"; return "false"; } if (StreamSize==0) { return Returnvalue ; } else { Returnvalue = Encoding.Default.GetString(ReadBuffer).Substring(0,StreamSize); logs+=Returnvalue+this.CRLF; return Returnvalue; } } /// <summary> /// 与服务器交互,发送一条命令并接收回应。 /// </summary> /// <param name="str">一个要发送的命令</param> /// <param name="errstr">如果错误,要反馈的信息</param> private bool Dialog(string str,string errstr) { if(str==null||str.Trim()==string.Empty) { return true; } if(SendCommand(str)) { string RR=RecvResponse(); if(RR=="false") { return false; } //检查返回的代码,根据[RFC 821]返回代码为3位数字代码如220 string RRCode=RR.Substring(0,3); if(RightCodeHT[RRCode]!=null) { return true; } else { if(ErrCodeHT[RRCode]!=null) { errmsg+=(RRCode+ErrCodeHT[RRCode].ToString()); errmsg+=CRLF; } else { errmsg+=RR; } errmsg+=errstr; return false; } } else { return false; } } /// <summary> /// 与服务器交互,发送一组命令并接收回应。 /// </summary> private bool Dialog(string[] str,string errstr) { for(int i=0;i<str.Length;i++) { if(!Dialog(str[i],"")) { errmsg+=CRLF; errmsg+=errstr; return false; } } return true; } //连接服务器 private bool Connect(string smtpServer,int port) { //创建Tcp连接 try { tcpClient=new TcpClient(smtpServer,port); } catch(Exception e) { errmsg=e.ToString(); return false; } networkStream=tcpClient.GetStream(); //验证网络连接是否正确 if(RightCodeHT[RecvResponse().Substring(0,3)]==null) { errmsg="网络连接失败"; return false; } return true; } private string GetPriorityString(MailPriority mailPriority) { string priority="Normal"; if (mailPriority==MailPriority.Low) { priority="Low"; } else if (mailPriority==MailPriority.High) { priority="High"; } return priority; } /// <summary> /// 发送电子邮件,SMTP服务器不需要身份验证 /// </summary> /// <param name="smtpServer"></param> /// <param name="port"></param> /// <param name="mailMessage"></param> /// <returns></returns> public bool SendEmail(string smtpServer,int port,MailMessage mailMessage) { return SendEmail(smtpServer,port,false,"","",mailMessage); } /// <summary> /// 发送电子邮件,SMTP服务器需要身份验证 /// </summary> /// <param name="smtpServer"></param> /// <param name="port"></param> /// <param name="username"></param> /// <param name="password"></param> /// <param name="mailMessage"></param> /// <returns></returns> public bool SendEmail(string smtpServer,int port,string username,string password,MailMessage mailMessage) { return SendEmail(smtpServer,port,false,username,password,mailMessage); } private bool SendEmail(string smtpServer,int port,bool ESmtp,string username,string password,MailMessage mailMessage) { if (Connect(smtpServer,port)==false)//测试连接服务器是否成功 return false; string priority=GetPriorityString(mailMessage.Priority); bool Html=(mailMessage.BodyFormat==MailFormat.HTML); string[] SendBuffer; string SendBufferstr; //进行SMTP验证,现在大部分SMTP服务器都要认证 if(ESmtp) { SendBuffer=new String[4]; SendBuffer[0]="EHLO " + smtpServer + CRLF; SendBuffer[1]="AUTH LOGIN" + CRLF; SendBuffer[2]=Base64Encode(username) + CRLF; SendBuffer[3]=Base64Encode(password) + CRLF; if(!Dialog(SendBuffer,"SMTP服务器验证失败,请核对用户名和密码。")) return false; } else {//不需要身份认证 SendBufferstr="HELO " + smtpServer + CRLF; if(!Dialog(SendBufferstr,"")) return false; } //发件人地址 SendBufferstr="MAIL FROM:<" + mailMessage.From + ">" + CRLF; if(!Dialog(SendBufferstr,"发件人地址错误,或不能为空")) return false; //收件人地址 SendBuffer=new string[mailMessage.Recipients.Count]; for(int i=0;i<mailMessage.Recipients.Count;i++) { SendBuffer[i]="RCPT TO:<" +(string)mailMessage.Recipients[i] +">" + CRLF; } if(!Dialog(SendBuffer,"收件人地址有误")) return false; /* SendBuffer=new string[10]; for(int i=0;i<RecipientBCC.Count;i++) { SendBuffer[i]="RCPT TO:<" + RecipientBCC[i].ToString() +">" + CRLF; } if(!Dialog(SendBuffer,"密件收件人地址有误")) return false; */ SendBufferstr="DATA" + CRLF; if(!Dialog(SendBufferstr,"")) return false; //发件人姓名 SendBufferstr="From:" + mailMessage.FromName + "<" +mailMessage.From +">" +CRLF; //if(ReplyTo.Trim()!="") //{ // SendBufferstr+="Reply-To: " + ReplyTo + CRLF; //} //SendBufferstr+="To:" + ToName + "<" + Recipient[0] +">" +CRLF; //至少要有一个收件人 if (mailMessage.Recipients.Count==0) { return false; } else { SendBufferstr += "To:=?"+mailMessage.Charset.ToUpper()+"?B?"+ Base64Encode((string)mailMessage.Recipients[0])+"?="+"<"+(string)mailMessage.Recipients[0]+">"+CRLF; } //SendBufferstr+="CC:"; //for(int i=0;i<Recipient.Count;i++) //{ // SendBufferstr+=Recipient[i].ToString() + "<" + Recipient[i].ToString() +">,"; //} //SendBufferstr+=CRLF; SendBufferstr+= ((mailMessage.Subject==String.Empty || mailMessage.Subject==null)?"Subject:":((mailMessage.Charset=="")?("Subject:" + mailMessage.Subject):("Subject:" + "=?" + mailMessage.Charset.ToUpper() + "?B?" + Base64Encode(mailMessage.Subject) +"?="))) + CRLF; SendBufferstr+="X-Priority:" + priority + CRLF; SendBufferstr+="X-MSMail-Priority:" + priority + CRLF; SendBufferstr+="Importance:" + priority + CRLF; SendBufferstr+="X-Mailer: Lion.Web.Mail.SmtpMail Pubclass [cn]" + CRLF; SendBufferstr+="MIME-Version: 1.0" + CRLF; if(mailMessage.Attachments.Count!=0) { SendBufferstr+="Content-Type: multipart/mixed;" + CRLF; SendBufferstr += " boundary=\"====="+ (Html?"001_Dragon520636771063_":"001_Dragon303406132050_")+"=====\""+CRLF+CRLF; } if(Html) { if(mailMessage.Attachments.Count==0) { SendBufferstr += "Content-Type: multipart/alternative;"+CRLF;//内容格式和分隔符 SendBufferstr += " boundary=\"=====003_Dragon520636771063_=====\""+CRLF+CRLF; SendBufferstr += "This is a multi-part message in MIME format."+CRLF+CRLF; } else { SendBufferstr +="This is a multi-part message in MIME format."+CRLF+CRLF; SendBufferstr += "--=====001_Dragon520636771063_====="+CRLF; SendBufferstr += "Content-Type: multipart/alternative;"+CRLF;//内容格式和分隔符 SendBufferstr += " boundary=\"=====003_Dragon520636771063_=====\""+CRLF+CRLF; } SendBufferstr += "--=====003_Dragon520636771063_====="+CRLF; SendBufferstr += "Content-Type: text/plain;"+ CRLF; SendBufferstr += ((mailMessage.Charset=="")?(" charset=\"iso-8859-1\""):(" charset=\"" + mailMessage.Charset.ToLower() + "\"")) + CRLF; SendBufferstr+="Content-Transfer-Encoding: base64" + CRLF + CRLF; SendBufferstr+= Base64Encode("邮件内容为HTML格式,请选择HTML方式查看") + CRLF + CRLF; SendBufferstr += "--=====003_Dragon520636771063_====="+CRLF; SendBufferstr+="Content-Type: text/html;" + CRLF; SendBufferstr+=((mailMessage.Charset=="")?(" charset=\"iso-8859-1\""):(" charset=\"" + mailMessage.Charset.ToLower() + "\"")) + CRLF; SendBufferstr+="Content-Transfer-Encoding: base64" + CRLF + CRLF; SendBufferstr+= Base64Encode(mailMessage.Body) + CRLF + CRLF; SendBufferstr += "--=====003_Dragon520636771063_=====--"+CRLF; } else { if(mailMessage.Attachments.Count!=0) { SendBufferstr += "--=====001_Dragon303406132050_====="+CRLF; } SendBufferstr+="Content-Type: text/plain;" + CRLF; SendBufferstr+=((mailMessage.Charset=="")?(" charset=\"iso-8859-1\""):(" charset=\"" + mailMessage.Charset.ToLower() + "\"")) + CRLF; SendBufferstr+="Content-Transfer-Encoding: base64" + CRLF + CRLF; SendBufferstr+= Base64Encode(mailMessage.Body) + CRLF; } //SendBufferstr += "Content-Transfer-Encoding: base64"+CRLF; if(mailMessage.Attachments.Count!=0) { for(int i=0;i<mailMessage.Attachments.Count;i++) { string filepath = (string)mailMessage.Attachments[i]; SendBufferstr += "--====="+ (Html?"001_Dragon520636771063_":"001_Dragon303406132050_") +"====="+CRLF; //SendBufferstr += "Content-Type: application/octet-stream"+CRLF; SendBufferstr += "Content-Type: text/plain;"+CRLF; SendBufferstr += " name=\"=?"+mailMessage.Charset.ToUpper()+"?B?"+ Base64Encode(filepath.Substring(filepath.LastIndexOf("\\")+1))+"?=\""+CRLF; SendBufferstr += "Content-Transfer-Encoding: base64"+CRLF; SendBufferstr += "Content-Disposition: attachment;"+CRLF; SendBufferstr += " filename=\"=?"+mailMessage.Charset.ToUpper()+"?B?"+ Base64Encode(filepath.Substring(filepath.LastIndexOf("\\")+1))+"?=\""+CRLF+CRLF; SendBufferstr += GetStream(filepath)+CRLF+CRLF; } SendBufferstr += "--====="+ (Html?"001_Dragon520636771063_":"001_Dragon303406132050_")+"=====--"+CRLF+CRLF; } SendBufferstr += CRLF + "." + CRLF;//内容结束 if(!Dialog(SendBufferstr,"错误信件信息")) return false; SendBufferstr="QUIT" + CRLF; if(!Dialog(SendBufferstr,"断开连接时错误")) return false; networkStream.Close(); tcpClient.Close(); return true; } } public class SmtpMail { private static string _SmtpServer; /// <summary> /// 格式:SmtpAccount:Password@SmtpServerAddress<br> /// 或者:SmtpServerAddress<br> /// <code> /// SmtpMail.SmtpServer="user:12345678@smtp.126.com"; /// //或者: /// SmtpMail.SmtpServer="smtp.126.com"; /// 或者: /// SmtpMail.SmtpServer=SmtpServerHelper.GetSmtpServer("user","12345678","smtp.126.com"); /// </code> /// </summary> public static string SmtpServer { set { _SmtpServer=value;} get { return _SmtpServer;} } public static bool Send(MailMessage mailMessage,string username,string password) { SmtpServerHelper helper=new SmtpServerHelper(); return helper.SendEmail(_SmtpServer,25,username,password,mailMessage); } } #endregion } using System; using NUnit.Framework; namespace SkyDev.Web.Mail { /// <summary> /// Test 的摘要说明。 /// </summary> [TestFixture] public class TestSmtpMail { //安装测试用例,完成初始化操作 [SetUp] public void SetUp() { } //测试结束完成清理操作 [TearDown] public void TearDown() { } [Test] public void TestMailAttachments() { SkyDev.Web.Mail.MailAttachments attachments=new MailAttachments(); Assert.AreEqual(0,attachments.Count,"初始化MailAttachments"); attachments.Add("c:\\autoexec.bat"); Assert.AreEqual(1,attachments.Count,"增加附件(附件确实存在)"); attachments.Add("c:\\autoexec.dat.txt"); Assert.AreEqual(1,attachments.Count,"增加附件(附件不存在)"); attachments.Clear(); Assert.AreEqual(0,attachments.Count,"清除附件"); } [Test] public void TestMailMessage() { MailMessage message=new MailMessage(); Assert.AreEqual(0,message.Attachments.Count,"初始化MailAttachments"); Assert.AreEqual(MailFormat.Text,message.BodyFormat,"邮件格式"); Assert.AreEqual("GB2312",message.Charset,"缺省的字符集"); } [Test] public void TestSendMail() { SmtpMail.SmtpServer="smtp.126.com"; MailMessage mail=new MailMessage(); mail.From="qs1976@126.com"; mail.FromName="曾青松"; mail.AddRecipients("qs1976@126.com"); mail.Subject="主题:测试邮件"; mail.BodyFormat=MailFormat.Text; mail.Body="测试的内容."; mail.Attachments.Add("c:\\test.txt"); SmtpMail.Send(mail,"","");//请填写自己的测试邮件帐号 } } } 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/21aspnet/archive/2007/03/24/1539942.aspx
C#实现SMTP服务器,使用TCP命令实现,功能比较完善_
using System; using System.Text; using System.IO; using System.Net; using System.Net.Sockets; using System.Collections; namespace SkyDev.Web.Mail { public enum MailFormat{Text,HTML}; public enum MailPriority{Low=1,Normal=3,High=5}; #region Class mailAttachments public class MailAttachments { private const int MaxAttachmentNum=10; private IList _Attachments; public MailAttachments() { _Attachments=new ArrayList(); } public string this[int index] { get { return (string)_Attachments[index];} } /// <summary> /// 添加邮件附件 /// </summary> /// <param name="FilePath">附件的绝对路径</param> public void Add(params string[] filePath) { if(filePath==null) { throw(new ArgumentNullException("非法的附件")); } else { for(int i=0;i<filePath.Length;i++) { Add(filePath[i]); } } } /// <summary> /// 添加一个附件,当指定的附件不存在时,忽略该附件,不产生异常。 /// </summary> /// <param name="filePath">附件的绝对路径</param> public void Add(string filePath) { //当附件存在时才加入,否则忽略 if (System.IO.File.Exists(filePath)) { if (_Attachments.Count<MaxAttachmentNum) { _Attachments.Add(filePath); } } } public void Clear()//清除所有附件 { _Attachments.Clear(); } public int Count//获取附件个数 { get { return _Attachments.Count;} } } #endregion//end Class mailAttachments #region Class MailMessage /// <summary> /// MailMessage 表示SMTP要发送的一封邮件的消息。 /// </summary> public class MailMessage { private const int MaxRecipientNum=10; public MailMessage() { _Recipients=new ArrayList();//收件人列表 _Attachments=new MailAttachments();//附件 _BodyFormat=MailFormat.Text;//缺省的邮件格式为Text _Priority=MailPriority.Normal; _Charset="GB2312"; } /// <summary> /// 设定语言代码,默认设定为GB2312,如不需要可设置为"" /// </summary> public string Charset { get { return _Charset;} set { _Charset=value;} } public string From { get{ return _From;} set { _From=value;} } public string FromName { get { return _FromName;} set { _FromName=value;} } public string Body { get { return _Body;} set { _Body=value;} } public string Subject { get { return _Subject;} set { _Subject=value;} } public MailAttachments Attachments { get {return _Attachments;} set { _Attachments=value;} } public MailPriority Priority { get { return _Priority;} set { _Priority=value;} } public IList Recipients { get { return _Recipients;} } /// <summary> /// 增加一个收件人地址 /// </summary> /// <param name="recipient">收件人的Email地址</param> public void AddRecipients(string recipient) { //先检查邮件地址是否符合规范 if (_Recipients.Count<MaxRecipientNum) { _Recipients.Add(recipient);//增加到收件人列表 } } public void AddRecipients(params string[] recipient) { if (recipient==null) { throw (new ArgumentException("收件人不能为空.")); } else { for (int i=0;i<recipient.Length;i++) { AddRecipients(recipient[i]); } } } public MailFormat BodyFormat { set { _BodyFormat=value;} get { return _BodyFormat;} } private string _From;//发件人地址 private string _FromName;//发件人姓名 private IList _Recipients;//收件人 private MailAttachments _Attachments;//附件 private string _Body;//内容 private string _Subject;//主题 private MailFormat _BodyFormat;//邮件格式 private string _Charset="GB2312";//字符编码格式 private MailPriority _Priority;//邮件优先级 } #endregion #region Class SmtpMail public class SmtpServerHelper { private string CRLF="\r\n";//回车换行 /// <summary> /// 错误消息反馈 /// </summary> private string errmsg; /// <summary> /// TcpClient对象,用于连接服务器 /// </summary> private TcpClient tcpClient; /// <summary> /// NetworkStream对象 /// </summary> private NetworkStream networkStream; /// <summary> /// 服务器交互记录 /// </summary> private string logs=""; /// <summary> /// SMTP错误代码哈希表 /// </summary> private Hashtable ErrCodeHT = new Hashtable(); /// <summary> /// SMTP正确代码哈希表 /// </summary> private Hashtable RightCodeHT = new Hashtable(); public SmtpServerHelper() { SMTPCodeAdd();//初始化SMTPCode } ~SmtpServerHelper() { networkStream.Close(); tcpClient.Close(); } /// <summary> /// 将字符串编码为Base64字符串 /// </summary> /// <param name="str">要编码的字符串</param> private string Base64Encode(string str) { byte[] barray; barray=Encoding.Default.GetBytes(str); return Convert.ToBase64String(barray); } /// <summary> /// 将Base64字符串解码为普通字符串 /// </summary> /// <param name="str">要解码的字符串</param> private string Base64Decode(string str) { byte[] barray; barray=Convert.FromBase64String(str); return Encoding.Default.GetString(barray); } /// <summary> /// 得到上传附件的文件流 /// </summary> /// <param name="FilePath">附件的绝对路径</param> private string GetStream(string FilePath) { //建立文件流对象 System.IO.FileStream FileStr=new System.IO.FileStream(FilePath,System.IO.FileMode.Open); byte[] by=new byte[System.Convert.ToInt32(FileStr.Length)]; FileStr.Read(by,0,by.Length); FileStr.Close(); return(System.Convert.ToBase64String(by)); } /// <summary> /// SMTP回应代码哈希表 /// </summary> private void SMTPCodeAdd() { //[RFC 821 4.2.1.] /* 4.2.2. NUMERIC ORDER LIST OF REPLY CODES 211 System status, or system help reply 214 Help message [Information on how to use the receiver or the meaning of a particular non-standard command; this reply is useful only to the human user] 220 <domain> Service ready 221 <domain> Service closing transmission channel 250 Requested mail action okay, completed 251 User not local; will forward to <forward-path> 354 Start mail input; end with <CRLF>.<CRLF> 421 <domain> Service not available, closing transmission channel [This may be a reply to any command if the service knows it must shut down] 450 Requested mail action not taken: mailbox unavailable [E.g., mailbox busy] 451 Requested action aborted: local error in processing 452 Requested action not taken: insufficient system storage 500 Syntax error, command unrecognized [This may include errors such as command line too long] 501 Syntax error in parameters or arguments 502 Command not implemented 503 Bad sequence of commands 504 Command parameter not implemented 550 Requested action not taken: mailbox unavailable [E.g., mailbox not found, no access] 551 User not local; please try <forward-path> 552 Requested mail action aborted: exceeded storage allocation 553 Requested action not taken: mailbox name not allowed [E.g., mailbox syntax incorrect] 554 Transaction failed */ ErrCodeHT.Add("421","服务未就绪,关闭传输信道"); ErrCodeHT.Add("432","需要一个密码转换"); ErrCodeHT.Add("450","要求的邮件操作未完成,邮箱不可用(例如,邮箱忙)"); ErrCodeHT.Add("451","放弃要求的操作;处理过程中出错"); ErrCodeHT.Add("452","系统存储不足,要求的操作未执行"); ErrCodeHT.Add("454","临时认证失败"); ErrCodeHT.Add("500","邮箱地址错误"); ErrCodeHT.Add("501","参数格式错误"); ErrCodeHT.Add("502","命令不可实现"); ErrCodeHT.Add("503","服务器需要SMTP验证"); ErrCodeHT.Add("504","命令参数不可实现"); ErrCodeHT.Add("530","需要认证"); ErrCodeHT.Add("534","认证机制过于简单"); ErrCodeHT.Add("538","当前请求的认证机制需要加密"); ErrCodeHT.Add("550","要求的邮件操作未完成,邮箱不可用(例如,邮箱未找到,或不可访问)"); ErrCodeHT.Add("551","用户非本地,请尝试<forward-path>"); ErrCodeHT.Add("552","过量的存储分配,要求的操作未执行"); ErrCodeHT.Add("553","邮箱名不可用,要求的操作未执行(例如邮箱格式错误)"); ErrCodeHT.Add("554","传输失败"); /* 211 System status, or system help reply 214 Help message [Information on how to use the receiver or the meaning of a particular non-standard command; this reply is useful only to the human user] 220 <domain> Service ready 221 <domain> Service closing transmission channel 250 Requested mail action okay, completed 251 User not local; will forward to <forward-path> 354 Start mail input; end with <CRLF>.<CRLF> */ RightCodeHT.Add("220","服务就绪"); RightCodeHT.Add("221","服务关闭传输信道"); RightCodeHT.Add("235","验证成功"); RightCodeHT.Add("250","要求的邮件操作完成"); RightCodeHT.Add("251","非本地用户,将转发向<forward-path>"); RightCodeHT.Add("334","服务器响应验证Base64字符串"); RightCodeHT.Add("354","开始邮件输入,以<CRLF>.<CRLF>结束"); } /// <summary> /// 发送SMTP命令 /// </summary> private bool SendCommand(string str) { byte[]WriteBuffer; if(str==null||str.Trim()==String.Empty) { return true; } logs+=str; WriteBuffer = Encoding.Default.GetBytes(str); try { networkStream.Write(WriteBuffer,0,WriteBuffer.Length); } catch { errmsg="网络连接错误"; return false; } return true; } /// <summary> /// 接收SMTP服务器回应 /// </summary> private string RecvResponse() { int StreamSize; string Returnvalue = String.Empty; byte[] ReadBuffer = new byte[1024] ; try { StreamSize=networkStream.Read(ReadBuffer,0,ReadBuffer.Length); } catch { errmsg="网络连接错误"; return "false"; } if (StreamSize==0) { return Returnvalue ; } else { Returnvalue = Encoding.Default.GetString(ReadBuffer).Substring(0,StreamSize); logs+=Returnvalue+this.CRLF; return Returnvalue; } } /// <summary> /// 与服务器交互,发送一条命令并接收回应。 /// </summary> /// <param name="str">一个要发送的命令</param> /// <param name="errstr">如果错误,要反馈的信息</param> private bool Dialog(string str,string errstr) { if(str==null||str.Trim()==string.Empty) { return true; } if(SendCommand(str)) { string RR=RecvResponse(); if(RR=="false") { return false; } //检查返回的代码,根据[RFC 821]返回代码为3位数字代码如220 string RRCode=RR.Substring(0,3); if(RightCodeHT[RRCode]!=null) { return true; } else { if(ErrCodeHT[RRCode]!=null) { errmsg+=(RRCode+ErrCodeHT[RRCode].ToString()); errmsg+=CRLF; } else { errmsg+=RR; } errmsg+=errstr; return false; } } else { return false; } } /// <summary> /// 与服务器交互,发送一组命令并接收回应。 /// </summary> private bool Dialog(string[] str,string errstr) { for(int i=0;i<str.Length;i++) { if(!Dialog(str[i],"")) { errmsg+=CRLF; errmsg+=errstr; return false; } } return true; } //连接服务器 private bool Connect(string smtpServer,int port) { //创建Tcp连接 try { tcpClient=new TcpClient(smtpServer,port); } catch(Exception e) { errmsg=e.ToString(); return false; } networkStream=tcpClient.GetStream(); //验证网络连接是否正确 if(RightCodeHT[RecvResponse().Substring(0,3)]==null) { errmsg="网络连接失败"; return false; } return true; } private string GetPriorityString(MailPriority mailPriority) { string priority="Normal"; if (mailPriority==MailPriority.Low) { priority="Low"; } else if (mailPriority==MailPriority.High) { priority="High"; } return priority; } /// <summary> /// 发送电子邮件,SMTP服务器不需要身份验证 /// </summary> /// <param name="smtpServer"></param> /// <param name="port"></param> /// <param name="mailMessage"></param> /// <returns></returns> public bool SendEmail(string smtpServer,int port,MailMessage mailMessage) { return SendEmail(smtpServer,port,false,"","",mailMessage); } /// <summary> /// 发送电子邮件,SMTP服务器需要身份验证 /// </summary> /// <param name="smtpServer"></param> /// <param name="port"></param> /// <param name="username"></param> /// <param name="password"></param> /// <param name="mailMessage"></param> /// <returns></returns> public bool SendEmail(string smtpServer,int port,string username,string password,MailMessage mailMessage) { return SendEmail(smtpServer,port,false,username,password,mailMessage); } private bool SendEmail(string smtpServer,int port,bool ESmtp,string username,string password,MailMessage mailMessage) { if (Connect(smtpServer,port)==false)//测试连接服务器是否成功 return false; string priority=GetPriorityString(mailMessage.Priority); bool Html=(mailMessage.BodyFormat==MailFormat.HTML); string[] SendBuffer; string SendBufferstr; //进行SMTP验证,现在大部分SMTP服务器都要认证 if(ESmtp) { SendBuffer=new String[4]; SendBuffer[0]="EHLO " + smtpServer + CRLF; SendBuffer[1]="AUTH LOGIN" + CRLF; SendBuffer[2]=Base64Encode(username) + CRLF; SendBuffer[3]=Base64Encode(password) + CRLF; if(!Dialog(SendBuffer,"SMTP服务器验证失败,请核对用户名和密码。")) return false; } else {//不需要身份认证 SendBufferstr="HELO " + smtpServer + CRLF; if(!Dialog(SendBufferstr,"")) return false; } //发件人地址 SendBufferstr="MAIL FROM:<" + mailMessage.From + ">" + CRLF; if(!Dialog(SendBufferstr,"发件人地址错误,或不能为空")) return false; //收件人地址 SendBuffer=new string[mailMessage.Recipients.Count]; for(int i=0;i<mailMessage.Recipients.Count;i++) { SendBuffer[i]="RCPT TO:<" +(string)mailMessage.Recipients[i] +">" + CRLF; } if(!Dialog(SendBuffer,"收件人地址有误")) return false; /* SendBuffer=new string[10]; for(int i=0;i<RecipientBCC.Count;i++) { SendBuffer[i]="RCPT TO:<" + RecipientBCC[i].ToString() +">" + CRLF; } if(!Dialog(SendBuffer,"密件收件人地址有误")) return false; */ SendBufferstr="DATA" + CRLF; if(!Dialog(SendBufferstr,"")) return false; //发件人姓名 SendBufferstr="From:" + mailMessage.FromName + "<" +mailMessage.From +">" +CRLF; //if(ReplyTo.Trim()!="") //{ // SendBufferstr+="Reply-To: " + ReplyTo + CRLF; //} //SendBufferstr+="To:" + ToName + "<" + Recipient[0] +">" +CRLF; //至少要有一个收件人 if (mailMessage.Recipients.Count==0) { return false; } else { SendBufferstr += "To:=?"+mailMessage.Charset.ToUpper()+"?B?"+ Base64Encode((string)mailMessage.Recipients[0])+"?="+"<"+(string)mailMessage.Recipients[0]+">"+CRLF; } //SendBufferstr+="CC:"; //for(int i=0;i<Recipient.Count;i++) //{ // SendBufferstr+=Recipient[i].ToString() + "<" + Recipient[i].ToString() +">,"; //} //SendBufferstr+=CRLF; SendBufferstr+= ((mailMessage.Subject==String.Empty || mailMessage.Subject==null)?"Subject:":((mailMessage.Charset=="")?("Subject:" + mailMessage.Subject):("Subject:" + "=?" + mailMessage.Charset.ToUpper() + "?B?" + Base64Encode(mailMessage.Subject) +"?="))) + CRLF; SendBufferstr+="X-Priority:" + priority + CRLF; SendBufferstr+="X-MSMail-Priority:" + priority + CRLF; SendBufferstr+="Importance:" + priority + CRLF; SendBufferstr+="X-Mailer: Lion.Web.Mail.SmtpMail Pubclass [cn]" + CRLF; SendBufferstr+="MIME-Version: 1.0" + CRLF; if(mailMessage.Attachments.Count!=0) { SendBufferstr+="Content-Type: multipart/mixed;" + CRLF; SendBufferstr += " boundary=\"====="+ (Html?"001_Dragon520636771063_":"001_Dragon303406132050_")+"=====\""+CRLF+CRLF; } if(Html) { if(mailMessage.Attachments.Count==0) { SendBufferstr += "Content-Type: multipart/alternative;"+CRLF;//内容格式和分隔符 SendBufferstr += " boundary=\"=====003_Dragon520636771063_=====\""+CRLF+CRLF; SendBufferstr += "This is a multi-part message in MIME format."+CRLF+CRLF; } else { SendBufferstr +="This is a multi-part message in MIME format."+CRLF+CRLF; SendBufferstr += "--=====001_Dragon520636771063_====="+CRLF; SendBufferstr += "Content-Type: multipart/alternative;"+CRLF;//内容格式和分隔符 SendBufferstr += " boundary=\"=====003_Dragon520636771063_=====\""+CRLF+CRLF; } SendBufferstr += "--=====003_Dragon520636771063_====="+CRLF; SendBufferstr += "Content-Type: text/plain;"+ CRLF; SendBufferstr += ((mailMessage.Charset=="")?(" charset=\"iso-8859-1\""):(" charset=\"" + mailMessage.Charset.ToLower() + "\"")) + CRLF; SendBufferstr+="Content-Transfer-Encoding: base64" + CRLF + CRLF; SendBufferstr+= Base64Encode("邮件内容为HTML格式,请选择HTML方式查看") + CRLF + CRLF; SendBufferstr += "--=====003_Dragon520636771063_====="+CRLF; SendBufferstr+="Content-Type: text/html;" + CRLF; SendBufferstr+=((mailMessage.Charset=="")?(" charset=\"iso-8859-1\""):(" charset=\"" + mailMessage.Charset.ToLower() + "\"")) + CRLF; SendBufferstr+="Content-Transfer-Encoding: base64" + CRLF + CRLF; SendBufferstr+= Base64Encode(mailMessage.Body) + CRLF + CRLF; SendBufferstr += "--=====003_Dragon520636771063_=====--"+CRLF; } else { if(mailMessage.Attachments.Count!=0) { SendBufferstr += "--=====001_Dragon303406132050_====="+CRLF; } SendBufferstr+="Content-Type: text/plain;" + CRLF; SendBufferstr+=((mailMessage.Charset=="")?(" charset=\"iso-8859-1\""):(" charset=\"" + mailMessage.Charset.ToLower() + "\"")) + CRLF; SendBufferstr+="Content-Transfer-Encoding: base64" + CRLF + CRLF; SendBufferstr+= Base64Encode(mailMessage.Body) + CRLF; } //SendBufferstr += "Content-Transfer-Encoding: base64"+CRLF; if(mailMessage.Attachments.Count!=0) { for(int i=0;i<mailMessage.Attachments.Count;i++) { string filepath = (string)mailMessage.Attachments[i]; SendBufferstr += "--====="+ (Html?"001_Dragon520636771063_":"001_Dragon303406132050_") +"====="+CRLF; //SendBufferstr += "Content-Type: application/octet-stream"+CRLF; SendBufferstr += "Content-Type: text/plain;"+CRLF; SendBufferstr += " name=\"=?"+mailMessage.Charset.ToUpper()+"?B?"+ Base64Encode(filepath.Substring(filepath.LastIndexOf("\\")+1))+"?=\""+CRLF; SendBufferstr += "Content-Transfer-Encoding: base64"+CRLF; SendBufferstr += "Content-Disposition: attachment;"+CRLF; SendBufferstr += " filename=\"=?"+mailMessage.Charset.ToUpper()+"?B?"+ Base64Encode(filepath.Substring(filepath.LastIndexOf("\\")+1))+"?=\""+CRLF+CRLF; SendBufferstr += GetStream(filepath)+CRLF+CRLF; } SendBufferstr += "--====="+ (Html?"001_Dragon520636771063_":"001_Dragon303406132050_")+"=====--"+CRLF+CRLF; } SendBufferstr += CRLF + "." + CRLF;//内容结束 if(!Dialog(SendBufferstr,"错误信件信息")) return false; SendBufferstr="QUIT" + CRLF; if(!Dialog(SendBufferstr,"断开连接时错误")) return false; networkStream.Close(); tcpClient.Close(); return true; } } public class SmtpMail { private static string _SmtpServer; /// <summary> /// 格式:SmtpAccount:Password@SmtpServerAddress<br> /// 或者:SmtpServerAddress<br> /// <code> /// SmtpMail.SmtpServer="user:12345678@smtp.126.com"; /// //或者: /// SmtpMail.SmtpServer="smtp.126.com"; /// 或者: /// SmtpMail.SmtpServer=SmtpServerHelper.GetSmtpServer("user","12345678","smtp.126.com"); /// </code> /// </summary> public static string SmtpServer { set { _SmtpServer=value;} get { return _SmtpServer;} } public static bool Send(MailMessage mailMessage,string username,string password) { SmtpServerHelper helper=new SmtpServerHelper(); return helper.SendEmail(_SmtpServer,25,username,password,mailMessage); } } #endregion } using System; using NUnit.Framework; namespace SkyDev.Web.Mail { /// <summary> /// Test 的摘要说明。 /// </summary> [TestFixture] public class TestSmtpMail { //安装测试用例,完成初始化操作 [SetUp] public void SetUp() { } //测试结束完成清理操作 [TearDown] public void TearDown() { } [Test] public void TestMailAttachments() { SkyDev.Web.Mail.MailAttachments attachments=new MailAttachments(); Assert.AreEqual(0,attachments.Count,"初始化MailAttachments"); attachments.Add("c:\\autoexec.bat"); Assert.AreEqual(1,attachments.Count,"增加附件(附件确实存在)"); attachments.Add("c:\\autoexec.dat.txt"); Assert.AreEqual(1,attachments.Count,"增加附件(附件不存在)"); attachments.Clear(); Assert.AreEqual(0,attachments.Count,"清除附件"); } [Test] public void TestMailMessage() { MailMessage message=new MailMessage(); Assert.AreEqual(0,message.Attachments.Count,"初始化MailAttachments"); Assert.AreEqual(MailFormat.Text,message.BodyFormat,"邮件格式"); Assert.AreEqual("GB2312",message.Charset,"缺省的字符集"); } [Test] public void TestSendMail() { SmtpMail.SmtpServer="smtp.126.com"; MailMessage mail=new MailMessage(); mail.From="qs1976@126.com"; mail.FromName="曾青松"; mail.AddRecipients("qs1976@126.com"); mail.Subject="主题:测试邮件"; mail.BodyFormat=MailFormat.Text; mail.Body="测试的内容."; mail.Attachments.Add("c:\\test.txt"); SmtpMail.Send(mail,"","");//请填写自己的测试邮件帐号 } } }
C# System.Net.Mail发送邮件
using System; using System.Collections; using System.Configuration; using System.Data; using System.Net; using System.Net.Mail; public partial class FindMM: System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { SendMail(); } } public bool SendMail() { MailMessage myMail = new MailMessage(); myMail.From = new MailAddress("uewang.com@gmail.com");//发件人邮箱 myMail.To.Add(new MailAddress("354990393@qq.com"));//收件人邮箱 myMail.Subject = "Test";//主题 myMail.SubjectEncoding = System.Text.Encoding.UTF8;//主题编码 myMail.Body = "You are successed.";//主题内容 myMail.BodyEncoding = System.Text.Encoding.UTF8;//n内容编码 myMail.IsBodyHtml = false;//内容是哪种格式(txt/html) myMail.Priority = MailPriority.High; myMail.CC.Add(new MailAddress("354990393@qq.com")); //抄送 myMail.Bcc.Add(new MailAddress("354990393@qq.com")); //密抄送 //smtp client SmtpClient sender = new SmtpClient(); sender.Host = "smtp.gmail.com";//简单邮件传输协议 sender.Port = 587;//端口 sender.Credentials = new NetworkCredential("用户名", "密码"); sender.DeliveryMethod = SmtpDeliveryMethod.Network;//指定如何处理待发的电子邮件 \\传递方法包括: \\SMTP 服务器。 \\将电子邮件移到 IIS 的拾取目录中,IIS 然后将传递邮件。 \\将电子邮件移到 PickupDirectoryLocation 指定的目录中,以便稍后由其他应用程序传递。 sender.EnableSsl = true; try { sender.Send(myMail); return true; } catch (Exception e) { LblMsg.Text = e.Message.ToString(); return false; } } } 在这种实现中要注意这样几个问题: 1 System.Net.Mail是.NET 2.0以后的版本中被推荐使用的方法,它解决了一些编码问题和一些安全验证的问题,并且对MailMessage类重写,提供了更多的函数,使得建立MailMessage更加便利。 2 System.Net.Mail.MailMessage中,加入SubjectEncoding属性,而且对于To, Cc, Bcc都加入了一些域下的方法,使得可以更便利的实现邮件群发。而且使用了更加面向对象的MailAddress类的对象来表明邮件地址。 3 System.Net.Mail中加入SmtpClient类,该类包含了诸如本应用中的一些方法和属性,可以对链接进行安全链接的标记等等 4 值得注意的是,一般来讲SMTP(Simple Message Transfer Protocol)使用的端口是25,这也是多数邮件服务期提供的端口,但是gmail却不一样,gmail的最新端口是587,而不是先前的465。 5 Gmail的服务器是要求安全链接的,所以一定要指定Sender.EnableSsl = true。 6 此外SmtpClient对象中有一个非常重要的方法,要介绍一下,就是SendAsync(), 这个方法已经被重载过了,public void SendAsync(MailMessage message, object userToken)要求使用MailMessage作为发送对象,并且勇userToken指定异步操作时调用的方法。public void SendAsync(string from, string recipients, string subject, string body, object userToken) 可以不用建立MailMessage对象直接发送邮件,userToken与上一个函数相同,public void SendAsyncCancel()用来取消异步操作以发送邮件。
SMTP服务器地址
邮件自动群发通内部已经内置了很多常用的SMTP地址,会根据你录入的账户邮件地址自动选择,如果没有将为你推荐一个。 一般的SMTP服务器地址是在邮箱地址前增加smtp,比如 email@126.com 的SMTP地址是 smtp.126.com。也有例外的,如果你用的是网站自带的邮箱,SMTP地址需要咨询一下你的网站提供商,一般常用的有下面几种,比如你的网站域名是www.yourdomain.com,那么SMTP服务器可能是下面之一 smtp.yourdomain.com mail.yourdomain.com smtp.mail.yourdomain.com 下面是一些常用邮箱的POP3 / SMTP地址。 特别提示:有些SMTP配置可能已经有所变化,具体请查询邮件服务器提供商 网易163邮箱 POP3:pop.163.com SMTP:smtp.163.com 网易vip.163邮箱 POP3:pop.vip.163.com SMTP:smtp.vip.163.com 网易126邮箱 POP3:pop.126.com SMTP:smtp.126.com 网易188邮箱 POP3:pop.188.com SMTP:smtp.188.com 网易yeah.net邮箱 POP3:pop.yeah.net SMTP:smtp.yeah.net 网易netease.com邮箱 POP3:pop.netease.com SMTP:smtp.netease.com 新浪免费邮箱 POP3:pop.sina.com SMTP:smtp.sina.com 新浪收费邮箱 POP3:pop3.vip.sina.com SMTP:smtp.vip.sina.com 新浪企业邮箱 POP3:pop.sina.com SMTP:smtp.sina.com 雅虎邮箱 POP3:pop.mail.yahoo.cn SMTP:smtp.mail.yahoo.cn 搜狐邮箱 POP3:pop3.sohu.com SMTP:smtp.sohu.com TOM邮箱 POP3:pop.tom.com SMTP:smtp.tom.com Gmail邮箱 POP3:pop.gmail.com SMTP:smtp.gmail.com QQ邮箱 POP3:pop.qq.com SMTP:smtp.qq.com 263邮箱 域名:263.net POP3:263.net SMTP:smtp.263.net 域名:x263.net POP3:pop.x263.net SMTP:smtp.x263.net 域名:263.net.cn POP3:263.net.cn SMTP:263.net.cn 域名:炫我型 POP3:pop.263xmail.com SMTP:smtp.263xmail.com 21CN 免费邮箱 POP3:pop.21cn.com SMTP:smtp.21cn.com IMAP:imap.21cn.com 21CN 经济邮邮箱 POP3:pop.21cn.com SMTP:smtp.21cn.com 21CN 商务邮邮箱 POP3:pop.21cn.net SMTP:smtp.21cn.net 21CN 快感邮箱 POP3:vip.21cn.com SMTP:vip.21cn.com 21CN Y邮箱 POP3:pop.y.vip.21cn.com SMTP:smtp.y.vip.21cn.com 中华网任我邮邮箱 POP3:rwpop.china.com SMTP:rwsmtp.china.com 中华网时尚、商务邮箱 POP3:pop.china.com SMTP:smtp.china.com
c# 邮件群发
/ 引入命名空间 using System.Net; using System.Net.Mail; SmtpClient smtp =new SmtpClient(); //实例化一个SmtpClientsmtp.DeliveryMethod = SmtpDeliveryMethod.Network; //将smtp的出站方式设为 Networksmtp.EnableSsl = false; //smtp服务器是否启用SSL加密smtp.Host = "smtp.163.com"; //指定 smtp 服务器地址smtp.Port = 25; //指定 smtp 服务器的端口,默认是25,如果采用默认端口,可省去 //如果你的SMTP服务器不需要身份认证,则使用下面的方式,不过,目前基本没有不需要认证的了smtp.UseDefaultCredentials = true; //如果需要认证,则用下面的方式 smtp.Credentials =new NetworkCredential("邮箱帐号@163.com", "邮箱密码"); MailMessage mm =new MailMessage(); //实例化一个邮件类mm.Priority = MailPriority.High; //邮件的优先级,分为 Low, Normal, High,通常用 Normal即可mm.From =new MailAddress("邮箱帐号@163.com", "真有意思", Encoding.GetEncoding(936));//收件方看到的邮件来源;//第一个参数是发信人邮件地址//第二参数是发信人显示的名称//第三个参数是 第二个参数所使用的编码,如果指定不正确,则对方收到后显示乱码//936是简体中文的codepage值注:上面的邮件来源,一定要和你登录邮箱的帐号一致,否则会认证失败mm.ReplyTo = new MailAddress("test_box@gmail.com", "我的接收邮箱", Encoding.GetEncoding(936)); //ReplyTo 表示对方回复邮件时默认的接收地址,即:你用一个邮箱发信,但却用另一个来收信//上面后两个参数的意义, 同 From 的意义mm.CC.Add("a@163.com,b@163.com,c@163.com"); //邮件的抄送者,支持群发,多个邮件地址之间用 半角逗号 分开 //当然也可以用全地址,如下:mm.CC.Add(new MailAddress("a@163.com", "抄送者A",Encoding.GetEncoding(936))); mm.CC.Add(new MailAddress("b@163.com", "抄送者B", Encoding.GetEncoding(936))); mm.CC.Add(new MailAddress("c@163.com", "抄送者C", Encoding.GetEncoding(936))); mm.Bcc.Add("d@163.com,e@163.com");//邮件的密送者,支持群发,多个邮件地址之间用 半角逗号 分开//当然也可以用全地址,如下:mm.CC.Add(new MailAddress("d@163.com", "密送者D", Encoding.GetEncoding(936)));mm.CC.Add(new MailAddress("e@163.com", "密送者E", Encoding.GetEncoding(936)));mm.Sender = new MailAddress("xxx@xxx.com", "邮件发送者", Encoding.GetEncoding(936)); //可以任意设置,此信息包含在邮件头中,但并不会验证有效性,也不会显示给收件人//说实话,我不知道有啥实际作用,大家可不理会,也可不写此项检举 mm.To.Add("g@163.com,h@163.com");//邮件的接收者,支持群发,多个地址之间用 半角逗号 分开//当然也可以用全地址添加mm.To.Add(new MailAddress("g@163.com", "接收者g", Encoding.GetEncoding(936))); mm.To.Add(new MailAddress("h@163.com", "接收者h", Encoding.GetEncoding(936))); mm.Subject ="这是邮件标题"; //邮件标题mm.SubjectEncoding = Encoding.GetEncoding(936); // 这里非常重要,如果你的邮件标题包含中文,这里一定要指定,否则对方收到的极有可能是乱码。 // 936是简体中文的pagecode,如果是英文标题,这句可以忽略不用mm.IsBodyHtml = true; //邮件正文是否是HTML格式mm.BodyEncoding = Encoding.GetEncoding(936);//邮件正文的编码, 设置不正确, 接收者会收到乱码mm.Body ="<font color="red">邮件测试,呵呵</font>"; //邮件正文mm.Attachments.Add( new Attachment( @"d:a.doc", System.Net.Mime.MediaTypeNames.Application.Rtf ) ); //添加附件,第二个参数,表示附件的文件类型,可以不用指定 //可以添加多个附件mm.Attachments.Add( new Attachment( @"d:b.doc") );smtp.Send( mm ); //发送邮件,如果不返回异常, 则大功告成了。
c#接收邮件类
using System; using System.Net.Sockets; using System.Net; using System.Security.Cryptography; using System.IO; // 类名:Pop3 // 功能:接收电子邮件 namespace ZTSX.Email { /// <summary> /// Pop3 的摘要说明。 /// </summary> public class Pop3 { private string mstrHost = null; //主机名称或IP地址 private int mintPort = 110; //主机的端口号(默认为110) private TcpClient mtcpClient = null; //客户端 private NetworkStream mnetStream = null; //网络基础数据流 private StreamReader m_stmReader = null; //读取字节流 private string mstrStatMessage = null; //执行STAT命令后得到的消息(从中得到邮件数) /// <summary> /// 构造函数 /// </summary> /// <remarks>一个邮件接收对象</remarks> public Pop3() { } /// <summary> /// 构造函数 /// </summary> /// <param name="host">主机名称或IP地址</param> public Pop3(string host) { mstrHost = host; } /// <summary> /// 构造函数 /// </summary> /// <param name="host">主机名称或IP地址</param> /// <param name="port">主机的端口号</param> /// <remarks>一个邮件接收对象</remarks> public Pop3(string host,int port) { mstrHost = host; mintPort = port; } #region 属性 /// <summary> /// 主机名称或IP地址 /// </summary> /// <remarks>主机名称或IP地址</remarks> public string HostName { get{return mstrHost;} set{mstrHost = value;} } /// <summary> /// 主机的端口号 /// </summary> /// <remarks>主机的端口号</remarks> public int Port { get{return mintPort;} set{mintPort = value;} } #endregion #region 私有方法 /// <summary> /// 向网络访问的基础数据流中写数据(发送命令码) /// </summary> /// <param name="netStream">可以用于网络访问的基础数据流</param> /// <param name="command">命令行</param> /// <remarks>向网络访问的基础数据流中写数据(发送命令码)</remarks> private void WriteToNetStream(ref NetworkStream netStream,String command) { string strToSend = command + "\r\n"; byte[] arrayToSend = System.Text.Encoding.ASCII.GetBytes(strToSend.ToCharArray()); netStream.Write(arrayToSend,0,arrayToSend.Length); } /// <summary> /// 检查命令行结果是否正确 /// </summary> /// <param name="message">命令行的执行结果</param> /// <param name="check">正确标志</param> /// <returns> /// 类型:布尔 /// 内容:true表示没有错误,false为有错误 /// </returns> /// <remarks>检查命令行结果是否有错误</remarks> private bool CheckCorrect(string message,string check) { if(message.IndexOf(check) == -1) return false; else return true; } /// <summary> /// 邮箱中的未读邮件数 /// </summary> /// <param name="message">执行完LIST命令后的结果</param> /// <returns> /// 类型:整型 /// 内容:邮箱中的未读邮件数 /// </returns> /// <remarks>邮箱中的未读邮件数</remarks> private int GetMailNumber(string message) { string[] strMessage = message.Split(‘ ‘); return Int32.Parse(strMessage[1]); } /// <summary> /// 得到经过解码后的邮件的内容 /// </summary> /// <param name="encodingContent">解码前的邮件的内容</param> /// <returns> /// 类型:字符串 /// 内容:解码后的邮件的内容 /// </returns> /// <remarks>得到解码后的邮件的内容</remarks> private string GetDecodeMailContent(string encodingContent) { string strContent = encodingContent.Trim(); string strEncode = null; int iStart = strContent.IndexOf("Base64"); if(iStart == -1) throw new Pop3Exception("邮件内容不是Base64编码,请检查"); else { strEncode = strContent.Substring(iStart + 6,strContent.Length - iStart - 6); try { return SX.Encode.TransformToString(strEncode); } catch(SX.EncodeException exc) { throw new Pop3Exception(exc.Message); } } } #endregion /// <summary> /// 与主机建立连接 /// </summary> /// <returns> /// 类型:布尔 /// 内容:连接结果(true为连接成功,false为连接失败) /// </returns> /// <remarks>与主机建立连接</remarks> public bool Connect() { if(mstrHost == null) throw new Exception("请提供SMTP主机名称或IP地址!"); if(mintPort == 0) throw new Exception("请提供SMTP主机的端口号"); try { mtcpClient = new TcpClient(mstrHost,mintPort); mnetStream = mtcpClient.GetStream(); m_stmReader = new StreamReader(mtcpClient.GetStream()); string strMessage = m_stmReader.ReadLine(); if(CheckCorrect(strMessage,"+OK") == true) return true; else return false; } catch(SocketException exc) { throw new Pop3Exception(exc.ToString()); } catch(NullReferenceException exc) { throw new Pop3Exception(exc.ToString()); } } #region Pop3命令 /// <summary> /// 执行Pop3命令,并检查执行的结果 /// </summary> /// <param name="command">Pop3命令行</param> /// <returns> /// 类型:字符串 /// 内容:Pop3命令的执行结果 /// </returns> private string ExecuteCommand(string command) { string strMessage = null; //执行Pop3命令后返回的消息 try { //发送命令 WriteToNetStream(ref mnetStream,command); //读取多行 if(command.Substring(0,4).Equals("LIST") || command.Substring(0,4).Equals("RETR") || command.Substring(0,4).Equals("UIDL")) //记录STAT后的消息(其中包含邮件数) { strMessage = ReadMultiLine(); if(command.Equals("LIST")) //记录LIST后的消息(其中包含邮件数) mstrStatMessage = strMessage; } //读取单行 else strMessage = m_stmReader.ReadLine(); //判断执行结果是否正确 if(CheckCorrect(strMessage,"+OK")) return strMessage; else return "Error"; } catch(IOException exc) { throw new Pop3Exception(exc.ToString()); } } /// <summary> /// 在Pop3命令中,LIST、RETR和UIDL命令的结果要返回多行,以点号(.)结尾, /// 所以如果想得到正确的结果,必须读取多行 /// </summary> /// <returns> /// 类型:字符串 /// 内容:执行Pop3命令后的结果 /// </returns> private string ReadMultiLine() { string strMessage = m_stmReader.ReadLine(); string strTemp = null; while(strMessage != ".") { strTemp = strTemp + strMessage; strMessage = m_stmReader.ReadLine(); } return strTemp; } //USER命令 private string USER(string user) { return ExecuteCommand("USER " + user) + "\r\n"; } //PASS命令 private string PASS(string password) { return ExecuteCommand("PASS " + password) + "\r\n"; } //LIST命令 private string LIST() { return ExecuteCommand("LIST") + "\r\n"; } //UIDL命令 private string UIDL() { return ExecuteCommand("UIDL") + "\r\n"; } //NOOP命令 private string NOOP() { return ExecuteCommand("NOOP") + "\r\n"; } //STAT命令 private string STAT() { return ExecuteCommand("STAT") + "\r\n"; } //RETR命令 private string RETR(int number) { return ExecuteCommand("RETR " + number.ToString()) + "\r\n"; } //DELE命令 private string DELE(int number) { return ExecuteCommand("DELE " + number.ToString()) + "\r\n"; } //QUIT命令 private void Quit() { WriteToNetStream(ref mnetStream,"QUIT"); } /// <summary> /// 收取邮件 /// </summary> /// <param name="user">用户名</param> /// <param name="password">口令</param> /// <returns> /// 类型:字符串数组 /// 内容:解码前的邮件内容 /// </returns> private string[] ReceiveMail(string user,string password) { int iMailNumber = 0; //邮件数 if(USER(user).Equals("Error")) throw new Pop3Exception("用户名不正确!"); if(PASS(password).Equals("Error")) throw new Pop3Exception("用户口令不正确!"); if(STAT().Equals("Error")) throw new Pop3Exception("准备接收邮件时发生错误!"); if(LIST().Equals("Error")) throw new Pop3Exception("得到邮件列表时发生错误!"); try { iMailNumber = GetMailNumber(mstrStatMessage); //没有新邮件 if(iMailNumber == 0) return null; else { string[] strMailContent = new string[iMailNumber]; for(int i = 1 ; i <= iMailNumber ; i++) { //读取邮件内容 strMailContent[i - 1] = GetDecodeMailContent(RETR(i)); } return strMailContent; } } catch(Pop3Exception exc) { throw new Pop3Exception(exc.ToString()); } } #endregion /// <summary> /// 收取邮件 /// </summary> /// <param name="user">用户名</param> /// <param name="password">口令</param> /// <returns> /// 类型:字符串数组 /// 内容:解码前的邮件内容 /// </returns> ///<remarks>收取邮箱中的未读邮件</remarks> public string[] Receive(string user,string password) { try { return ReceiveMail(user,password); } catch(Pop3Exception exc) { throw new Pop3Exception(exc.ToString()); } } /// <summary> /// 断开所有与服务器的会话 /// </summary> /// <remarks>断开所有与服务器的会话</remarks> public void DisConnect() { try { Quit(); if(m_stmReader != null) m_stmReader.Close(); if(mnetStream != null) mnetStream.Close(); if(mtcpClient != null) mtcpClient.Close(); } catch(SocketException exc) { throw new Pop3Exception(exc.ToString()); } } /// <summary> /// 删除邮件 /// </summary> /// <param name="number">邮件号</param> public void DeleteMail(int number) { //删除邮件 int iMailNumber = number + 1; if(DELE(iMailNumber).Equals("Error")) throw new Pop3Exception("删除第" + iMailNumber.ToString() + "时出现错误!"); } } }
c#实现smtp服务器,使用tcp命令实现,功能比较完善
using System; using System.Text; using System.IO; using System.Net; using System.Net.Sockets; using System.Collections; namespace SkyDev.Web.Mail { public enum MailFormat{Text,HTML}; public enum MailPriority{Low=1,Normal=3,High=5}; #region Class mailAttachments public class MailAttachments { private const int MaxAttachmentNum=10; private IList _Attachments; public MailAttachments() { _Attachments=new ArrayList(); } public string this[int index] { get { return (string)_Attachments[index];} } /// <summary> /// 添加邮件附件 /// </summary> /// <param name="FilePath">附件的绝对路径</param> public void Add(params string[] filePath) { if(filePath==null) { throw(new ArgumentNullException("非法的附件")); } else { for(int i=0;i<filePath.Length;i ) { Add(filePath[i]); } } } /// <summary> /// 添加一个附件,当指定的附件不存在时,忽略该附件,不产生异常。 /// </summary> /// <param name="filePath">附件的绝对路径</param> public void Add(string filePath) { //当附件存在时才加入,否则忽略 if (System.IO.File.Exists(filePath)) { if (_Attachments.Count<MaxAttachmentNum) { _Attachments.Add(filePath); } } } public void Clear()//清除任何附件 { _Attachments.Clear(); } public int Count//获取附件个数 { get { return _Attachments.Count;} } } #endregion//end Class mailAttachments #region Class MailMessage /// <summary> /// MailMessage 表示SMTP要发送的一封邮件的消息。 /// </summary> public class MailMessage { private const int MaxRecipientNum=10; public MailMessage() { _Recipients=new ArrayList();//收件人列表 _Attachments=new MailAttachments();//附件 _BodyFormat=MailFormat.Text;//缺省的邮件格式为Text _Priority=MailPriority.Normal; _Charset="GB2312"; } /// <summary> /// 设定语言代码,默认设定为GB2312,如无需可配置为"" /// </summary> public string Charset { get { return _Charset;} set { _Charset=value;} } public string From { get{ return _From;} set { _From=value;} } public string FromName { get { return _FromName;} set { _FromName=value;} } public string Body { get { return _Body;} set { _Body=value;} } public string Subject { get { return _Subject;} set { _Subject=value;} } public MailAttachments Attachments { get {return _Attachments;} set { _Attachments=value;} } public MailPriority Priority { get { return _Priority;} set { _Priority=value;} } public IList Recipients { get { return _Recipients;} } /// <summary> /// 增加一个收件人地址 /// </summary> /// <param name="recipient">收件人的Email地址</param> public void AddRecipients(string recipient) { //先检查邮件地址是否符合规范 if (_Recipients.Count<MaxRecipientNum) { _Recipients.Add(recipient);//增加到收件人列表 } } public void AddRecipients(params string[] recipient) { if (recipient==null) { throw (new ArgumentException("收件人不能为空.")); } else { for (int i=0;i<recipient.Length;i ) { AddRecipients(recipient[i]); } } } public MailFormat BodyFormat { set { _BodyFormat=value;} get { return _BodyFormat;} } private string _From;//发件人地址 private string _FromName;//发件人姓名 private IList _Recipients;//收件人 private MailAttachments _Attachments;//附件 private string _Body;//内容 private string _Subject;//主题 private MailFormat _BodyFormat;//邮件格式 private string _Charset="GB2312";//字符编码格式 private MailPriority _Priority;//邮件优先级 } #endregion #region Class SmtpMail public class SmtpServerHelper { private string CRLF="\r\n";//回车换行 /// <summary> /// 错误消息反馈 /// </summary> private string errmsg; /// <summary> /// TcpClient对象,用于连接服务器 /// </summary> private TcpClient tcpClient; /// <summary> /// NetworkStream对象 /// </summary> private NetworkStream networkStream; /// <summary> /// 服务器交互记录 /// </summary> private string logs=""; /// <summary> /// SMTP错误代码哈希表 /// </summary> private Hashtable ErrCodeHT = new Hashtable(); /// <summary> /// SMTP正确代码哈希表 特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。 本站文章均来自网络,如有侵权,请联系028-86262244-200 QQ: 1585463984 我们将立即删除! // </summary> private Hashtable RightCodeHT = new Hashtable();public SmtpServerHelper() { SMTPCodeAdd();//初始化SMTPCode } ~SmtpServerHelper() { networkStream.Close(); tcpClient.Close(); } /// <summary> /// 将字符串编码为Base64字符串 /// </summary> /// <param name="str">要编码的字符串</param> private string Base64Encode(string str) { byte[] barray; barray=Encoding.Default.GetBytes(str); return Convert.ToBase64String(barray); } /// <summary> /// 将Base64字符串解码为普通字符串 /// </summary> /// <param name="str">要解码的字符串</param> private string Base64Decode(string str) { byte[] barray; barray=Convert.FromBase64String(str); return Encoding.Default.GetString(barray); } /// <summary> /// 得到上传附件的文档流 /// </summary> /// <param name="FilePath">附件的绝对路径</param> private string GetStream(string FilePath) { //建立文档流对象 System.IO.FileStream FileStr=new System.IO.FileStream(FilePath,System.IO.FileMode.Open); byte[] by=new byte[System.Convert.ToInt32(FileStr.Length)]; FileStr.Read(by,0,by.Length); FileStr.Close(); return(System.Convert.ToBase64String(by)); } /// <summary> /// SMTP回应代码哈希表 /// </summary> private void SMTPCodeAdd() { //[RFC 821 4.2.1.] /* 4.2.2. NUMERIC ORDER LIST OF REPLY CODES 211 System status, or system help reply 214 Help message [Information on how to use the receiver or the meaning of a particular non-standard command; this reply is useful only to the human user] 220 <domain> Service ready 221 <domain> Service closing transmission channel 250 Requested mail action okay, completed 251 User not local; will forward to <forward-path> 354 Start mail input; end with <CRLF>.<CRLF> 421 <domain> Service not available, closing transmission channel [This may be a reply to any command if the service knows it must shut down] 450 Requested mail action not taken: mailbox unavailable [E.g., mailbox busy] 451 Requested action aborted: local error in processing 452 Requested action not taken: insufficient system storage 500 Syntax error, command unrecognized [This may include errors such as command line too long] 501 Syntax error in parameters or arguments 502 Command not implemented 503 Bad sequence of commands 504 Command parameter not implemented 550 Requested action not taken: mailbox unavailable [E.g., mailbox not found, no access] 551 User not local; please try <forward-path> 552 Requested mail action aborted: exceeded storage allocation 553 Requested action not taken: mailbox name not allowed [E.g., mailbox syntax incorrect] 554 Transaction failed */ ErrCodeHT.Add("421","服务未就绪,关闭传输信道"); ErrCodeHT.Add("432","需要一个密码转换"); ErrCodeHT.Add("450","需要的邮件操作未完成,邮箱不可用(例如,邮箱忙)"); ErrCodeHT.Add("451","放弃需要的操作;处理过程中出错"); ErrCodeHT.Add("452","系统存储不足,需要的操作未执行"); ErrCodeHT.Add("454","临时认证失败"); ErrCodeHT.Add("500","邮箱地址错误"); ErrCodeHT.Add("501","参数格式错误"); ErrCodeHT.Add("502","命令不可实现"); ErrCodeHT.Add("503","服务器需要SMTP验证"); ErrCodeHT.Add("504","命令参数不可实现"); ErrCodeHT.Add("530","需要认证"); ErrCodeHT.Add("534","认证机制过于简单"); ErrCodeHT.Add("538","当前请求的认证机制需要加密"); ErrCodeHT.Add("550","需要的邮件操作未完成,邮箱不可用(例如,邮箱未找到,或不可访问)"); ErrCodeHT.Add("551","用户非本地,请尝试<forward-path>"); ErrCodeHT.Add("552","过量的存储分配,需要的操作未执行"); ErrCodeHT.Add("553","邮箱名不可用,需要的操作未执行(例如邮箱格式错误)"); ErrCodeHT.Add("554","传输失败"); /* 211 System status, or system help reply 214 Help message [Information on how to use the receiver or the meaning of a particular non-standard command; this reply is useful only to the human user] 220 <domain> Service ready 221 <domain> Service closing transmission channel 250 Requested mail action okay, completed 251 User not local; will forward to <forward-path> 354 Start mail input; end with <CRLF>.<CRLF> */ RightCodeHT.Add("220","服务就绪"); RightCodeHT.Add("221","服务关闭传输信道"); RightCodeHT.Add("235","验证成功"); RightCodeHT.Add("250","需要的邮件操作完成"); RightCodeHT.Add("251","非本地用户,将转发向<forward-path>"); 特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。 本站文章均来自网络,如有侵权,请联系028-86262244-200 QQ: 1585463984 我们将立即删除! RightCodeHT.Add("334","服务器响应验证Base64字符串"); RightCodeHT.Add("354","开始邮件输入,以<CRLF>.<CRLF>结束");} /// <summary> /// 发送SMTP命令 /// </summary> private bool SendCommand(string str) { byte[]WriteBuffer; if(str==null||str.Trim()==String.Empty) { return true; } logs =str; WriteBuffer = Encoding.Default.GetBytes(str); try { networkStream.Write(WriteBuffer,0,WriteBuffer.Length); } catch { errmsg="网络连接错误"; return false; } return true; } /// <summary> /// 接收SMTP服务器回应 /// </summary> private string RecvResponse() { int StreamSize; string Returnvalue = String.Empty; byte[] ReadBuffer = new byte[1024] ; try { StreamSize=networkStream.Read(ReadBuffer,0,ReadBuffer.Length); } catch { errmsg="网络连接错误"; return "false"; } if (StreamSize==0) { return Returnvalue ; } else { Returnvalue = Encoding.Default.GetString(ReadBuffer).Substring(0,StreamSize); logs =Returnvalue this.CRLF; return Returnvalue; } } /// <summary> /// 和服务器交互,发送一条命令并接收回应。 /// </summary> /// <param name="str">一个要发送的命令</param> /// <param name="errstr">假如错误,要反馈的信息</param> private bool Dialog(string str,string errstr) { if(str==null||str.Trim()==string.Empty) { return true; } if(SendCommand(str)) { string RR=RecvResponse(); if(RR=="false") { return false; } //检查返回的代码,根据[RFC 821]返回代码为3位数字代码如220 string RRCode=RR.Substring(0,3); if(RightCodeHT[RRCode]!=null) { return true; } else { if(ErrCodeHT[RRCode]!=null) { errmsg =(RRCode ErrCodeHT[RRCode].ToString()); errmsg =CRLF; } else { errmsg =RR; } errmsg =errstr; return false; } } else { return false; } } /// <summary> /// 和服务器交互,发送一组命令并接收回应。 /// </summary> private bool Dialog(string[] str,string errstr) { for(int i=0;i<str.Length;i ) { if(!Dialog(str[i],"")) { errmsg =CRLF; errmsg =errstr; return false; } } return true; } //连接服务器 private bool Connect(string smtpServer,int port) { //创建Tcp连接 try { tcpClient=new TcpClient(smtpServer,port); } catch(Exception e) { errmsg=e.ToString(); return false; } networkStream=tcpClient.GetStream(); //验证网络连接是否正确 if(RightCodeHT[RecvResponse().Substring(0,3)]==null) { errmsg="网络连接失败"; return false; } return true; } private string GetPriorityString(MailPriority mailPriority) { string priority="Normal"; if (mailPriority==MailPriority.Low) { priority="Low"; } else if (mailPriority==MailPriority.High) { priority="High"; } return priority; } /// <summary> /// 发送电子邮件,SMTP服务器无需身份验证 /// </summary> /// <param name="smtpServer"></param> /// <param name="port"></param> /// <param name="mailMessage"></param> /// <returns></returns> public bool SendEmail(string smtpServer,int port,MailMessage mailMessage) { return SendEmail(smtpServer,port,false,"","",mailMessage); } /// <summary> /// 发送电子邮件,SMTP服务器需要身份验证 /// </summary> /// <param name="smtpServer"></param> /// <param name="port"></param> /// <param name="username"></param> /// <param name="password"></param> /// <param name="mailMessage"></param> /// <returns></returns> public bool SendEmail(string smtpServer,int port,string username,string password,MailMessage mailMessage) { return SendEmail(smtpServer,port,false,username,password,mailMessage); } private bool SendEmail(string smtpServer,int port,bool ESmtp,string username,string password,MailMessage mailMessage) { if (Connect(smtpServer,port)==false)//测试连接服务器是否成功 return false; string priority=GetPriorityString(mailMessage.Priority); bool Html=(mailMessage.BodyFormat==MailFormat.HTML); string[] SendBuffer; string SendBufferstr; //进行SMTP验证,现在大部分SMTP服务器都要认证 if(ESmtp) { SendBuffer=new String[4]; 特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。 本站文章均来自网络,如有侵权,请联系028-86262244-200 QQ: 1585463984 我们将立即删除! SendBuffer[0]="EHLO " smtpServer CRLF; SendBuffer[1]="AUTH LOGIN" CRLF; SendBuffer[2]=Base64Encode(username) CRLF; SendBuffer[3]=Base64Encode(password) CRLF; if(!Dialog(SendBuffer,"SMTP服务器验证失败,请核对用户名和密码。")) return false; } else {//无需身份认证 SendBufferstr="HELO " smtpServer CRLF; if(!Dialog(SendBufferstr,"")) return false; }//发件人地址 SendBufferstr="MAIL FROM:<" mailMessage.From ">" CRLF; if(!Dialog(SendBufferstr,"发件人地址错误,或不能为空")) return false; //收件人地址 SendBuffer=new string[mailMessage.Recipients.Count]; for(int i=0;i<mailMessage.Recipients.Count;i ) { SendBuffer[i]="RCPT TO:<" (string)mailMessage.Recipients[i] ">" CRLF; } if(!Dialog(SendBuffer,"收件人地址有误")) return false; /* SendBuffer=new string[10]; for(int i=0;i<RecipientBCC.Count;i ) { SendBuffer[i]="RCPT TO:<" RecipientBCC[i].ToString() ">" CRLF; } if(!Dialog(SendBuffer,"密件收件人地址有误")) return false; */ SendBufferstr="DATA" CRLF; if(!Dialog(SendBufferstr,"")) return false; //发件人姓名 SendBufferstr="From:" mailMessage.FromName "<" mailMessage.From ">" CRLF; //if(ReplyTo.Trim()!="") //{ // SendBufferstr ="Reply-To: " ReplyTo CRLF; / 特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。 本站文章均来自网络,如有侵权,请联系028-86262244-200 QQ: 1585463984 我们将立即删除!
c#写的邮件群发程序
c#写的邮件群发程序 实现思路: 将要发送的邮件写入到sql Server中的表(固定的表结构),由此程序周期性地从表中读取要待发邮件并进行发送。 发送邮件的方法在单独的线程中运行。 可配置多个smtp进行发送。 其中涉及的主要技术有:c#中对xml进行操作、数据集设计器的使用;c#中线程的创建、启动及终止;配置文件的使用;.net中邮件发送工具的使用.... 此程序仅用作学习交流。 下载地址:邮件群发程序 使用方法: 1、创建一个sqlserver数据表 ,必须命名为:maillist,表结构如下: CREATE TABLE [dbo].[MAILLIST]( [编号] [char](20) COLLATE Chinese_PRC_CI_AS NULL, [用户类型] [char](6) COLLATE Chinese_PRC_CI_AS NULL, [用户编号] [char](20) COLLATE Chinese_PRC_CI_AS NULL, [收件人] [text] COLLATE Chinese_PRC_CI_AS NULL, [主题] [char](50) COLLATE Chinese_PRC_CI_AS NULL, [邮件内容] [text] COLLATE Chinese_PRC_CI_AS NULL, [添加时间] [datetime] NULL, [发送时间] [datetime] NULL, [状态] [numeric](11, 0) NULL, [ID] [int] NULL, [ID_9DSOFT] [int] IDENTITY(1,1) NOT NULL, [html] [bit] NULL, PRIMARY KEY CLUSTERED ( [ID_9DSOFT] ASC ) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 其中:编号、用户类型、用户编号几个字段为可选字段。 收件人:填写收件人地址,可以填写以分号分隔的多个邮件地址。 主题:邮件主题 状态:一定要置为 0,邮件发送程序只找状态为0的记录。 html:标识邮件是否是html邮件。 邮件内容:邮件主体内容,可以是纯文本,也可以是html内容 2 配置smtp,配置完成后要进行测试,测试通过后程序会将相应的smtp配置的状态设为为1,表示此smtp配置有效。其它的状态说明如下: 0:表示未测试过。 1:表示测试通过 2:表示测试未通过。 smtp配置信息保存在:程序工作目录\data\smtps.xml中 3 配置sql连接。 4:在要发送的邮件写入maillist中,在[邮件发送]标签中点击[发送]按钮,开始发送邮件。
c#邮件群发系统代码解析
2011/1/14 Blog: xiaoyaosr.blog.51cto.com | 逍遥散人 概要: 子线程工作,发送成功邮件做标记,逐条提取数据,气泡提示信息,最小化到托盘,实时进度条 代码: using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Data.OleDb; using System.Threading; using System.Text; using System.Windows.Forms; using System.Net.Mail; using System.Net; using System.Text.RegularExpressions; namespace MailGroupSends { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private string subject = string.Empty; private string mailto = string.Empty; private string body = string.Empty; private int sucNum = 0; private int TotalDate { get { if (this.txtDateCount.Text.Trim().Length > 0) return Convert.ToInt32(this.txtDateCount.Text.Trim()); return 4; } set { this.txtDateCount.Text = value.ToString(); } } private string ConnString { get { string pathFull = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; string path = pathFull.Substring(0, pathFull.LastIndexOf(@"\")); return @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + path + @"\mail.mdb"; } } private bool mailSent = false; //邮件是否发送成功 private int mailTotalCount = 0; private int CategoryId = 0; private int SentCount = 0; //已发送数 private int UnitConversion = 1; //默认为秒 /// <summary> /// 发送间隔 /// </summary> private int Interval { get { int timer = 0; int totalMis = (TotalDate * UnitConversion * 1000); timer = totalMis / (mailTotalCount-SentCount); return timer; } } /// <summary> /// 提取邮件 /// </summary> private void InitMailList() { OleDbConnection Conn = new OleDbConnection(ConnString); try { string strWhere = CategoryId == 1000 ? "" : " and categoryid=" + CategoryId + " order by isSend,uyx"; string sqlStr = @"select top 1 uyx from [usermail] where isDelete=0 and IsSend=0 " + strWhere; if (Conn.State == ConnectionState.Closed) Conn.Open(); OleDbCommand cmd = new OleDbCommand(sqlStr, Conn); OleDbDataReader reader = cmd.ExecuteReader(); mailto = string.Empty; while (reader.Read()) { mailto += reader[0].ToString() + ","; } reader.Close(); if (reader != null) reader.Dispose(); mailto = mailto.Trim(",".ToCharArray()); } catch (Exception ex) { MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { if (Conn.State == ConnectionState.Open) Conn.Close(); if (Conn != null) Conn.Dispose(); } } /// <summary> /// 加载邮件列表 /// </summary> private void LoadMailList() { this.dataGridView1.Columns.Clear(); if (this.dataGridView1.Rows.Count > 0) this.dataGridView1.Rows.Clear(); dataGridView1.RowHeadersWidth = 21; DataGridViewTextBoxColumn column = new DataGridViewTextBoxColumn(); column.ReadOnly = true; column.HeaderText = "邮箱列表"; column.DisplayIndex = 0; column.Name = "邮箱列表"; column.Width = 120; dataGridView1.Columns.Add(column); column = new DataGridViewTextBoxColumn(); column.ReadOnly = true; column.HeaderText = "状态"; column.DisplayIndex = 1; column.Name = "状态"; column.Width = 60; dataGridView1.Columns.Add(column); OleDbConnection Conn = new OleDbConnection(ConnString); try { string strWhere = CategoryId == 1000 ? "" : " and categoryid=" + CategoryId + " order by isSend,uyx"; string sql = @"select uyx,IsSend from usermail where isDelete=0 "+strWhere; if (Conn.State == ConnectionState.Closed) Conn.Open(); OleDbCommand cmd = new OleDbCommand(sql, Conn); OleDbDataReader reader = cmd.ExecuteReader(); mailTotalCount = 0; while (reader.Read()) { DataGridViewRow dgvr = new DataGridViewRow(); DataGridViewTextBoxCell cell = new DataGridViewTextBoxCell(); cell.Value = reader[0].ToString(); dgvr.Cells.Add(cell); cell = new DataGridViewTextBoxCell(); cell.Value = "●"; cell.Style.ForeColor = Convert.ToInt32(reader[1]) == 0 ? System.Drawing.Color.Yellow : System.Drawing.Color.Green; dgvr.Cells.Add(cell); dataGridView1.Rows.Add(dgvr); mailTotalCount++; } reader.Close(); if (reader != null) reader.Dispose(); this.lblmailCount.Text = "(" + SentCount + "/" + mailTotalCount + ")"; } catch { } finally { if (Conn.State == ConnectionState.Open) Conn.Close(); if (Conn != null) Conn.Dispose(); } } /// <summary> /// 已发送邮件个数 /// </summary> private void SentMailCount() { OleDbConnection Conn = new OleDbConnection(ConnString); try { string strWhere = CategoryId == 1000 ? "" : " and categoryid=" + CategoryId; string sqlStr = @"select uyx from [usermail] where isDelete=0 and IsSend=1 " + strWhere; if (Conn.State == ConnectionState.Closed) Conn.Open(); OleDbDataAdapter adapter = new OleDbDataAdapter(sqlStr, Conn); DataSet ds = new DataSet(); adapter.Fill(ds); SentCount = ds.Tables[0].Rows.Count; } catch (Exception ex) { MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { if (Conn.State == ConnectionState.Open) Conn.Close(); if (Conn != null) Conn.Dispose(); } } /// <summary> /// 标记出错的邮箱 /// </summary> /// <param name="mail"></param> private void MarkErrorMail(string mail) { OleDbConnection Conn = new OleDbConnection(ConnString); try { string sql = "update usermail set IsDelete=10 where uyx=‘" + mail + "‘ "; if (Conn.State == ConnectionState.Closed) Conn.Open(); OleDbCommand cmd = new OleDbCommand(sql, Conn); cmd.ExecuteNonQuery(); } catch { } finally { if (Conn.State == ConnectionState.Open) Conn.Close(); if (Conn != null) Conn.Dispose(); } } /// <summary> /// 修改已发送邮件状态 /// </summary> /// <param name="mail"></param> private void UpdateMailState(string mail, int state) { OleDbConnection Conn = new OleDbConnection(ConnString); try { string where = string.Empty; if (mail.Length > 0) { WriteToTxt(DateTime.Now + " Success " + mail, txtLogPath); if (mail.IndexOf(",") > -1) where = " and uyx =‘" + mail.Replace(",", "‘ and uyx=‘") + "‘ "; else where = " and uyx=‘" + mail + "‘"; } else { where = " and IsSend=1"; } string category = CategoryId == 1000 ? "" : " and categoryid=" + CategoryId; string sql = "update usermail set IsSend=" + state + " where IsDelete=0 " + category + where; if (Conn.State == ConnectionState.Closed) Conn.Open(); OleDbCommand cmd = new OleDbCommand(sql, Conn); cmd.ExecuteNonQuery(); } catch { } finally { if (Conn.State == ConnectionState.Open) Conn.Close(); if (Conn != null) Conn.Dispose(); } } /// <summary> /// 邮件发送 /// </summary> /// <param name="mailTo"></param> /// <param name="subject"></param> /// <param name="body"></param> /// <returns></returns> private bool Send(string mailTo, string subject, string body) { try { if (!IsEmail(mailTo)) { WriteToTxt(DateTime.Now + " Faild " + mailTo, txtLogPath + " Error Message:邮箱格式不正确"); MarkErrorMail(mailTo); return false; } if (mailTo.Substring(mailTo.Length - 1) == "." || mailTo.Substring(mailTo.Length - 1) == ",") { WriteToTxt(DateTime.Now + " Faild " + mailTo, txtLogPath + " Error Message:邮箱格式不正确"); MarkErrorMail(mailTo); return false; } MailMessage msg = new MailMessage(); msg.From = new MailAddress("***@****", "xiaoyaosr", Encoding.UTF8); if (mailTo.IndexOf(",") > -1) msg.Bcc.Add(mailTo); else msg.To.Add(mailTo); msg.Subject = subject; msg.Body = body; ArrayList annexList = ReadTxt(txtAnnexPath); for (int i = 0; i < annexList.Count; i++) { msg.Attachments.Add(new Attachment(annexList[i].ToString())); } SmtpClient smtp = new SmtpClient("mail.163.com"); smtp.Credentials = new NetworkCredential("***@****", "*******"); smtp.Send(msg); mailSent = true; sucNum++; } catch (Exception ex) { if (ex.Message.IndexOf("http://www.ipmotor.com/smtp_err.htm") > -1) { WriteToTxt(DateTime.Now + " Faild Error Message:" + ex.Message, txtLogPath); this.notifyIcon1.ShowBalloonTip(Interval, "", ex.Message, ToolTipIcon.None); System.Threading.Thread.Sleep(Interval * 2); base.Dispose(true); Application.ExitThread(); KillThread(); } WriteToTxt(DateTime.Now + " Faild " + mailTo + " Error Message:" + ex.Message, txtLogPath); MarkErrorMail(mailTo); mailSent = false; } return mailSent; } //*******************************************************************// //开始发送 public void StartMailSend() { MailSend mailSend = new MailSend(); mailSend.iTotalCount = mailTotalCount; mailSend.interval = Interval; mailSend.iSentCount = SentCount; mailSend.onMailSendProgress += new MailSend.dMailSendProgress(mailSend_onMailSendProgress); mailSend.Start(); } //同步更新 void mailSend_onMailSendProgress(int total, int current) { try { if (this.InvokeRequired) { this.Invoke(new MailSend.dMailSendProgress(mailSend_onMailSendProgress), new object[] { total, current }); } else { InitMailList(); string percent = (((current + 1) *100) / mailTotalCount).ToString() + "%"; string progress = percent + " " + (current + 1) + "/" + mailTotalCount; this.lableTimer.Text = progress; this.notifyIcon1.ShowBalloonTip(Interval,"", progress,ToolTipIcon.None);//气泡提示信息 this.progressBar1.Maximum = total; this.progressBar1.Value = current; if (total > 0 && subject.Length > 0) { mailto = mailto.Replace(" ", ","); if (Send(mailto, subject, body)) { UpdateMailState(mailto, 1); LoadMailList(); } } if (current == total - 1) { this.notifyIcon1.ShowBalloonTip(Interval, "", "发送完毕,成功发送" + sucNum + "封", ToolTipIcon.None); this.progressBar1.Visible = false; this.lblProgress.Visible = false; this.lableTimer.Text = ""; ControlEnabled(true); return; } } } catch(Exception ex) { this.notifyIcon1.ShowBalloonTip(Interval, "", ex.Message, ToolTipIcon.None); System.Threading.Thread.Sleep(Interval * 2); base.Dispose(true); Application.ExitThread(); KillThread(); } } private void Form1_Load(object sender, EventArgs e) { Control.CheckForIllegalCrossThreadCalls = false; InitMailCategory(); SentMailCount(); LoadMailList(); ClearTxt(txtAnnexPath); InitTime(); } /// <summary> /// 初始化时间长 /// </summary> private void InitTime() { if (mailTotalCount > 0 && SentCount < mailTotalCount) { this.txtDateCount.Text = ((mailTotalCount - SentCount) * 10).ToString(); this.lblTime.Text = TimeConvert((mailTotalCount - SentCount) * 10); } } /// <summary> /// 附件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnAnnexSelect_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.InitialDirectory = Application.ExecutablePath; ofd.FileName = ""; ofd.Filter = "所有文件(*)|*"; string strFileName = ""; if (ofd.ShowDialog() == DialogResult.OK) { strFileName = ofd.FileName; this.txtAnnex.Text = strFileName; } WriteToTxt(strFileName, txtAnnexPath); ArrayList list = ReadTxt(txtAnnexPath); if (list.Count > 0) { string str = string.Empty; for (int i = 0; i < list.Count; i++) { string file = list[i].ToString(); str += "·¡è"+file.Substring(file.LastIndexOf("\\") + 1) + ";"; } this.lblAnnexList.Text = str.Trim(";".ToCharArray()); } } /// <summary> /// 发送 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSendMail_Click(object sender, EventArgs e) { if (this.txtDateCount.Text.Trim().Length == 0 || !IsNumber(this.txtDateCount.Text.Trim())) { MessageBox.Show("请正确设定计划用时"); return; } TotalDate = Convert.ToInt32(this.txtDateCount.Text.Trim()); if(UnitConversion==1 && this.lblTime.Text.Length==0) this.lblTime.Text = TimeConvert(TotalDate); ControlEnabled(false); subject = this.txtSubject.Text.Trim(); body = this.rtxtBody.Text.Trim(); this.progressBar1.Visible = true; this.lblProgress.Visible = true; //用子线程工作 new Thread(new ThreadStart(StartMailSend)).Start(); } /// <summary> /// 刷新 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnRefresh_Click(object sender, EventArgs e) { LoadMailList(); } /// <summary> /// 邮件状态重置 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnMailStateReSet_Click(object sender, EventArgs e) { UpdateMailState("", 0); SentMailCount(); LoadMailList(); InitTime(); } /// <summary> /// 关闭 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnClose_Click(object sender, EventArgs e) { base.Dispose(true); Application.ExitThread(); KillThread(); } /// <summary> /// 结束进程 /// </summary> private void KillThread() { foreach (System.Diagnostics.Process thisproc in System.Diagnostics.Process.GetProcesses()) { if (thisproc.ProcessName.Equals("MailGroupSends")) { thisproc.Kill(); } } } /// <summary> /// 状态 /// </summary> /// <param name="state"></param> private void ControlEnabled(bool state) { this.txtDateCount.Enabled = state; this.rbHours.Enabled = state; this.rbMinutes.Enabled = state; this.rbtSeconds.Enabled = state; this.txtSubject.Enabled = state; this.rtxtBody.Enabled = state; this.txtAnnex.Enabled = state; this.btnAnnexSelect.Enabled = state; this.btnSendMail.Enabled = state; this.btnRefresh.Enabled = state; this.btnMailStateReSet.Enabled = state; this.comboBox_mailcategory.Enabled = state; this.lableTimer.Text = string.Empty; } /// <summary> /// 时 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void rbHours_Click(object sender, EventArgs e) { this.UnitConversion = 3600; this.lblTime.Text = ""; } /// <summary> /// 分 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void rbMinutes_Click(object sender, EventArgs e) { this.UnitConversion = 60; this.lblTime.Text = ""; } /// <summary> /// 秒 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void rbtSeconds_Click(object sender, EventArgs e) { this.UnitConversion = 1; } #region 最小化到托盘 private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e) { this.ShowInTaskbar = true; this.WindowState = FormWindowState.Normal; this.Activate(); } private void Form1_SizeChanged(object sender, EventArgs e) { if (this.WindowState == FormWindowState.Minimized) this.ShowInTaskbar = false; } #endregion /// <summary> /// 邮箱分类 /// </summary> private void InitMailCategory() { OleDbConnection Conn = new OleDbConnection(ConnString); try { string sql = @"select categoryid,categoryname from mailCategory where recordstate=0"; if (Conn.State == ConnectionState.Closed) Conn.Open(); OleDbCommand cmd = new OleDbCommand(sql, Conn); OleDbDataReader reader = cmd.ExecuteReader(); mailTotalCount = 0; DataTable table = new DataTable(); table.Columns.Add("categoryid"); table.Columns.Add("categoryname"); DataRow row = table.NewRow(); row[0] = "1000"; row[1] = "全部"; table.Rows.Add(row); row = table.NewRow(); row[0] = "0"; row[1] = "未分类"; table.Rows.Add(row); while (reader.Read()) { row = table.NewRow(); row[0] = reader[0].ToString(); row[1] = reader[1].ToString(); table.Rows.Add(row); } reader.Close(); if (reader != null) reader.Dispose(); this.comboBox_mailcategory.ValueMember = "categoryid"; this.comboBox_mailcategory.DisplayMember = "categoryname"; this.comboBox_mailcategory.DataSource = table; this.comboBox_mailcategory.SelectedIndex = 0; } catch { } finally { if (Conn.State == ConnectionState.Open) Conn.Close(); if (Conn != null) Conn.Dispose(); } } /// <summary> /// 选择邮箱分类 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void comboBox_mailcategory_SelectedIndexChanged(object sender, EventArgs e) { CategoryId =Convert.ToInt32(this.comboBox_mailcategory.SelectedValue); LoadMailList(); SentMailCount(); InitTime(); } /// <summary> /// 时间长(秒)转换成时分秒格式 /// </summary> /// <param name="time"></param> /// <returns></returns> private string TimeConvert(int time) { int h = time / 3600; int m = (time - h * 3600) / 60; int s = time - h * 3600 - m * 60; return h + "时" + m + "分" + s + "秒"; } /// <summary> /// 验证邮件格式是否正确 /// </summary> /// <param name="email"></param> /// <returns></returns> private bool IsEmail(string email) { string strExp = @"\w+([-+.‘]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"; Regex r = new Regex(strExp); Match m = r.Match(email); return m.Success ? true : false; } /// <summary> /// 是否为整数 /// </summary> /// <param name="txt"></param> /// <returns></returns> private bool IsNumber(string txt) { bool flag = false; try { int num = Convert.ToInt32(txt); flag = true; } catch { flag = false; } return flag; } #region TxtOperator private string txtAnnexPath { get { string pathFull = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; string path = pathFull.Substring(0, pathFull.LastIndexOf(@"\")); return path + @"\Annex.txt"; } } private string txtLogPath { get { string pathFull = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; string path = pathFull.Substring(0, pathFull.LastIndexOf(@"\")); return path + @"\Log.txt"; } } public void WriteToTxt(string txt, string filePath) { System.IO.FileInfo errfile = new System.IO.FileInfo(filePath); if (!errfile.Exists) { System.IO.FileStream fs = System.IO.File.Create(filePath); fs.Close(); } System.IO.StreamWriter srWriteLine = System.IO.File.AppendText(filePath); srWriteLine.WriteLine(txt); srWriteLine.Close(); } public ArrayList ReadTxt(string filePath) { string txt = string.Empty; System.IO.FileInfo errfile = new System.IO.FileInfo(filePath); if (!errfile.Exists) { System.IO.FileStream fs = System.IO.File.Create(filePath); fs.Close(); } System.IO.StreamReader objReader = new System.IO.StreamReader(filePath); string sLine = ""; ArrayList arrText = new ArrayList(); while (sLine != null) { sLine = objReader.ReadLine(); if (sLine != null) arrText.Add(sLine); } objReader.Close(); return arrText; } public void ClearTxt(string filePath) { System.IO.FileInfo errfile = new System.IO.FileInfo(filePath); if (ReadTxt(filePath).Count > 0) { System.IO.FileStream fs = System.IO.File.Create(filePath); fs.Close(); } } #endregion } } using System; using System.Collections; using System.Collections.Generic; using System.Text; using System.Threading; namespace MailGroupSends { public class MailSend { //委托 public delegate void dMailSendProgress(int total, int current); //事件 public event dMailSendProgress onMailSendProgress; public int iTotalCount; public int interval; public int iSentCount; //开始模拟工作 public void Start() { for (int i = iSentCount; i < iTotalCount; i++) { if (onMailSendProgress != null) onMailSendProgress(iTotalCount, i); Thread.Sleep(interval); } } } } 截图:
c#之 简单stmppop邮件服务(一)-------发送邮件
大家好! 很高兴和大家分享,邮件服务操作。我也是昨天刚刚学会的!呵呵,希望对大家有用。 c#的邮件服务,主要有两种。 一种是利用JMail组件,进行收发。 另一种是利用vs自带的stmp/pop3邮件服务,来实现。 我将要讲解的是利用stmp/pop3邮件服务。原因无它。vs自己就有,无需安装插件之类。 首先,我们要添加stmp/pop3邮件服务类的命名空间: using System.Net.Mail; 接下来,我给出源代码,并给出详细注释!是一个邮件发送函数,已测试成功。 如果你只想用,而不想理解那么多细节,那么在最后面,我给出了一个比较精简的发送邮箱函数(点击此处链接),希望,对你有帮助! /// <summary> /// 邮件发送 /// </summary> /// <param name="strTo">收信对象邮箱</param> /// <param name="strSubject">邮件主题</param> /// <param name="strBody">邮件内容</param> public static bool SendEmail(string strTo, string strSubject, string strBody) { string strSmtpServer = "smtp.163.com"; //163邮件服务器 string strFrom = "*****@163.com"; //用户邮箱 string strFromPass = "****";//用户密码 //string strSmtpServer = "smtp.qq.com"; //qq邮件服务器 //string strSmtpServer = "202.108.3.190"; //新浪邮件服务器 SmtpClient client = new SmtpClient(strSmtpServer);//创建邮箱服务器对象 client.UseDefaultCredentials = false;//获取或设置是否使用默认凭据访问 Web 代理服务器 client.Credentials = new System.Net.NetworkCredential(strFrom, strFromPass);//创建用户对象 client.DeliveryMethod = SmtpDeliveryMethod.Network;//投递方式 MailMessage message = new MailMessage(); //创建邮件对象 message.From = new MailAddress(strFrom); //发信人地址 message.To.Add(strTo); //添加收信人地址 message.Subject = strSubject; //邮件主题 message.Body = strBody; //邮件内容 //当然,你也把上面五条语句简化为如下: //MailMessage message = new MailMessage(strFrom, strto, strSubject, strBody); //添加附件,要注意的是,发送附件可能会慢点,耐心等下! //Attachment attachment = new Attachment("e:\\a.xls"); //创建附件对象,括号内参数为要添加的附件所在的地址 // message.Attachments.Add(attachment); //添加到邮件 message.BodyEncoding = System.Text.Encoding.UTF8;//获取或设置用于邮件正文的编码 message.IsBodyHtml = true;//取得或设定值,指出电子邮件的主体是否为 HTML if (!string.IsNullOrEmpty(strBody))//判断邮件内容是否为空 { try { client.Send(message);//发送 MessageBox.Show("发送成功!"); return true; } catch(Exception ex) { MessageBox.Show("发送失败:"+ex.Message); return false; } } else { MessageBox.Show("不能发送空信息!"); return false; } } 这里,再举一个调用该函数的例子: SendEmail("*****@qq.com","测试", "发送成功!"); 这里还要说明下邮件服务的一些细节,对于发邮件而言是stmp协议,而要接收邮件把stmp改成pop就可以,在以后的文章中, 将介绍到如何接收邮件: 1.qq邮箱 邮件服务器:smtp.qq.com 但要注意一点,qq的stmp/pop3服务必须开启才能连接,开启方法详见: http://service.mail.qq.com/cgi-bin/help?subtype=1&&no=308&&id=26 2.163邮箱 邮件服务器:smtp.163.com 3.新浪邮箱 邮件服务器:202.108.3.190 对于想设置为新浪邮箱的服务器的朋友,有三点要注意下: 1.服务器名设置不能用stmp.sina.com, 而是用它的ip地址,不信,你试试。 2.它的stmp/pos3功能要手动开启,方法同qq一样,这里就不重复了。 3.它不能发送qq邮件 下面是上面代码的精简版: /// <summary> /// 邮件发送 /// </summary> /// <param name="strTo">收信对象邮箱</param> /// <param name="strSubject">邮件主题</param> /// <param name="strBody">邮件内容</param> public static bool SendEmail2(string strto, string strSubject, string strBody) { string strSmtpServer = "smtp.163.com"; //163邮件服务器 string strFrom = "*******@163.com"; string strFromPass = "*******"; SmtpClient client = new SmtpClient(strSmtpServer); client.Credentials = new System.Net.NetworkCredential(strFrom, strFromPass); client.DeliveryMethod = SmtpDeliveryMethod.Network; MailMessage message = new MailMessage(strFrom, strto, strSubject, strBody); //添加附件,要注意的是,发送附件可能会慢点,耐心等下! //Attachment attachment = new Attachment("e:\\a.xls"); //创建附件对象,括号内参数为要添加的附件所在的地址 //message.Attachments.Add(attachment); //添加到邮件 try { client.Send(message); MessageBox.Show("发送成功!"); return true; } catch (Exception ex) { MessageBox.Show("发送失败:" + ex.Message); return false; } } 讲完了! 希望,对大家有用! 在后面,我将继续和大家分享邮件的一些基本应用。
可能是被对方邮箱当成垃圾邮件过滤了,
可能是被对方邮箱当成垃圾邮件过滤了, 再测试下, 给自己发, 如果收得到, 就是对方邮件过滤了, 发果收不到, 检查一下163的SMTP服务器设置正常, 是否开启POP接收发送邮件功能 附:发邮件代码 /// <summary> /// 发送邮件 /// </summary> /// <param name="smtpserver">SMTP服务器</param> /// <param name="userName">用户名</param> /// <param name="pwd">密码</param> /// <param name="strfrom">发件人</param> /// <param name="strto">收件人</param> /// <param name="subj">主题</param> /// <param name="bodys">内容</param> /// <param name="SendPort">端口</param> /// <param name="ssl">是否SSL加密</param> /// <returns>string(true/错误信息)</returns> private static bool IntoMail(string smtpserver, string userName, string pwd, string strfrom, string strto, string subj, string bodys, int SendPort, bool ssl) { try { System.Net.Mail.SmtpClient _smtpClient = new System.Net.Mail.SmtpClient(); _smtpClient.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network; _smtpClient.Host = smtpserver;//SMTP服务器 _smtpClient.Port = SendPort;//端口 _smtpClient.EnableSsl = ssl;//是否SSL加密 _smtpClient.Credentials = new System.Net.NetworkCredential(userName, pwd); System.Net.Mail.MailMessage _mailMessage = new System.Net.Mail.MailMessage(strfrom, strto); _mailMessage.Subject = subj; _mailMessage.Body = bodys; _mailMessage.BodyEncoding = System.Text.Encoding.Default;//正文编码 //_mailMessage.P _mailMessage.IsBodyHtml = true;//设置为HTML格式 _mailMessage.Priority = System.Net.Mail.MailPriority.High;//优先级 _smtpClient.Send(_mailMessage); return true; } catch { throw; } }
免费SMTP服务器
免费SMTP服务器版本:2.5 先进的SMTP服务器 - SMTP服务器 大量电子邮件邮件 - 您的用户发送电子邮件 第一大众梅勒 - 发送电子邮件和管理邮件列表 密码安全 工具 版权所有©1998-2008 Softstack.com个工作日 日期:02/03/2009 大小:619KB 价格:免费 平台:Windows的98/ME/NT/2000/XP/Vista/Win7 下载 | 更多信息 | 截图 主要特点:· 免费的SMTP服务器· 免费的SMTP服务器支持所有的电子邮件程序· 该计划是免费的· 为笔记本电脑用户免费的SMTP服务器是有用的 免费的SMTP服务器是一个Windows的SMTP服务器程序,它可让您直接从您的计算机发送电子邮件。这是很简单,但周游世界和自己的电脑连接在不同的国家不同的互联网服务供应商的笔记本电脑用户非常有用。您可以使用ISP的SMTP服务器,而不是增加您的安全和隐私。免费的SMTP服务器支持所有的电子邮件程序,如Outlook Express和Eudora,但与Outlook Express的最优化的工作。你已经在使用发送和接收邮件的电子邮件程序可以连接到服务器,在一个非常简单的方法 - 通过使用这个词的“localhost”,而不是你目前的SMTP主机。正因为如此,你可以发送邮件在一个平常的方式。免费的SMTP服务器是非常快的,同时发送,它建立了几十个SMTP连接,并得到最出你的互联网连接。该程序的用户界面是非常容易学习,包括优秀的文档。该计划是免费的,所以没有理由不下载和尝试它! 免责声明:免费的SMTP服务器是不是发送垃圾邮件的工具,它的名字没什么意思。我们不支持垃圾邮件,并严格禁止任何人使用免费的SMTP服务器发送不请自来的垃圾邮件。如果我们发现你用于此目的的程序,您的许可将被撤销,将停止所有的技术支持。通过下载或购买程序,您同意合法使用它。
用C#打造匿名邮件群发软件
电子邮件攻击是最常见的网络攻击手法之一,黑客们通过电子邮件发送木马、病毒或是包含有攻击性或信息获取脚本的特定html代码,使邮箱使用者打开这类邮件就会导致信息泄露甚至电脑被控制。而这种攻击手法常常要和“社会工程学”结合起来,信件要求伪装成邮箱使用者熟悉的发信人,以迷惑对方使其放松警惕,来达到获得重要信息和控制对方电脑的目的。为了深入的了解这种攻击方法,前段时间我打算在网上找一个免费好用的匿名邮件群发软件,来实际测试发送伪造信件的效果,结果上网转了一大圈也没找到一个称心如意的,不是收费就是试用,插件广告一大堆,想来邮件群发软件是被所谓的“邮件营销”用的太多太滥,难得找到好用而且免费的了。仔细想想有这时间精力去网上瞎找,还不如自己写一个合适的匿名群发器呢。有了源代码就掌握了主动权,以后想怎么改都行,再不用看那些“垃圾”邮件群发器的“脸色”了。哈哈,自己动手,丰衣足食,让我们准备好Visual Stdio.NET开发环境,开始编写属于自己的匿名邮件群发软件。 一、匿名发送原理 现在广泛使用的邮件发送协议是ESMTP,是由SMTP协议发展而来,SMTP协议由于没有身份认证等功能早已不被邮件服务提供商采用,当然如果我们自己架设邮件发送服务器的话可以使用该协议,因为该协议不用身份认证就可以实现完全的匿名邮件发送。现在还有很多免费邮件服务提供商让用户通过网页登录的方式来进行邮件的收发,这种WebMail的方式和上面所说的SMTP协议方式不在本文讨论之列,本文程序采用的ESMTP协议是被现在流行的邮件服务提供商广泛采用的邮件发送协议。在开始编程之前我们首先需要一个支持该协议的邮箱用于发信测试,现在大家使用的大部分邮箱都支持的。在这里我选163、新浪信箱进行测试。下面我们就通过telnet方式手工发送一封匿名邮件,以了解ESMTP协议和匿名效果(注:前面带“>”号的是输入命令) 复制内容到剪贴板 代码: >telnet smtp.163.com 25 //163邮件发送服务器的域名和端口 220 163.com Anti-spam GT for Coremail System (163com[20081010]) >HELO VVVVVV //告诉服务器我的机器名,当然是伪造的 250 OK >AUTH LOGIN //要求输入用户名密码 334 dXNlcm5hbWU6 >aWAsDSFc //Base64编码过的用户名 334 UGFzc3dvcmQ6 >GzlzNMUz //Base64编码过的密码 235 Authentication successful //提示认证成功 >MAIL FROM:<xxxxxx@163.com> //发件地址,这个必须是与上面输 //入的用户名对应的邮箱地址,163服务器会验证,否则无法发信。 250 Mail OK >RCPT TO:<liuhua@sina.com> //真实的收件人地址 250 Mail OK >DATA //要求发送邮件内容 354 End data with <CR><LF>.<CR><LF> >From: "fajianren" <fanjianren@163.com> //伪造的发信人地址 >To: "shoujianren" <shoujianren@sina.com> //伪造的收信人地址 >Subject: helloo Helloo //邮件主题 >tfffffffffffffffff //邮件正文 > >. //输入结束标志 250 Mail OK queued as smtp2,DNGowLD7TkkxNiZKCZ+FCg--.33908S3 1244018310 >quit //退出 221 Bye 现在我们登录到收件箱发现已经收到了这封伪造邮件,单从表面上看,我们是分辨不出它的真伪。原因在于ESMTP协议本身存在问题,它允许邮件发送者自己填写发件人和收件人的地址和姓名而并不检查,这就导致了伪造电子邮件的出现。 二、C#编写匿名群发 下面,开始编程实现匿名邮件群发功能。这里使用C#中封装好的TcpClient类,它可以直接为TCP网络服务提供客户端连接,不用再使用复杂的socket套接字接口类了。收件人列表和发件帐户列表分别存放和显示在richTextBox和ListView控件中,以实现使用不同帐户发送大量邮件的功能。这样做是为了避免同一邮箱帐户在同一段时间内因发送大量邮件而被邮件服务提供商锁定。以下是程序匿名发送部分的一些代码: 复制内容到剪贴板 代码: for (int i = 0; i < richTextBox2.Lines.Length; i++) //发送次数 {//建立与SMTP服务器的套接字 TcpClient SmtpServ = new TcpClient(SMTPHoststr, 25); NetworkStream NetStrm = SmtpServ.GetStream(); StreamReader RDStrm = new StreamReader(SmtpServ.GetStream()); Data = "HELO server " + CRLF; //在这里我们就默认叫server吧 szData = System.Text.Encoding.ASCII.GetBytes(Data. ToCharArray()); NetStrm.Write(szData, 0, szData.Length); //发送要求认证命令 Data = "AUTH LOGIN " + CRLF; szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray()); NetStrm.Write(szData, 0, szData.Length); //发送base64编码过的用户名 byte[] b = System.Text.Encoding.ASCII.GetBytes(namestr); string s = Convert.ToBase64String(b); Data = s + CRLF; szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray()); NetStrm.Write(szData, 0, szData.Length); //发送base64编码过的密码 b = System.Text.Encoding.ASCII.GetBytes(passwordstr); s = Convert.ToBase64String(b); Data = s + CRLF; szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray()); NetStrm.Write(szData, 0, szData.Length); //发送发件人信息 Data = "MAIL FROM: " + "<" + Senderstr + ">" + CRLF; szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray()); NetStrm.Write(szData, 0, szData.Length); //发送接收人信息 Data = "RCPT TO: " + "<" + richTextBox2.Lines.ToString() + ">" + CRLF; szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray()); NetStrm.Write(szData, 0, szData.Length); listBox1.Items.Add(RDStrm.ReadLine()); //发送Data命令 Data = "DATA" + CRLF; szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray()); NetStrm.Write(szData, 0, szData.Length); //发送数据内容 其中包括伪造的发、收件人地址和姓名; Data = ChangeString + "SUBJECT: " + textBox4.Text + CRLF + MIMEString + CRLF + richTextBox1.Text + CRLF; szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray()); NetStrm.Write(szData, 0, szData.Length); Data = CRLF + "." + CRLF; szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray()); NetStrm.Write(szData, 0, szData.Length); //退出SMTP服务器 Data = "QUIT " + CRLF; szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray()); NetStrm.Write(szData, 0, szData.Length); // 关闭连接 NetStrm.Close(); RDStrm.Close(); } 以上只是部分代码,整个程序编写完成后能够实现通过输入多个支持ESMTP协议的邮箱帐户向大量邮箱发送匿名邮件的功能。 三、程序效果 通过该程序向多个不同的邮件服务提供商邮箱发送匿名测试邮件,包括yahoo、hotmail、gmail、yeah、163、126、qq、sina邮箱(申请这么多种信箱搞测试,累呀J),测试发件帐户选用的是163信箱,邮件的查看方式采用的是登录到邮箱页面上直接查看,结果表明,除了发送到hotmail邮箱的匿名测试邮件在打开后会显示真实的发信人邮箱地址外其余均能够正常实现匿名。 J J J J 四、防范方法 如何有效的防范这些匿名的邮件,以避免被网络钓鱼邮件所欺骗呢?最有效的方法就是仔细分析可疑邮件的邮件头信息。在邮件头中包含的Received字段可以显示出邮件发送的完整轨迹。在邮件被发往目的地的过程中,每个中转服务器都会在邮件头中增加一条Received字段,这样一个邮件中就会有多条Received字段。所以要追踪到邮件的来源,可以采用自下向上的分析各条Received字段的方法。我们以发往sina的匿名邮件头为例,来探寻一下匿名邮件发送者的真面目。Received: from server (unknown [221.13.187.11]) by smtp11 (Coremail) with SMTP id D8CowLBL1IdlSypKdmHpBA--.12983S2; 这是第一条(自下而上)记录,虽然服务器名称显示的是我伪造的,可后面紧跟的IP地址却是我的真实地址,这个地址可以让匿名邮件发送者完全暴露,无处可逃(当然发送匿名邮件时使用代理的话,这个地址就是代理的IP地址了)。 Received: from m12-15.163.com ([220.181.12.15]) by irxd5-185.sinamail.sina.com.cn with ESMTP; 06 Jun 2009 18:56:41 +0800 上面第二条记录显示这封邮件被名为m12-15.163.com的服务器传送,显然如果这封匿名信件显示的发件地址不是来自163的话,那么它就一定是伪造的了。像这样对每一条Received字段进行分析,我们就可以掌握完整的邮件发送轨迹。在这封邮件的最上面有一条记录:Return-path:<xxxxxx@163.com>, 它完全暴露了真实发件人的电子信箱地址。当然并不是每个邮件服务提供商邮件中都有此字段。此外,我们可以再看看Message-ID字段:Message-Id: <4B3A4A67.05B67A.08726@m12-15.163.com>从这条记录可以看出,发信账户属于163。通过以上方法,我们可以识别出大部分的匿名邮件。当然,如果匿名邮件发送者通过代理来发送邮件,我们就很难找到它的真实发件IP地址了,同时Message-ID字段,信件发送时间都可以伪造,不同的邮件服务提供商邮件头所包含的信息也不尽相同,有时候一封精心伪造的邮件是很难识别出来的,需要涉及到很多知识,这里就不多说了。 五、总结和改进 文章中仔细分析和解决了邮件匿名和群发的问题。但对于邮件发送的内容编码没有仔细处理,如果需要发送非ASCII文本信息的话就需要事先对发送内容进行编码,如采用Base64编码的话就需要在DATA命令后发送Content- Transfer-Encoding:Base64命令,同时信件内容要进行Base64编码,这样就可以正常发送非ASCII内容信息的邮件了。同时程序没有太多的异常处理代码,也没有采用多线程发送,有需要的朋友可以自己加上
邮件群发账户配置大全(SMTP服务器配置)
邮件群发账户配置大全(SMTP服务器配置) 邮件群发账户配置大全(SMTP服务器配置) GMail 免费邮箱 http://gmail.google.com SMTP 服务器:smtp.gmail.com, SSL:是,服务器端口:465 策略:发送延时 0,每天发送量限制 50(GMail的每天发送量是动态控制的) 开通POP3/SMTP: 备注:gmail邮箱有可能被锁定,需要解锁,在这里进行解锁,按向导走就可以了。 评价:发送的有点慢(原因使用了SSL,服务器在国外),对于申请比较老的GMail邮箱每天发送的数量比较多(500/天)。 ————————————————————————————————— 网易免费邮箱 http://mail.126.com, http://mail.163.com, http://mail.yeah.net SMTP 服务器:smtp.126.com,smtp.163.com, smtp.yeah.net, SSL:否,服务器端口:25 策略:发送延时 20秒,每天发送量限制 50 开通POP3/SMTP: 备注: 评价:暂无 ————————————————————————————————— AOL免费邮箱 http://mail.aol.com SMTP 服务器:smtp.aol.com, SSL:否,服务器端口:25 策略:发送延时 5,每天发送量限制 100 开通POP3/SMTP:不需要 备注:AOL为美国著名门户网站,英文版。 评价:发国外邮箱比发国内邮箱效果好。 ————————————————————————————————— GMX免费邮箱 http://www.gmx.com SMTP 服务器:smtp.gmx.com, SSL:否,服务器端口:25 策略:发送延时 5,每天发送量限制 100 开通POP3/SMTP:不需要 备注:GMX是德国老牌邮箱,英文版。 评价:发国外邮箱比发国内邮箱效果好。 ————————————————————————————————— Gawab免费邮箱 http://www.gawab.com SMTP 服务器:smtp.gawab.com, SSL:否,服务器端口:25 策略:发送延时 5,每天发送量限制 100 开通POP3/SMTP:不需要 备注:Gawab是美国老牌邮箱,英文版。 评价:发国外邮箱比发国内邮箱效果好。 ————————————————————————————————— QQ免费邮箱 http://mail.qq.com SMTP 服务器:smtp.qq.com, SSL:否,服务器端口:25 策略:发送延时 45,每天发送量限制 50 开通POP3/SMTP:开通方法 备注:新激活的QQ邮箱,14天后才能使用POP3/SMTP功能 评价:近来发现QQ邮箱经常出现账户测试不通过,不稳定。 ————————————————————————————————— 搜狐免费邮箱 http://mail.sohu.com SMTP 服务器:smtp.sohu.com, SSL:否,服务器端口:25 策略:发送延时 135,每天发送量限制 100 开通POP3/SMTP:不需要 备注:无 评价:暂无 ————————————————————————————————— 雅虎免费邮箱 http://mail.yahoo.com.cn SMTP 服务器:smtp.mail.yahoo.com, SSL:否,服务器端口:25 策略:发送延时 5,每天发送量限制 100 开通POP3/SMTP:免费开通方法;付费开通方法 ,月租10元。 备注:此邮箱包含@yahoo.com, @yahoo.com.cn, @yahoo.cn 评价:暂无 ————————————————————————————————— 中国移动139免费邮箱 http://mail.139.com SMTP 服务器:smtp.139.com, SSL:否,服务器端口:25 策略:发送延时 15,每天发送量限制 100 开通POP3/SMTP:不需要 备注: 评价:暂无 ————————————————————————————————— Foxmail免费邮箱 http://mail.foxmail.com SMTP 服务器:smtp.foxmail.com, SSL:否,服务器端口:25 策略:发送延时 45,每天发送量限制 50 开通POP3/SMTP:Foxmail已经被腾讯收购,开通方法请参考QQ邮箱的开通SMTP方法。 备注: 评价:暂无 ————————————————————————————————— 新浪免费邮箱 http://mail.sina.com SMTP 服务器:smtp.sina.com, SSL:否,服务器端口:25 策略:发送延时 130,每天发送量限制 30 开通POP3/SMTP:开通方法 备注: 评价:暂无 ————————————————————————————————— HotMail, Windows live Mail 免费邮箱 http://mail.live.com SMTP 服务器:smtp.live.com, SSL:否,服务器端口:25 策略:发送延时 10,每天发送量限制 100 开通POP3/SMTP:不需要 备注: 评价:暂无 ————————————————————————————————— TOM免费邮箱和21CN免费邮箱采用了严格的邮件过滤技术,目前还不能支持这两种免费邮箱的发送。 ————————————————————————————————— 作者:Sunny Peng出处:http://www.cnblogs.com/psunny/本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
运用C#实现POP3邮件接收程序
微软的VS.Net开发工具推出已有一段时日了,其中的那门新语言C#也日渐为大家所熟悉并接受。C#作为一门新兴的语言相信具有传统语言不可比拟的优越性,特别是在网络应用方面,开发者更是感觉到了C#的强大功能。所以本文就通过运用C#来实现一个基于POP3协议的邮件接收程序来向大家展示C#网络编程的功能强大,同时也向大家介绍一下基于POP3协议的电子邮件接收原理。 首先我向大家介绍邮件接收的基本原理: 一开始便是客户端与服务器的连接。不过,在客户端连接到服务器之前,注意把端口设为POP3协议默认的110号。 客户端连接服务器成功后,服务器会返回以下信息: +OK…… 字符+OK是POP3协议的返回信息。它的回应信息不像SMTP协议那样用丰富多变的数字表示,只有两个:+OK或者-ERR。其中,+OK表示连接成功,而-ERR则表示连接失败。 接下来,客户端输入USER <用户名> 该命令告诉服务器你的用户名。注意,有些服务器会区分大小写字母的。 服务器返回+OK后,客户端输入PASS <口令> 服务器返回+OK后,还返回一些邮箱的统计信息,比如:+OK 1 message(s) [1304 byte(s)] 不同的服务器返回的信息格式不太一样,所以我们可以用STAT命令来查看邮箱的情况。STAT命令的回应中有两个数字,分别表示邮件的数量和邮件的大小。 如果信箱里有信,就可以用RETR命令来获取邮件的正文。RETR命令的格式为: RETR <邮件编号> 如果返回结果第一行是+OK信息,则表示成功。第二行起便是邮件的正文。最后一行和SMTP协议一样,是一个单独的英文句号,表示邮件的结尾部分。 把邮件存储起来后要用DELE命令删除邮箱中的邮件,否则原有的邮件会继续保留在服务器上,一旦邮件一多,你的邮箱就爆了。DELE命令的格式为: DELE <邮件编号> 如果删错了,可以用RSET命令来恢复所有已被删除的邮件。条件是你还没有退出,一旦退出,那就一切Bye Bye了。全部完成以后,输入QUIT命令就可以退出POP3服务器了。 实现 以上,我简要地向大家介绍了POP3邮件接收的基本过程和原理,下面就是一个运用上面的原理实现的简易的邮件接收程序。有了对基本原理的理解,编程的工作就变得相当轻松了。在本程序中,我主要用到了两个类:TcpClient类和NetworkStream类。TcpClient类是运用C#进行网络编程的一个非常重要的类,它提供了通过网络连接、发送和接收数据的简单方法,从而实现了网络编程的大大简化。NetworkStream类实现通过网络套接字发送和接收数据的标准.Net框架流机制,它支持对网络数据流的同步和异步访问,是实现网络通讯的重要组成部分。在这里我先给出程序最终的运行效果,图示如下:
自己电脑做smtp服务器不求人_邮件服务器
冲锋队:现在网络流行收费,Email当然首当其冲。容量小就小吧,可不能容忍的是发送速度也变得特慢,而且还有很多限制。能不能让自己的电脑充当发信服务器呢?这样就可以不受ISP的任何限制了。 Windows 2000用户 安装设置服务端 Windows XP和2000本身就拥有构件SMTP服务器的功能,只是一般还没有安装。选择“控制面板→添加/删除程序→添加/删除Windows组件”,弹出“Windows组件向导”对话框,在其中双击“Internet信息服务(IIS)”项,就会打开详细选择项,选中“SMTP Service”,按“确定”,插入Windows XP安装盘进行安装(如图1)。 安装好SMTP服务器后,选择“控制面板→性能和维护→管理工具→Internet信息服务”打开Internet信息服务设置窗口,在窗口左侧点击本地计算机名,展开本地计算机目录,可以看到有两个分支“Wed站点”和“默认SMTP虚拟服务器”。在“默认SMTP虚拟服务器”上点击鼠标右键选择“属性”,打开“默认SMTP虚拟服务器属性”窗口。 “常规”选项卡主要设置IP地址,单击IP地址下拉项选择“127.0.0.1”,表示指向本地计算机IP地址,其他项使用默认即可。如果你是局域网接入,拥有固定IP地址,那么IP地址就应该选择相应的地址(如图2)。 “访问”选项卡中设置访问权限。单击“身份验证”,选择“匿名访问”,表示任何用户都可以发送,其他两项不用选择;单击“连接控制”中的“连接”和“中段限制”中的“中断”,选中“仅以下列表除外”,表示可以许接入所有用户的访问。 “邮件”选项卡中设置邮件传输条件及限制,“限制邮件大小为”等四个选项可以使用默认值,无须更改; “将未传递报告的副本发送到”可将发送不成功的邮件返回发件人,并且写明不成功的原因;“死信目录”设置没有发送成功的邮件被存放的位置。 “传输”选项中设置邮件传递时间,这里不用修改,使用默认值;“LDAP路由”选项用来指定服务器使用的目录服务器标识和属性,这里也不用启动它。 “安全”选项中设置使用发送服务器的有权用户,默认用户是“Administrators”,你可以单击“添加”添加使用用户。 一切设置好后,你就拥护了自己的邮件发送服务器了!下面我们来看看在Outlook Express和Foxmail中如何设置使用自己的SMTP来发信。 设置客户端软件 打开Outlook Express,选择“工具→账号→邮件”,选中帐号点“属性”,在“服务器”标签下的“发送邮件(SMTP)”中输入“127.0.0.1”,即本机地址(如图3),“我的服务器需要身份验证”不选择。 在Foxmail中选择需要设置本机发信的帐号,然后选择“帐号→属性→邮件服务器”,在“发送邮件服务器”中输入“127.0.0.1”(如图4),“SMTP邮件服务器需要身份验证”也不要选择上。 撰写发送邮件和我们平时操作一样,没有什么区别。写好后点发送,邮件会在瞬间发送完毕。 , 文章整理:西部数码--专业提供域名注册、虚拟主机服务 http://www.west263.com 以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!
Imports System Imports System.Net Imports System.Net.Mime Imports System.Net.Mail Public Class Form1 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load SendWebMailAndAttach("smtp.126.com") End Sub Public Shared Sub SendWebMailAndAttach(ByVal server As String) Dim file As String = "项目提交申请表.doc" Dim message As New System.Net.Mail.MailMessage("aa@126.com", "bb@126.com", "text message for you.", "Test Title") Dim data As New System.Net.Mail.Attachment(file, System.Net.Mime.MediaTypeNames.Application.Octet) Dim disposition As System.Net.Mime.ContentDisposition = data.ContentDisposition disposition.CreationDate = System.IO.File.GetCreationTime(file) disposition.ModificationDate = System.IO.File.GetLastWriteTime(file) disposition.ReadDate = System.IO.File.GetLastAccessTime(file) message.Attachments.Add(data) Dim client As New System.Net.Mail.SmtpClient(server) client.Credentials = New NetworkCredential("aa", "aaaaaaaaaaaaaa") client.Send(message) data.Dispose() End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) ‘Dim FileName As String = "项目提交申请表.doc" ‘Dim Message As New Mail.MailMessage ‘Message.From = New MailAddress("aa@126.com", "aa") ‘Message.To.Add("bb@126.com") ‘Message.CC.Add("aa@126.com") ‘Message.Subject = "你好" ‘Message.Body = "你好啊" ‘Dim data As New System.Net.Mail.Attachment(FileName, System.Net.Mime.MediaTypeNames.Application.Octet) ‘Dim disposition As System.Net.Mime.ContentDisposition = data.ContentDisposition ‘disposition.CreationDate = System.IO.File.GetCreationTime(FileName) ‘disposition.ModificationDate = System.IO.File.GetLastWriteTime(FileName) ‘disposition.ReadDate = System.IO.File.GetLastAccessTime(FileName) ‘Message.Attachments.Add(data) ‘Dim client As New Mail.SmtpClient("smtp.126.com") ‘client.Credentials = New NetworkCredential("aa", "aaaaaaaaaaaaaa") ‘client.Send(Message) ‘data.Dispose() End Sub End Class
1298671954
教师联盟
Exchange Server破解版
http://bbs.pcbeta.com/viewthread-324082-1-1.html
win7配置smtp
http://bbs.51cto.com/thread-636650-1.html
http://www.hackol.com/down/20100626081459434051.shtml
imail
http://hi.baidu.com/morecn/blog/item/47efbafbc222cb264f4aea29.html
http://www.catmaomao.com/download/view-software-13886.html
http://www.zhujiangroad.com/software/html/44/44027.html
http://www.a6a7.com/down/38902.shtml
mdaemon
http://www.pc6.com/softview/SoftView_5502.html
标签:识别 编号 end 邮件内容 上网 保存 提示信息 regular 邮件服务器
原文地址:https://www.cnblogs.com/blogpro/p/11458419.html