using System; using System.Collections.Generic; using System.Linq; using System.Text; using CY.Infrastructure.Common; using System.Net.Sockets; using System.Collections; namespace CY.Infrastructure.Mail { #region 邮件发送程序 /// /// Discuz!NT邮件发送程序 /// [SmtpEmail("邮件发送程序", Version = "2.0", Author = "zg", DllFileName = "CY.Infrastructure.dll")] public class SmtpMail : ISmtpMail { private string enter = "\r\n"; /// /// 设定语言代码,默认设定为GB2312,如不需要可设置为"" /// private string _charset = "GB2312"; /// /// 发件人地址 /// private string _from = ""; /// /// 发件人姓名 /// private string _fromName = ""; /// /// 回复邮件地址 /// ///public string ReplyTo=""; /// /// 收件人姓名 /// private string _recipientName = ""; /// /// 收件人列表 /// private Hashtable Recipient = new Hashtable(); /// /// 邮件服务器域名 /// private string mailserver = ""; /// /// 邮件服务器端口号 /// private int mailserverport = 25; /// /// SMTP认证时使用的用户名 /// private string username = ""; /// /// SMTP认证时使用的密码 /// private string password = ""; /// /// 是否需要SMTP验证 /// private bool ESmtp = false; /// /// 是否Html邮件 /// private bool _html = false; /// /// 邮件附件列表 /// private IList Attachments; /// /// 邮件发送优先级,可设置为"High","Normal","Low"或"1","3","5" /// private string priority = "Normal"; /// /// 邮件主题 /// private string _subject; /// /// 邮件正文 /// private string _body; /// /// 密送收件人列表 /// ///private Hashtable RecipientBCC=new Hashtable(); /// /// 收件人数量 /// private int RecipientNum = 0; /// /// 最多收件人数量 /// private int recipientmaxnum = 5; /// /// 密件收件人数量 /// ///private int RecipientBCCNum=0; /// /// 错误消息反馈 /// private string errmsg; /// /// TcpClient对象,用于连接服务器 /// private TcpClient tc; /// /// NetworkStream对象 /// private NetworkStream ns; /// /// 服务器交互记录 /// private string logs = ""; /// /// SMTP错误代码哈希表 /// private Hashtable ErrCodeHT = new Hashtable(); /// /// SMTP正确代码哈希表 /// private Hashtable RightCodeHT = new Hashtable(); /// /// public SmtpMail() { Attachments = new System.Collections.ArrayList(); SMTPCodeAdd(); } #region Properties /// /// 邮件主题 /// public string Subject { get { return this._subject; } set { this._subject = value; } } /// /// 邮件正文 /// public string Body { get { return this._body; } set { this._body = value; } } /// /// 发件人地址 /// public string From { get { return _from; } set { this._from = value; } } /// /// 设定语言代码,默认设定为GB2312,如不需要可设置为"" /// public string Charset { get { return this._charset; } set { this._charset = value; } } /// /// 发件人姓名 /// public string FromName { get { return this._fromName; } set { this._fromName = value; } } /// /// 收件人姓名 /// public string RecipientName { get { return this._recipientName; } set { this._recipientName = value; } } /// /// 邮件服务器域名和验证信息 /// 形如:"user:pass@www.server.com:25",也可省略次要信息。如"user:pass@www.server.com"或"www.server.com" /// public string MailDomain { set { string maidomain = value.Trim(); int tempint; if (maidomain != "") { tempint = maidomain.IndexOf("@"); if (tempint != -1) { string str = maidomain.Substring(0, tempint); MailServerUserName = str.Substring(0, str.IndexOf(":")); MailServerPassWord = str.Substring(str.IndexOf(":") + 1, str.Length - str.IndexOf(":") - 1); maidomain = maidomain.Substring(tempint + 1, maidomain.Length - tempint - 1); } tempint = maidomain.IndexOf(":"); if (tempint != -1) { mailserver = maidomain.Substring(0, tempint); mailserverport = System.Convert.ToInt32(maidomain.Substring(tempint + 1, maidomain.Length - tempint - 1)); } else { mailserver = maidomain; } } } } /// /// 邮件服务器端口号 /// public int MailDomainPort { set { mailserverport = value; } } /// /// SMTP认证时使用的用户名 /// public string MailServerUserName { set { if (value.Trim() != "") { username = value.Trim(); ESmtp = true; } else { username = ""; ESmtp = false; } } } /// /// SMTP认证时使用的密码 /// public string MailServerPassWord { set { password = value; } } public string ErrCodeHTMessage(string code) { return ErrCodeHT[code].ToString(); } /// /// 邮件发送优先级,可设置为"High","Normal","Low"或"1","3","5" /// public string Priority { set { switch (value.ToLower()) { case "high": priority = "High"; break; case "1": priority = "High"; break; case "normal": priority = "Normal"; break; case "3": priority = "Normal"; break; case "low": priority = "Low"; break; case "5": priority = "Low"; break; default: priority = "High"; break; } } } /// /// 是否Html邮件 /// public bool Html { get { return this._html; } set { this._html = value; } } /// /// 错误消息反馈 /// public string ErrorMessage { get { return errmsg; } } /// /// 服务器交互记录 /// public string Logs { get { return logs; } } /// /// 最多收件人数量 /// public int RecipientMaxNum { set { recipientmaxnum = value; } } #endregion #region Methods /// /// 添加邮件附件 /// /// 附件绝对路径 public void AddAttachment(params string[] FilePath) { if (FilePath == null) { throw (new ArgumentNullException("FilePath")); } for (int i = 0; i < FilePath.Length; i++) { Attachments.Add(FilePath[i]); } } /// /// 添加一组收件人(不超过recipientmaxnum个),参数为字符串数组 /// /// 保存有收件人地址的字符串数组(不超过recipientmaxnum个) public bool AddRecipient(params string[] Recipients) { if (Recipient == null) { Dispose(); throw (new ArgumentNullException("Recipients")); } for (int i = 0; i < Recipients.Length; i++) { string recipient = Recipients[i].Trim(); if (recipient == String.Empty) { Dispose(); throw new ArgumentNullException("Recipients[" + i + "]"); } if (recipient.IndexOf("@") == -1) { Dispose(); throw new ArgumentException("Recipients.IndexOf(\"@\")==-1", "Recipients"); } if (!AddRecipient(recipient)) { return false; } } return true; } /// /// 发送邮件方法,所有参数均通过属性设置。 /// public bool Send() { if (mailserver.Trim() == "") { throw (new ArgumentNullException("Recipient", "必须指定SMTP服务器")); } return SendEmail(); } /// /// 发送邮件方法 /// /// smtp服务器信息,如"username:password@www.smtpserver.com:25",也可去掉部分次要信息,如"www.smtpserver.com" public bool Send(string smtpserver) { MailDomain = smtpserver; return Send(); } /// /// 发送邮件方法 /// /// smtp服务器信息,如"username:password@www.smtpserver.com:25",也可去掉部分次要信息,如"www.smtpserver.com" /// 发件人mail地址 /// 发件人姓名 /// 收件人地址 /// 收件人姓名 /// 是否HTML邮件 /// 邮件主题 /// 邮件正文 public bool Send(string smtpserver, string from, string fromname, string to, string toname, bool html, string subject, string body) { MailDomain = smtpserver; From = from; FromName = fromname; AddRecipient(to); RecipientName = toname; Html = html; Subject = subject; Body = body; return Send(); } #endregion #region Private Helper Functions /// /// 添加一个收件人 /// /// 收件人地址 private bool AddRecipient(string Recipients) { //修改等待邮件验证的用户重复发送的问题 Recipient.Clear(); RecipientNum = 0; if (RecipientNum < recipientmaxnum) { Recipient.Add(RecipientNum, Recipients); RecipientNum++; return true; } else { Dispose(); throw (new ArgumentOutOfRangeException("Recipients", "收件人过多不可多于 " + recipientmaxnum + " 个")); } } void Dispose() { if (ns != null) ns.Close(); if (tc != null) tc.Close(); } /// /// SMTP回应代码哈希表 /// private void SMTPCodeAdd() { ErrCodeHT.Add("500", "邮箱地址错误"); ErrCodeHT.Add("501", "参数格式错误"); ErrCodeHT.Add("502", "命令不可实现"); ErrCodeHT.Add("503", "服务器需要SMTP验证"); ErrCodeHT.Add("504", "命令参数不可实现"); ErrCodeHT.Add("421", "服务未就绪,关闭传输信道"); ErrCodeHT.Add("450", "要求的邮件操作未完成,邮箱不可用(例如,邮箱忙)"); ErrCodeHT.Add("550", "要求的邮件操作未完成,邮箱不可用(例如,邮箱未找到,或不可访问)"); ErrCodeHT.Add("451", "放弃要求的操作;处理过程中出错"); ErrCodeHT.Add("551", "用户非本地,请尝试"); ErrCodeHT.Add("452", "系统存储不足, 要求的操作未执行"); ErrCodeHT.Add("552", "过量的存储分配, 要求的操作未执行"); ErrCodeHT.Add("553", "邮箱名不可用, 要求的操作未执行(例如邮箱格式错误)"); ErrCodeHT.Add("432", "需要一个密码转换"); ErrCodeHT.Add("534", "认证机制过于简单"); ErrCodeHT.Add("538", "当前请求的认证机制需要加密"); ErrCodeHT.Add("454", "临时认证失败"); ErrCodeHT.Add("530", "需要认证"); RightCodeHT.Add("220", "服务就绪"); RightCodeHT.Add("250", "要求的邮件操作完成"); RightCodeHT.Add("251", "用户非本地, 将转发向"); RightCodeHT.Add("354", "开始邮件输入, 以.结束"); RightCodeHT.Add("221", "服务关闭传输信道"); RightCodeHT.Add("334", "服务器响应验证Base64字符串"); RightCodeHT.Add("235", "验证成功"); } /// /// 将字符串编码为Base64字符串 /// /// 要编码的字符串 private string Base64Encode(string str) { byte[] barray; barray = Encoding.Default.GetBytes(str); return Convert.ToBase64String(barray); } /// /// 将Base64字符串解码为普通字符串 /// /// 要解码的字符串 private string Base64Decode(string str) { byte[] barray; barray = Convert.FromBase64String(str); return Encoding.Default.GetString(barray); } /// /// 得到上传附件的文件流 /// /// 附件的绝对路径 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)); } /// /// 发送SMTP命令 /// private bool SendCommand(string str) { byte[] WriteBuffer; if (str == null || str.Trim() == String.Empty) { return true; } logs += str; WriteBuffer = Encoding.Default.GetBytes(str); try { ns.Write(WriteBuffer, 0, WriteBuffer.Length); } catch { errmsg = "网络连接错误"; return false; } return true; } /// /// 接收SMTP服务器回应 /// private string RecvResponse() { int StreamSize; string ReturnValue = String.Empty; byte[] ReadBuffer = new byte[1024]; try { StreamSize = ns.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.enter; return ReturnValue; } } /// /// 与服务器交互,发送一条命令并接收回应。 /// /// 一个要发送的命令 /// 如果错误,要反馈的信息 private bool Dialog(string str, string errstr) { if (str == null || str.Trim() == "") { return true; } if (SendCommand(str)) { string RR = RecvResponse(); if (RR == "false") { return false; } string RRCode = RR.Substring(0, 3); if (RightCodeHT[RRCode] != null) { return true; } else { if (ErrCodeHT[RRCode] != null) { errmsg += (RRCode + ErrCodeHT[RRCode].ToString()); errmsg += enter; } else { errmsg += RR; } errmsg += errstr; return false; } } else { return false; } } /// /// 与服务器交互,发送一组命令并接收回应。 /// private bool Dialog(string[] str, string errstr) { for (int i = 0; i < str.Length; i++) { if (!Dialog(str[i], "")) { errmsg += enter; errmsg += errstr; return false; } } return true; } /// /// SendEmail /// /// private bool SendEmail() { //连接网络 try { tc = new TcpClient(mailserver, mailserverport); } catch (Exception e) { errmsg = e.ToString(); return false; } ns = tc.GetStream(); //验证网络连接是否正确 if (RightCodeHT[RecvResponse().Substring(0, 3)] == null) { errmsg = "网络连接失败"; return false; } string[] SendBuffer; string SendBufferstr; //进行SMTP验证 if (ESmtp) { SendBuffer = new String[4]; SendBuffer[0] = "EHLO " + mailserver + enter; SendBuffer[1] = "AUTH LOGIN" + enter; SendBuffer[2] = Base64Encode(username) + enter; SendBuffer[3] = Base64Encode(password) + enter; if (!Dialog(SendBuffer, "SMTP服务器验证失败,请核对用户名和密码。")) return false; } else { SendBufferstr = "HELO " + mailserver + enter; if (!Dialog(SendBufferstr, "")) return false; } // SendBufferstr = "MAIL FROM:<" + From + ">" + enter; if (!Dialog(SendBufferstr, "发件人地址错误,或不能为空")) return false; // SendBuffer = new string[recipientmaxnum]; for (int i = 0; i < Recipient.Count; i++) { SendBuffer[i] = "RCPT TO:<" + Recipient[i].ToString() + ">" + enter; } if (!Dialog(SendBuffer, "收件人地址有误")) return false; /* SendBuffer=new string[10]; for(int i=0;i" + enter; } if(!Dialog(SendBuffer,"密件收件人地址有误")) return false; */ SendBufferstr = "DATA" + enter; if (!Dialog(SendBufferstr, "")) return false; SendBufferstr = "From:" + FromName + "<" + From + ">" + enter; //if(ReplyTo.Trim()!="") //{ // SendBufferstr+="Reply-To: " + ReplyTo + enter; //} //SendBufferstr += "To:" + (Discuz.Common.Utils.StrIsNullOrEmpty(RecipientName)?"":Base64Encode(RecipientName)) + "<" + Recipient[0] + ">" + enter; SendBufferstr += "To:=?" + Charset.ToUpper() + "?B?" + (Utils.StrIsNullOrEmpty(RecipientName) ? "" : Base64Encode(RecipientName)) + "?=" + "<" + Recipient[0] + ">" + enter; //注释掉抄送代码 SendBufferstr += "CC:"; for (int i = 1; i < Recipient.Count; i++) { SendBufferstr += Recipient[i].ToString() + "<" + Recipient[i].ToString() + ">,"; } SendBufferstr += enter; SendBufferstr += ((Subject == String.Empty || Subject == null) ? "Subject:" : ((Charset == "") ? ("Subject:" + Subject) : ("Subject:" + "=?" + Charset.ToUpper() + "?B?" + Base64Encode(Subject) + "?="))) + enter; SendBufferstr += "X-Priority:" + priority + enter; SendBufferstr += "X-MSMail-Priority:" + priority + enter; SendBufferstr += "Importance:" + priority + enter; SendBufferstr += "X-Mailer: Lion.Web.Mail.SmtpMail Pubclass [cn]" + enter; SendBufferstr += "MIME-Version: 1.0" + enter; if (Attachments.Count != 0) { SendBufferstr += "Content-Type: multipart/mixed;" + enter; SendBufferstr += " boundary=\"=====" + (Html ? "001_Dragon520636771063_" : "001_Dragon303406132050_") + "=====\"" + enter + enter; } if (Html) { if (Attachments.Count == 0) { SendBufferstr += "Content-Type: multipart/alternative;" + enter;//内容格式和分隔符 SendBufferstr += " boundary=\"=====003_Dragon520636771063_=====\"" + enter + enter; SendBufferstr += "This is a multi-part message in MIME format." + enter + enter; } else { SendBufferstr += "This is a multi-part message in MIME format." + enter + enter; SendBufferstr += "--=====001_Dragon520636771063_=====" + enter; SendBufferstr += "Content-Type: multipart/alternative;" + enter;//内容格式和分隔符 SendBufferstr += " boundary=\"=====003_Dragon520636771063_=====\"" + enter + enter; } SendBufferstr += "--=====003_Dragon520636771063_=====" + enter; SendBufferstr += "Content-Type: text/plain;" + enter; SendBufferstr += ((Charset == "") ? (" charset=\"iso-8859-1\"") : (" charset=\"" + Charset.ToLower() + "\"")) + enter; SendBufferstr += "Content-Transfer-Encoding: base64" + enter + enter; SendBufferstr += Base64Encode("邮件内容为HTML格式,请选择HTML方式查看") + enter + enter; SendBufferstr += "--=====003_Dragon520636771063_=====" + enter; SendBufferstr += "Content-Type: text/html;" + enter; SendBufferstr += ((Charset == "") ? (" charset=\"iso-8859-1\"") : (" charset=\"" + Charset.ToLower() + "\"")) + enter; SendBufferstr += "Content-Transfer-Encoding: base64" + enter + enter; SendBufferstr += Base64Encode(Body) + enter + enter; SendBufferstr += "--=====003_Dragon520636771063_=====--" + enter; } else { if (Attachments.Count != 0) { SendBufferstr += "--=====001_Dragon303406132050_=====" + enter; } SendBufferstr += "Content-Type: text/plain;" + enter; SendBufferstr += ((Charset == "") ? (" charset=\"iso-8859-1\"") : (" charset=\"" + Charset.ToLower() + "\"")) + enter; SendBufferstr += "Content-Transfer-Encoding: base64" + enter + enter; SendBufferstr += Base64Encode(Body) + enter; } //SendBufferstr += "Content-Transfer-Encoding: base64"+enter; if (Attachments.Count != 0) { for (int i = 0; i < Attachments.Count; i++) { string filepath = (string)Attachments[i]; SendBufferstr += "--=====" + (Html ? "001_Dragon520636771063_" : "001_Dragon303406132050_") + "=====" + enter; //SendBufferstr += "Content-Type: application/octet-stream"+enter; SendBufferstr += "Content-Type: text/plain;" + enter; SendBufferstr += " name=\"=?" + Charset.ToUpper() + "?B?" + Base64Encode(filepath.Substring(filepath.LastIndexOf("\\") + 1)) + "?=\"" + enter; SendBufferstr += "Content-Transfer-Encoding: base64" + enter; SendBufferstr += "Content-Disposition: attachment;" + enter; SendBufferstr += " filename=\"=?" + Charset.ToUpper() + "?B?" + Base64Encode(filepath.Substring(filepath.LastIndexOf("\\") + 1)) + "?=\"" + enter + enter; SendBufferstr += GetStream(filepath) + enter + enter; } SendBufferstr += "--=====" + (Html ? "001_Dragon520636771063_" : "001_Dragon303406132050_") + "=====--" + enter + enter; } SendBufferstr += enter + "." + enter; if (!Dialog(SendBufferstr, "错误信件信息")) return false; SendBufferstr = "QUIT" + enter; if (!Dialog(SendBufferstr, "断开连接时错误")) return false; ns.Close(); tc.Close(); return true; } #endregion #region /* /// /// 添加一个密件收件人 /// /// 收件人地址 public bool AddRecipientBCC(string str) { if(str==null||str.Trim()=="") return true; if(RecipientBCCNum<10) { RecipientBCC.Add(RecipientBCCNum,str); RecipientBCCNum++; return true; } else { errmsg+="收件人过多"; return false; } } /// /// 添加一组密件收件人(不超过10个),参数为字符串数组 /// /// 保存有收件人地址的字符串数组(不超过10个) public bool AddRecipientBCC(string[] str) { for(int i=0;i