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==nullstr.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==nullstr.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,"","");//请填写自己的测试邮件帐号
}
}
}
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器