欢迎光临
我们一直在努力

C#实现SMTP服务器,使用TCP命令实现,功能比较完善-.NET教程,C#语言

建站超值云服务器,限时71元/月

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,"","");//请填写自己的测试邮件帐号

}

}

}

赞(0)
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com 特别注意:本站所有转载文章言论不代表本站观点! 本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。未经允许不得转载:IDC资讯中心 » C#实现SMTP服务器,使用TCP命令实现,功能比较完善-.NET教程,C#语言
分享到: 更多 (0)

相关推荐

  • 暂无文章