using System;
using System.Text;
using System.IO;
using System.Net.Sockets;
using System.Collections;
namespace Baolee.GeneralMethod
{
/// <summary>
/// ESmtpMail 的摘要说明。
/// </summary>
public class ESmtpMail
{
#region // Fields
private ArrayList Attachments;
public string Body;
public string Charset;
private string enter;
private Hashtable ErrCodeHT;
private string errmsg;
private bool ESmtp;
public string From;
public string FromName;
public bool Html;
private string logs;
private string mailserver;
private int mailserverport;
private NetworkStream ns;
private string password;
private string priority;
private Hashtable Recipient;
private int recipientmaxnum;
public string RecipientName;
private int RecipientNum;
private Hashtable RightCodeHT;
public string Subject;
private TcpClient tc;
private string username;
#endregion
#region 建构函式
/// <summary>
/// 建构函式
/// </summary>
public ESmtpMail()
{
this.enter = "/r/n";
this.Charset = "GB2312";
this.From = "";
this.FromName = "";
this.RecipientName = "";
this.Recipient = new Hashtable();
this.mailserver = "";
this.mailserverport = 0x19;
this.username = "";
this.password = "";
this.ESmtp = false;
this.Html = false;
this.priority = "Normal";
this.Subject = "";
this.Body = "";
this.RecipientNum = 0;
this.recipientmaxnum = 1;
this.ErrCodeHT = new Hashtable();
this.RightCodeHT = new Hashtable();
this.logs = "";
this.Attachments = new ArrayList();
}
#endregion
#region // Methods
/// <summary>
/// 添加邮件附件
/// </summary>
/// <param name="path">附件绝对路径</param>
public void AddAttachment(string path)
{
this.Attachments.Add(path);
}
/// <summary>
/// 添加一组收件人(不超过recipientmaxnum个),参数为字符串数组
/// </summary>
/// <param name="str">保存有收件人地址的字符串数组(不超过recipientmaxnum个)</param>
/// <returns></returns>
public bool AddRecipient(string[] str)
{
for (int i = 0; i < str.Length; i++)
{
if (!this.AddRecipient(str[i]))
{
return false;
}
}
return true;
}
/// <summary>
/// 添加一个收件人
/// </summary>
/// <param name="str">收件人地址</param>
/// <returns></returns>
public bool AddRecipient(string str)
{
str = str.Trim();
if (((str == null) || (str == "")) || (str.IndexOf("@") == -1))
{
return true;
}
if (this.RecipientNum < this.recipientmaxnum)
{
this.Recipient.Add(this.RecipientNum, str);
this.RecipientNum++;
return true;
}
this.errmsg = this.errmsg + "收件人过多";
return false;
}
/// <summary>
/// 将Base64字符串解码为普通字符串
/// </summary>
/// <param name="str">要解码的字符串</param>
/// <returns></returns>
private string Base64Decode(string str)
{
byte[] bytes = Convert.FromBase64String(str);
return Encoding.Default.GetString(bytes);
}
/// <summary>
/// 将字符串编码为Base64字符串
/// </summary>
/// <param name="str">要编码的字符串</param>
/// <returns></returns>
private string Base64Encode(string str)
{
return Convert.ToBase64String(Encoding.Default.GetBytes(str));
}
/// <summary>
/// 与服务器交互,发送一条命令并接收回应。
/// </summary>
/// <param name="str">一个要发送的命令</param>
/// <param name="errstr">如果错误,要反馈的信息</param>
/// <returns></returns>
private bool Dialog(string str, string errstr)
{
if ((str == null) || (str.Trim() == ""))
{
return true;
}
if (this.SendCommand(str))
{
string text = this.RecvResponse();
if (text == "false")
{
return false;
}
string text2 = text.Substring(0, 3);
if (this.RightCodeHT[text2] != null)
{
return true;
}
if (this.ErrCodeHT[text2] != null)
{
this.errmsg = this.errmsg + text2 + this.ErrCodeHT[text2].ToString();
this.errmsg = this.errmsg + this.enter;
}
else
{
this.errmsg = this.errmsg + text;
}
this.errmsg = this.errmsg + errstr;
}
return false;
}
/// <summary>
/// 与服务器交互,发送一组命令并接收回应。
/// </summary>
/// <param name="str"></param>
/// <param name="errstr"></param>
/// <returns></returns>
private bool Dialog(string[] str, string errstr)
{
for (int i = 0; i < str.Length; i++)
{
if (!this.Dialog(str[i], ""))
{
this.errmsg = this.errmsg + this.enter;
this.errmsg = this.errmsg + errstr;
return false;
}
}
return true;
}
/// <summary>
/// 得到上传附件的文件流
/// </summary>
/// <param name="FilePath">附件的绝对路径</param>
/// <returns></returns>
private string GetStream(string FilePath)
{
FileStream stream = new FileStream(FilePath, FileMode.Open);
byte[] buffer = new byte[Convert.ToInt32(stream.Length)];
stream.Read(buffer, 0, buffer.Length);
stream.Close();
return Convert.ToBase64String(buffer);
}
/// <summary>
/// 接收SMTP服务器回应
/// </summary>
/// <returns></returns>
private string RecvResponse()
{
int length;
string text = "";
byte[] buffer = new byte[0x400];
try
{
length = this.ns.Read(buffer, 0, buffer.Length);
}
catch
{
this.errmsg = "网络连接错误";
return "false";
}
if (length != 0)
{
text = Encoding.Default.GetString(buffer).Substring(0, length);
this.logs = this.logs + text;
}
return text;
}
/// <summary>
/// 发送邮件方法,所有参数均通过属性设置。
/// </summary>
/// <returns></returns>
public bool Send()
{
if (this.Recipient.Count == 0)
{
this.errmsg = "收件人列表不能为空";
return false;
}
if (this.mailserver.Trim() == "")
{
this.errmsg = "必须指定SMTP服务器";
return false;
}
return this.SendEmail();
}
/// <summary>
/// 发送邮件方法
/// </summary>
/// <param name="smtpserver">smtp服务器信息,如"username:passwordwww.smtpserver.com:25",也可去掉部分次要信息,如www.smtpserver.com"</param>
/// <returns></returns>
public bool Send(string smtpserver)
{
this.MailDomain = smtpserver;
return this.Send();
}
/// <summary>
/// 发送邮件方法
/// </summary>
/// <param name="smtpserver">smtp服务器信息,如"username:passwordwww.smtpserver.com:25",也可去掉部分次要信息,如www.smtpserver.com"</param>
/// <param name="from">发件人mail地址</param>
/// <param name="fromname">发件人姓名</param>
/// <param name="to">收件人地址</param>
/// <param name="toname">收件人姓名</param>
/// <param name="html">是否HTML邮件</param>
/// <param name="subject">邮件主题</param>
/// <param name="body">邮件正文</param>
/// <returns></returns>
public bool Send(string smtpserver, string from, string fromname, string to, string toname, bool html, string subject, string body)
{
this.MailDomain = smtpserver;
this.From = from;
this.FromName = fromname;
this.AddRecipient(to);
this.RecipientName = toname;
this.Html = html;
this.Subject = subject;
this.Body = body;
return this.Send();
}
/// <summary>
/// 发送SMTP命令
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
private bool SendCommand(string str)
{
if ((str != null) && (str.Trim() != ""))
{
this.logs = this.logs + str;
byte[] bytes = Encoding.Default.GetBytes(str);
try
{
this.ns.Write(bytes, 0, bytes.Length);
}
catch
{
this.errmsg = "网络连接错误";
return false;
}
}
return true;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
private bool SendEmail()
{
string[] str;
string text;
string text3;
try
{
this.tc = new TcpClient(this.mailserver, this.mailserverport);
}
catch (Exception exception)
{
this.errmsg = exception.ToString();
return false;
}
this.ns = this.tc.GetStream();
this.SMTPCodeAdd();
if (this.RightCodeHT[this.RecvResponse().Substring(0, 3)] == null)
{
this.errmsg = "网络连接失败";
return false;
}
if (this.ESmtp)
{
str = new string[] { "EHLO " + this.mailserver + this.enter, "AUTH LOGIN" + this.enter, this.Base64Encode(this.username) + this.enter, this.Base64Encode(this.password) + this.enter };
if (!this.Dialog(str, "SMTP服务器验证失败,请核对用户名和密码。"))
{
return false;
}
}
else
{
text = "HELO " + this.mailserver + this.enter;
if (!this.Dialog(text, ""))
{
return false;
}
}
text = "MAIL FROM:<" + this.From + ">" + this.enter;
if (!this.Dialog(text, "发件人地址错误,或不能为空"))
{
return false;
}
str = new string[this.recipientmaxnum];
for (int i = 0; i < this.Recipient.Count; i++)
{
str[i] = "RCPT TO:<" + this.Recipient[i].ToString() + ">" + this.enter;
}
if (!this.Dialog(str, "收件人地址有误"))
{
return false;
}
text = "DATA" + this.enter;
if (!this.Dialog(text, ""))
{
return false;
}
object obj2 = "From:" + this.FromName + "<" + this.From + ">" + this.enter;
text = string.Concat(new object[] { obj2, "To:=?", this.Charset.ToUpper(), "?B?", this.Base64Encode(this.RecipientName), "?=<", this.Recipient[0], ">", this.enter }) + "CC:";
for (int j = 0; j < this.Recipient.Count; j++)
{
text3 = text;
text = text3 + this.Recipient[j].ToString() + "<" + this.Recipient[j].ToString() + ">,";
}
text = text + this.enter;
if (this.Charset == "")
{
text = text + "Subject:" + this.Subject + this.enter;
}
else
{
text3 = text;
text = text3 + "Subject:=?" + this.Charset.ToUpper() + "?B?" + this.Base64Encode(this.Subject) + "?=" + this.enter;
}
text = (((((((text + "X-Priority:" + this.priority + this.enter) + "X-MSMail-Priority:" + this.priority + this.enter) + "Importance:" + this.priority + this.enter) + "X-Mailer: Huolx.Pubclass" + this.enter) + "MIME-Version: 1.0" + this.enter) + "Content-Type: multipart/mixed;" + this.enter) + " boundary=/"----=_NextPart_000_00D6_01C29593.AAB31770/"" + this.enter) + "------=_NextPart_000_00D6_01C29593.AAB31770" + this.enter;
if (this.Html)
{
text = text + "Content-Type: text/html;" + this.enter;
}
else
{
text = text + "Content-Type: text/plain;" + this.enter;
}
if (this.Charset == "")
{
text = text + " charset=/"iso-8859-1/"" + this.enter;
}
else
{
text3 = text;
text = text3 + " charset=/"" + this.Charset.ToLower() + "/"" + this.enter;
}
text = (text + "Content-Transfer-Encoding: base64" + this.enter + this.enter) + this.Base64Encode(this.Body) + this.enter;
if (this.Attachments.Count != 0)
{
foreach (string text2 in this.Attachments)
{
text = text + "------=_NextPart_000_00D6_01C29593.AAB31770" + this.enter;
text = text + "Content-Type: application/octet-stream" + this.enter;
text3 = text;
text = text3 + " name=/"=?" + this.Charset.ToUpper() + "?B?" + this.Base64Encode(text2.Substring(text2.LastIndexOf(@"/") + 1)) + "?=/"" + this.enter;
text = text + "Content-Transfer-Encoding: base64" + this.enter;
text = text + "Content-Disposition: attachment;" + this.enter;
text3 = text;
text = text3 + " filename=/"=?" + this.Charset.ToUpper() + "?B?" + this.Base64Encode(text2.Substring(text2.LastIndexOf(@"/") + 1)) + "?=/"" + this.enter + this.enter;
text = text + this.GetStream(text2) + this.enter + this.enter;
}
}
text = (text + "------=_NextPart_000_00D6_01C29593.AAB31770--" + this.enter + this.enter) + this.enter + "." + this.enter;
if (!this.Dialog(text, "错误信件信息"))
{
return false;
}
text = "QUIT" + this.enter;
if (!this.Dialog(text, "断开连接时错误"))
{
return false;
}
this.ns.Close();
this.tc.Close();
return true;
}
/// <summary>
/// SMTP回应代码哈希表
/// </summary>
private void SMTPCodeAdd()
{
this.ErrCodeHT.Add("500", "邮箱地址错误");
this.ErrCodeHT.Add("501", "参数格式错误");
this.ErrCodeHT.Add("502", "命令不可实现");
this.ErrCodeHT.Add("503", "服务器需要SMTP验证");
this.ErrCodeHT.Add("504", "命令参数不可实现");
this.ErrCodeHT.Add("421", "服务未就绪,关闭传输信道");
this.ErrCodeHT.Add("450", "要求的邮件操作未完成,邮箱不可用(例如,邮箱忙)");
this.ErrCodeHT.Add("550", "要求的邮件操作未完成,邮箱不可用(例如,邮箱未找到,或不可访问)");
this.ErrCodeHT.Add("451", "放弃要求的操作;处理过程中出错");
this.ErrCodeHT.Add("551", "用户非本地,请尝试<forward-path>");
this.ErrCodeHT.Add("452", "系统存储不足,要求的操作未执行");
this.ErrCodeHT.Add("552", "过量的存储分配,要求的操作未执行");
this.ErrCodeHT.Add("553", "邮箱名不可用,要求的操作未执行(例如邮箱格式错误)");
this.ErrCodeHT.Add("432", "需要一个密码转换");
this.ErrCodeHT.Add("534", "认证机制过于简单");
this.ErrCodeHT.Add("538", "当前请求的认证机制需要加密");
this.ErrCodeHT.Add("454", "临时认证失败");
this.ErrCodeHT.Add("530", "需要认证");
this.RightCodeHT.Add("220", "服务就绪");
this.RightCodeHT.Add("250", "要求的邮件操作完成");
this.RightCodeHT.Add("251", "用户非本地,将转发向<forward-path>");
this.RightCodeHT.Add("354", "开始邮件输入,以.结束");
this.RightCodeHT.Add("221", "服务关闭传输信道");
this.RightCodeHT.Add("334", "服务器响应验证Base64字符串");
this.RightCodeHT.Add("235", "验证成功");
}
#endregion
#region // Properties
/// <summary>
/// 错误消息反馈
/// </summary>
public string ErrorMessage
{
get
{
return this.errmsg;
}
}
/// <summary>
/// 服务器交互记录,如发现本组件不能使用的SMTP服务器,请将出错时的Logs发给我(lion-a@sohu.com),我将尽快查明原因。
/// </summary>
public string Logs
{
get
{
return this.logs;
}
}
/// <summary>
/// 邮件服务器域名和验证信息形如:"user:paswww.server.com:25",也可省略次要信息。如"user:paswww.server.com"www.server.com"
/// </summary>
public string MailDomain
{
set
{
string text = value.Trim();
if (text != "")
{
int length = text.IndexOf("@");
if (length != -1)
{
string text2 = text.Substring(0, length);
this.MailServerUserName = text2.Substring(0, text2.IndexOf(":"));
this.MailServerPassWord = text2.Substring(text2.IndexOf(":") + 1, (text2.Length - text2.IndexOf(":")) - 1);
text = text.Substring(length + 1, (text.Length - length) - 1);
}
length = text.IndexOf(":");
if (length != -1)
{
this.mailserver = text.Substring(0, length);
this.mailserverport = Convert.ToInt32(text.Substring(length + 1, (text.Length - length) - 1));
}
else
{
this.mailserver = text;
}
}
}
}
/// <summary>
/// 邮件服务器端口号
/// </summary>
public int MailDomainPort
{
set
{
this.mailserverport = value;
}
}
/// <summary>
/// SMTP认证时使用的密码
/// </summary>
public string MailServerPassWord
{
set
{
this.password = value;
}
}
/// <summary>
/// SMTP认证时使用的用户名
/// </summary>
public string MailServerUserName
{
set
{
if (value.Trim() != "")
{
this.username = value.Trim();
this.ESmtp = true;
}
else
{
this.username = "";
this.ESmtp = false;
}
}
}
/// <summary>
/// 邮件发送优先级,可设置为"High","Normal","Low"或"1","3","5"
/// </summary>
public string Priority
{
set
{
switch (value.ToLower())
{
case "high":
this.priority = "High";
return;
case "1":
this.priority = "High";
return;
case "normal":
this.priority = "Normal";
return;
case "3":
this.priority = "Normal";
return;
case "low":
this.priority = "Low";
return;
case "5":
this.priority = "Low";
return;
}
this.priority = "Normal";
}
}
/// <summary>
/// 最多收件人数量
/// </summary>
public int RecipientMaxNum
{
set
{
this.recipientmaxnum = value;
}
}
#endregion
}
}