欢迎光临
我们一直在努力

对“[原创]EMAIL发送系统(C#+基于SMTP认证)”的改写-.NET教程,C#语言

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

在为公司写通知服务时,从网上找到了以上地址,非常感谢原作者创造性的劳动。改写的目的是为了适应作为服务运行的要求:

1、适应多线程的要求,发送邮件服务可在后台运行,将与smtp服务器的连接视为独占资源。

2、适应稳定性的要求,不再以简单地抛出异常来处理错误,在出现异常后等待一定时间间隔后重试,重试一段时间间隔后若还时发不出去,则认为是smtp出错,返回发送邮件不成功的标识。

3、精简属性、方法,与邮件相关的信息不再作为属性,而是作为send的参数传入;只公布了一个无重载的send方法。以此类为基类,另写通知服务要求的接口方法。

以下是改写后的代码:

using system;

using system.text;

using system.io;

using system.net;

using system.net.sockets;

using system.collections;

using system.threading;

namespace deep.sendemail

{

#region aspnetpager server control

/// <summary>

/// 邮件可以通过 microsoft windows 2000 中内置的 smtp 邮件服务或任意 smtp 服务器来传送

/// </summary>

public class smtpmail

{

private const string enter="\r\n";

/// <summary>

/// 设定语言代码,默认设定为gb2312,如不需要可设置为""

/// </summary>

private string m_charset="gb2312";

/// <summary>

/// 服务器交互记录

/// </summary>

private stringbuilder m_logs = new stringbuilder();

private string m_errcode;

/// <summary>

/// smtp错误代码哈希表

/// </summary>

private hashtable m_errcodeht = new hashtable();

/// <summary>

/// smtp正确代码哈希表

/// </summary>

private hashtable m_rightcodeht = new hashtable();

/// <summary>

/// 最多收件人数量

/// </summary>

private int m_recipientmaxnum = 2;

/// <summary>

/// 重复时间,以秒为单位

/// </summary>

private int m_repeattime = 120;

/// <summary>

/// 服务器出错或拒绝后的等待时间,以毫秒为单位

/// </summary>

private int m_waittime = 20000;

/// <summary>

/// 初始化 <see cref="lion.web.mail.smtpmail"/> 类的新实例

/// </summary>

public smtpmail()

{

smtpcodeadd();

}

#region properties 定义属性

/// <summary>

/// 服务器交互记录,如发现本组件不能使用的smtp服务器,请将出错时的logs发给我(lion-a@sohu.com),我将尽快查明原因。

/// </summary>

public string logs

{

get

{

return m_logs.tostring();

}

}

/// <summary>

/// 最多收件人数量

/// </summary>

public int recipientmaxnum

{

set

{

m_recipientmaxnum = value;

}

get

{

return m_recipientmaxnum;

}

}

/// <summary>

/// 设定语言代码,默认设定为gb2312,如不需要可设置为""

/// </summary>

public string charset

{

get

{

return this.m_charset;

}

set

{

this.m_charset = value;

}

}

/// <summary>

/// 重复时间,以秒为单位

/// </summary>

public int repeattime

{

get {return m_repeattime;}

set {m_repeattime = value;}

}

/// <summary>

/// 服务器出错或拒绝后的等待时间,以毫秒为单位

/// </summary>

public int waittime

{

get {return m_waittime;}

set {m_waittime = value > 10000?value:10000;}

}

#endregion

#region methods 定义方法

/// <summary>

/// 邮件服务器域名和验证信息

/// 形如:"user:pass@www.server.com:25",也可省略次要信息。如"user:pass@www.server.com"或"www.server.com"

/// </summary>

/// <param name="maildomain">输入用户名、密码、邮件服务器域名、端口号</param>

/// <param name="mailserver">返回邮件服务器域名</param>

/// <param name="mailserverusername">返回用户名</param>

/// <param name="password">返回密码</param>

/// <param name="mailserverport">返回端口号</param>

/// <param name="needsmtp">返回是否需要smtp验证</param>

/// <returns></returns>

private bool setmaildomain(string maildomain,out string mailserver,out string mailserverusername,out string password,

out int mailserverport,out bool needsmtp)

{

bool isright = false;

//为输出变量赋初值

mailserver = string.empty;

mailserverusername = string.empty;

password = string.empty;

mailserverport = 25;

needsmtp = false;

mailserver = maildomain.trim();

int tempint;

if( mailserver != "" )

{

tempint = mailserver.indexof("@");

isright = true;

if(tempint!=-1)

{

string str = mailserver.substring(0,tempint);

mailserverusername = str.substring(0,str.indexof(":"));

password = str.substring(str.indexof(":")+1,str.length-str.indexof(":")-1);

needsmtp = !(password==string.empty);

mailserver = maildomain.substring(tempint+1,maildomain.length-tempint-1);

}

tempint = mailserver.indexof(":");

if(tempint != -1)

{

mailserverport = system.convert.toint32(mailserver.substring(tempint+1,mailserver.length-tempint-1));

mailserver = mailserver.substring(0,tempint);

}

}

return isright;

}

/// <summary>

/// 添加邮件附件

/// </summary>

/// <param name="filepath">附件绝对路径</param>

private ilist addattachment(params string[] filepath)

{

if(filepath == null || filepath.length == 0)

{

return null;

}

ilist m_attachments = new system.collections.arraylist();// 邮件附件列表

for(int i=0;i<filepath.length;i++)

{

if(file.exists(filepath[i]))

{

m_attachments.add(filepath[i]);

}

else

{

m_logs.append("错误:没找到文件名为"+filepath[i]+"的附件文件!"+enter);

}

}

return m_attachments;

}

/// <summary>

/// 添加一组收件人(不超过m_recipientmaxnum个),参数为字符串数组

/// </summary>

/// <param name="recipients">保存有收件人地址的字符串数组(不超过m_recipientmaxnum个)</param>

private hashtable addrecipient(params string[] recipients)

{

if(recipients==null || recipients.length == 0)

{

return null;

}

hashtable recipientlist=new hashtable();// 收件人列表

for(int i=0;i<recipients.length;i++)

{

string recipient = recipients[i].trim();

if(recipient !=string.empty && recipient.indexof("@") != -1)

{

recipientlist.add(recipientlist.count,recipients[i]);

}

}

return recipientlist;

}

/// <summary>

/// 发送邮件方法

/// </summary>

/// <param name="smtpserver">smtp服务器信息,如"username:password@www.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>

/// <param name="filepath">邮件附件列表</param>

public bool send(string smtpserver,string from,string fromname,string[] recipientadd,string recipientname,bool ishtml,string subject,priority priority, string body,string[] filepath)

{

//如果收件人多于服务器可同时发送的最大值,则分多次发送

if(recipientadd.length > recipientmaxnum)

{

string[] recipientadd1 = new string[recipientmaxnum];

string[] recipientadd2 = new string[recipientadd.length – recipientmaxnum];

for(int i = 0;i < recipientadd.length; i++)

{

if(i < recipientmaxnum)

{

recipientadd1[i] = recipientadd[i];

}

else

{

recipientadd2[i – recipientmaxnum] = recipientadd[i];

}

}

return send(smtpserver,from,fromname,recipientadd1,recipientname,ishtml,subject,priority, body,filepath)

&&

send(smtpserver,from,fromname,recipientadd2,recipientname,ishtml,subject,priority, body,filepath);

}

if(m_logs.length > 2048)

{

m_logs.remove(0,m_logs.length);

}

string mailserver="";// 邮件服务器域名

int mailserverport=25;// 邮件服务器端口号

string username="";// smtp认证时使用的用户名

string password="";// smtp认证时使用的密码

bool needsmtp=false;// 是否需要smtp验证

setmaildomain(smtpserver,out mailserver,out username,out password,

out mailserverport,out needsmtp);

if(mailserver.trim()=="")

{

m_logs.append("必须指定smtp服务器"+enter);

return false;

}

ilist attachments = addattachment(filepath);// 邮件附件列表

hashtable recipients = addrecipient(recipientadd);// 收件人列表

if(recipients == null || recipients.count == 0 )

{

m_logs.append("必须指定收件人"+enter);

return false;

}

if(recipients.count > recipientmaxnum)

{

m_logs.append("一次发送的收件人太多"+enter);

return false;

}

bool issuccessful = false;

lock(this)

{

tcpclient tcpclientobject = null;// tcpclient对象,用于连接服务器

networkstream networkstreamobject = null;// networkstream对象

datetime datetimebegin = datetime.now;

int usetime = 0;

while(! ( usetime > repeattime || issuccessful))

{

try

{

tcpclientobject=new tcpclient(mailserver,mailserverport);

networkstreamobject = tcpclientobject.getstream();

issuccessful =sendemail(networkstreamobject,needsmtp,mailserver,username,password,recipients,from,

fromname,recipientname,subject,priority.tostring(),attachments, ishtml, body);

}

catch(exception e)

{

m_logs.append("错误:"+e.message+enter);

}

finally

{

if(networkstreamobject!=null)networkstreamobject.close();

if(tcpclientobject!=null)tcpclientobject.close();

if(!issuccessful)

{

string n = thread.currentthread.name;

thread.sleep(waittime);

}

usetime = ((timespan)(datetime.now – datetimebegin)).seconds;

}

}

}

return issuccessful;

}

#endregion

#region private helper functions

/// <summary>

/// smtp回应代码哈希表

/// </summary>

private void smtpcodeadd()

{

m_errcodeht.add("500","邮箱地址错误");

m_errcodeht.add("501","参数格式错误");

m_errcodeht.add("502","命令不可实现");

m_errcodeht.add("503","服务器需要smtp验证");

m_errcodeht.add("504","命令参数不可实现");

m_errcodeht.add("421","服务未就绪,关闭传输信道");

m_errcodeht.add("450","要求的邮件操作未完成,邮箱不可用(例如,邮箱忙)");

m_errcodeht.add("550","要求的邮件操作未完成,邮箱不可用(例如,邮箱未找到,或不可访问)");

m_errcodeht.add("451","放弃要求的操作;处理过程中出错");

m_errcodeht.add("551","用户非本地,请尝试<forward-path>");

m_errcodeht.add("452","系统存储不足,要求的操作未执行");

m_errcodeht.add("552","过量的存储分配,要求的操作未执行");

m_errcodeht.add("553","邮箱名不可用,要求的操作未执行(例如邮箱格式错误)");

m_errcodeht.add("432","需要一个密码转换");

m_errcodeht.add("534","认证机制过于简单");

m_errcodeht.add("538","当前请求的认证机制需要加密");

m_errcodeht.add("454","临时认证失败");

m_errcodeht.add("530","需要认证");

m_rightcodeht.add("220","服务就绪");

m_rightcodeht.add("250","要求的邮件操作完成");

m_rightcodeht.add("251","用户非本地,将转发向<forward-path>");

m_rightcodeht.add("354","开始邮件输入,以<enter>.<enter>结束");

m_rightcodeht.add("221","服务关闭传输信道");

m_rightcodeht.add("334","服务器响应验证base64字符串");

m_rightcodeht.add("235","验证成功");

}

/// <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)

{

byte[] by = null;

system.io.filestream filestr = null;

string streamstring = "";

try

{

//建立文件流对象

filestr=new system.io.filestream(filepath,system.io.filemode.open);

by=new byte[system.convert.toint32(filestr.length)];

filestr.read(by,0,by.length);

streamstring = system.convert.tobase64string(by);

}

catch(exception ex)

{

//写错误日志

m_logs.append("错误:"+ex.message+enter);

}

finally

{

if(filestr != null)

{

filestr.close();

}

}

return streamstring;

}

/// <summary>

/// 发送smtp命令

/// </summary>

private bool sendcommand(string str,networkstream _networkstreamobject)

{

byte[] writebuffer;

if(str==null||str.trim()==string.empty)

{

return true;

}

m_logs.append(str+enter);

writebuffer = encoding.default.getbytes(str);

try

{

_networkstreamobject.write(writebuffer,0,writebuffer.length);

}

catch(exception ex)

{

//写日志

m_logs.append("错误:"+ex.message+enter);

return false;

}

return true;

}

/// <summary>

/// 接收smtp服务器回应

/// </summary>

private string recvresponse(networkstream _networkstreamobject)

{

int streamsize = 0;

string returnvalue = string.empty;

byte[] readbuffer = new byte[1024] ;

try

{

streamsize = _networkstreamobject.read(readbuffer,0,readbuffer.length);

}

catch(exception ex)

{

//写日志

m_logs.append("错误:"+ex.message+enter);

m_errcode = ex.message;

return "false";

}

if (streamsize==0)

{

return returnvalue ;

}

else

{

returnvalue = encoding.default.getstring(readbuffer).substring(0,streamsize);

m_logs.append(returnvalue+enter);

return returnvalue;

}

}

/// <summary>

/// 与服务器交互,发送一条命令并接收回应。

/// </summary>

/// <param name="str">一个要发送的命令</param>

private bool dialog(string str,networkstream _networkstream)

{

if(str==null||str.trim()=="")

{

return true;

}

if(sendcommand(str,_networkstream))

{

string rr=recvresponse(_networkstream);

if(rr=="false")

{

return false;

}

string rrcode=rr.substring(0,3);

if(m_rightcodeht[rrcode]!=null)

{

return true;

}

else

{

m_errcode = rrcode;

return false;

}

}

else

{

return false;

}

}

/// <summary>

/// 与服务器交互,发送一组命令并接收回应。

/// </summary>

private bool dialog(string[] str,networkstream _networkstream)

{

for(int i=0;i<str.length;i++)

{

if(!dialog(str[i],_networkstream))

{

return false;

}

}

return true;

}

/// <summary>

/// sendemail

/// </summary>

/// <returns></returns>

private bool sendemail(networkstream _networkstream,bool needsmtp,string mailserver,string username,string password,hashtable recipients,string from,

string fromname,string recipientname,string subject,string priority,ilist attachments,bool ishtml,

string body)

{

//验证网络连接是否正确

if(m_rightcodeht[recvresponse(_networkstream).substring(0,3)]==null)

{

return false;

}

string[] sendbuffer;

string sendbufferstr;

stringbuilder sendbufferstrbuilder = new stringbuilder();

//进行smtp验证

if(needsmtp)

{

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,_networkstream))

{

return false;

}

}

else

{

sendbufferstr="helo " + mailserver + enter;

if(!dialog(sendbufferstr,_networkstream))

return false;

}

//

sendbufferstr="mail from:<" + from + ">" + enter;

if(!dialog(sendbufferstr,_networkstream))

return false;

//

sendbuffer=new string[m_recipientmaxnum];

for(int i=0;i<recipients.count;i++)

{

sendbuffer[i]="rcpt to:<" + recipients[i].tostring() +">" + enter;

}

if(!dialog(sendbuffer,_networkstream))

return false;

sendbufferstr="data" + enter;

if(!dialog(sendbufferstr,_networkstream))

return false;

sendbufferstrbuilder.append("from:" + fromname + "<" + from +">" +enter);

sendbufferstrbuilder.append("to:=?"+charset.toupper()+"?b?"+base64encode(recipientname)+"?="+"<"+recipients[0]+">"+enter);

sendbufferstrbuilder.append("cc:");

for(int i=0;i<recipients.count;i++)

{

sendbufferstrbuilder.append(recipients[i].tostring() + "<" + recipients[i].tostring() +">,");

}

sendbufferstrbuilder.append(enter);

sendbufferstrbuilder.append(((subject==string.empty || subject==null)?"subject:":((charset=="")?("subject:" + subject):("subject:" + "=?" + charset.toupper() + "?b?" + base64encode(subject) +"?="))) + enter);

sendbufferstrbuilder.append("x-priority:" + priority + enter);

sendbufferstrbuilder.append("x-msmail-priority:" + priority + enter);

sendbufferstrbuilder.append("importance:" + priority + enter);

sendbufferstrbuilder.append("x-mailer: lion.web.mail.smtpmail pubclass [cn]" + enter);

sendbufferstrbuilder.append("mime-version: 1.0" + enter);

if(attachments != null && attachments.count!=0)

{

sendbufferstrbuilder.append("content-type: multipart/mixed;" + enter);

sendbufferstrbuilder.append(" boundary=\"====="+(ishtml?"001_dragon520636771063_":"001_dragon303406132050_")+"=====\""+enter+enter);

}

if(ishtml)

{

if(attachments != null && attachments.count==0)

{

sendbufferstrbuilder.append("content-type: multipart/alternative;"+enter);//内容格式和分隔符

sendbufferstrbuilder.append(" boundary=\"=====003_dragon520636771063_=====\""+enter+enter);

sendbufferstrbuilder.append("this is a multi-part message in mime format."+enter+enter);

}

else

{

sendbufferstrbuilder.append("this is a multi-part message in mime format."+enter+enter);

sendbufferstrbuilder.append("–=====001_dragon520636771063_====="+enter);

sendbufferstrbuilder.append("content-type: multipart/alternative;"+enter);//内容格式和分隔符

sendbufferstrbuilder.append(" boundary=\"=====003_dragon520636771063_=====\""+enter+enter);

}

sendbufferstrbuilder.append("–=====003_dragon520636771063_====="+enter);

sendbufferstrbuilder.append("content-type: text/plain;"+ enter);

sendbufferstrbuilder.append(((charset=="")?(" charset=\"iso-8859-1\""):(" charset=\"" + charset.tolower() + "\"")) + enter);

sendbufferstrbuilder.append("content-transfer-encoding: base64" + enter + enter);

sendbufferstrbuilder.append(base64encode("邮件内容为html格式,请选择html方式查看") + enter + enter);

sendbufferstrbuilder.append("–=====003_dragon520636771063_====="+enter);

sendbufferstrbuilder.append("content-type: text/html;" + enter);

sendbufferstrbuilder.append(((charset=="")?(" charset=\"iso-8859-1\""):(" charset=\"" + charset.tolower() + "\"")) + enter);

sendbufferstrbuilder.append("content-transfer-encoding: base64" + enter + enter);

sendbufferstrbuilder.append(base64encode(body) + enter + enter);

sendbufferstrbuilder.append("–=====003_dragon520636771063_=====–"+enter);

}

else

{

if(attachments != null && attachments.count!=0)

{

sendbufferstrbuilder.append("–=====001_dragon303406132050_====="+enter);

}

sendbufferstrbuilder.append("content-type: text/plain;" + enter);

sendbufferstrbuilder.append(((charset=="")?(" charset=\"iso-8859-1\""):(" charset=\"" + charset.tolower() + "\"")) + enter);

sendbufferstrbuilder.append("content-transfer-encoding: base64" + enter + enter);

sendbufferstrbuilder.append(base64encode(body) + enter);

}

//sendbufferstr += "content-transfer-encoding: base64"+enter;

if(attachments != null && attachments.count!=0)

{

for(int i=0;i<attachments.count;i++)

{

string filepath = (string)attachments[i];

sendbufferstrbuilder.append("–====="+ (ishtml?"001_dragon520636771063_":"001_dragon303406132050_") +"====="+enter);

//sendbufferstr += "content-type: application/octet-stream"+enter;

sendbufferstrbuilder.append("content-type: text/plain;"+enter);

sendbufferstrbuilder.append(" name=\"=?"+charset.toupper()+"?b?"+base64encode(filepath.substring(filepath.lastindexof("\\")+1))+"?=\""+enter);

sendbufferstrbuilder.append("content-transfer-encoding: base64"+enter);

sendbufferstrbuilder.append("content-disposition: attachment;"+enter);

sendbufferstrbuilder.append(" filename=\"=?"+charset.toupper()+"?b?"+base64encode(filepath.substring(filepath.lastindexof("\\")+1))+"?=\""+enter+enter);

sendbufferstrbuilder.append(getstream(filepath)+enter+enter);

}

sendbufferstrbuilder.append("–====="+ (ishtml?"001_dragon520636771063_":"001_dragon303406132050_") +"=====–"+enter+enter);

}

sendbufferstrbuilder.append(enter + "." + enter);

sendbufferstr = sendbufferstrbuilder.tostring();

if(!dialog(sendbufferstr,_networkstream))

return false;

sendbufferstr="quit" + enter;

if(!dialog(sendbufferstr,_networkstream))

return false;

return true;

}

#endregion

#region

/*

/// <summary>

/// 添加一个密件收件人

/// </summary>

/// <param name="str">收件人地址</param>

public bool addrecipientbcc(string str)

{

if(str==null||str.trim()=="")

return true;

if(recipientbccnum<10)

{

recipientbcc.add(recipientbccnum,str);

recipientbccnum++;

return true;

}

else

{

m_logs.append("错误:收件人过多");

return false;

}

}

/// <summary>

/// 添加一组密件收件人(不超过10个),参数为字符串数组

/// </summary>

/// <param name="str">保存有收件人地址的字符串数组(不超过10个)</param>

public bool addrecipientbcc(string[] str)

{

for(int i=0;i<str.length;i++)

{

if(!addrecipientbcc(str[i]))

{

return false;

}

}

return true;

}

*/

#endregion

}

/// <summary>

/// 邮件发送优先级

/// </summary>

public enum priority

{

high,

normal,

low

}

#endregion

}

赞(0)
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com 特别注意:本站所有转载文章言论不代表本站观点! 本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。未经允许不得转载:IDC资讯中心 » 对“[原创]EMAIL发送系统(C#+基于SMTP认证)”的改写-.NET教程,C#语言
分享到: 更多 (0)