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];}
}
///
/// 添加邮件附件
///
/// 附件的绝对路径
public void Add(params string[] filePath)
{
if(filePath==null)
{
throw(new ArgumentNullException("非法的附件"));
}
else
{
for(int i=0;i
Add(filePath[i]);
}
}
}
///
/// 添加一个附件,当指定的附件不存在时,忽略该附件,不产生异常。
///
/// 附件的绝对路径
public void Add(string filePath)
{
//当附件存在时才加入,否则忽略
if (System.IO.File.Exists(filePath))
{
if (_Attachments.Count
_Attachments.Add(filePath);
}
}
}
public void Clear()//清除所有附件
{
_Attachments.Clear();
}
public int Count//获取附件个数
{
get { return _Attachments.Count;}
}
}
#endregion//end Class mailAttachments
#region Class MailMessage
///
/// MailMessage 表示SMTP要发送的一封邮件的消息。
///
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";
}
///
/// 设定语言代码,默认设定为GB2312,如不需要可设置为""
///
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;}
}
///
/// 增加一个收件人地址
///
/// 收件人的Email地址
public void AddRecipients(string recipient)
{
//先检查邮件地址是否符合规范
if (_Recipients.Count
_Recipients.Add(recipient);//增加到收件人列表
}
}
public void AddRecipients(params string[] recipient)
{
if (recipient==null)
{
throw (new ArgumentException("收件人不能为空."));
}
else
{
for (int i=0;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";//回车换行
///
/// 错误消息反馈
///
private string errmsg;
///
/// TcpClient对象,用于连接服务器
///
private TcpClient tcpClient;
///
/// NetworkStream对象
///
private NetworkStream networkStream;
///
/// 服务器交互记录
///
private string logs="";
///
/// SMTP错误代码哈希表
///
private Hashtable ErrCodeHT = new Hashtable();
///
/// SMTP正确代码哈希表
///
private Hashtable RightCodeHT = new Hashtable();
public SmtpServerHelper()
{
SMTPCodeAdd();//初始化SMTPCode
}
~SmtpServerHelper()
{
networkStream.Close();
tcpClient.Close();
}
///
/// 将字符串编码为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 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
221
250 Requested mail action okay, completed
251 User not local; will forward to
354 Start mail input; end with
421
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
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","用户非本地,请尝试
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
221
250 Requested mail action okay, completed
251 User not local; will forward to
354 Start mail input; end with
*/
RightCodeHT.Add("220","服务就绪");
RightCodeHT.Add("221","服务关闭传输信道");
RightCodeHT.Add("235","验证成功");
RightCodeHT.Add("250","要求的邮件操作完成");
RightCodeHT.Add("251","非本地用户,将转发向
RightCodeHT.Add("334","服务器响应验证Base64字符串");
RightCodeHT.Add("354","开始邮件输入,以
}
///
/// 发送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
{
networkStream.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=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;
}
}
///
/// 与服务器交互,发送一条命令并接收回应。
///
/// 一个要发送的命令
/// 如果错误,要反馈的信息
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;
}
}
///
/// 与服务器交互,发送一组命令并接收回应。
///
private bool Dialog(string[] str,string errstr)
{
for(int i=0;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;
}
///
/// 发送电子邮件,SMTP服务器不需要身份验证
///
///
///
///
///
public bool SendEmail(string smtpServer,int port,MailMessage mailMessage)
{
return SendEmail(smtpServer,port,false,"","",mailMessage);
}
///
/// 发送电子邮件,SMTP服务器需要身份验证
///
///
///
///
///
///
///
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
SendBuffer[i]="RCPT TO:<" +(string)mailMessage.Recipients[i] +">" + CRLF;
}
if(!Dialog(SendBuffer,"收件人地址有误"))
return false;
/*
SendBuffer=new string[10];
for(int i=0;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
// 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
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;
///
/// 格式:SmtpAccount:Password@SmtpServerAddress
/// 或者:SmtpServerAddress
///
/// SmtpMail.SmtpServer="user:12345678@smtp.126.com";
/// //或者:
/// SmtpMail.SmtpServer="smtp.126.com";
/// 或者:
/// SmtpMail.SmtpServer=SmtpServerHelper.GetSmtpServer("user","12345678","smtp.126.com");
///
///
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
{
///
/// Test 的摘要说明。
///
[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,"","");//请填写自己的测试邮件帐号
}
}
}
相关视频
相关阅读 Windows错误代码大全 Windows错误代码查询激活windows有什么用Mac QQ和Windows QQ聊天记录怎么合并 Mac QQ和Windows QQ聊天记录Windows 10自动更新怎么关闭 如何关闭Windows 10自动更新windows 10 rs4快速预览版17017下载错误问题Win10秋季创意者更新16291更新了什么 win10 16291更新内容windows10秋季创意者更新时间 windows10秋季创意者更新内容kb3150513补丁更新了什么 Windows 10补丁kb3150513是什么
热门文章 360快剪辑怎么使用 36金山词霸如何屏幕取词百度收购PPS已敲定!3
最新文章
微信3.6.0测试版更新了微信支付漏洞会造成哪
360快剪辑怎么使用 360快剪辑软件使用方法介酷骑单车是什么 酷骑单车有什么用Apple pay与支付宝有什么区别 Apple pay与贝贝特卖是正品吗 贝贝特卖网可靠吗
人气排行 xp系统停止服务怎么办?xp系统升级win7系统方电脑闹钟怎么设置 win7电脑闹钟怎么设置office2013安装教程图解:手把手教你安装与qq影音闪退怎么办 QQ影音闪退解决方法VeryCD镜像网站逐个数,电驴资料库全集同步推是什么?同步推使用方法介绍QQ2012什么时候出 最新版下载EDiary——一款好用的电子日记本
查看所有0条评论>>