这个是对于
[原创]EMAIL发送系统(C#+基于SMTP认证)
http://www.lionsky.net/MyWebsite/article/list.aspx?id=430
的改版
在为公司写通知服务时,从网上找到了以上地址,非常感谢原作者创造性的劳动。改写的目的是为了适应作为服务运行的要求:
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
///
1<summary>
2/// 邮件可以通过 Microsoft Windows 2000 中内置的 SMTP 邮件服务或任意 SMTP 服务器来传送
3/// </summary>
public class SmtpMail
{
private const string ENTER="\r\n";
///
1<summary>
2/// 设定语言代码,默认设定为GB2312,如不需要可设置为""
3/// </summary>
private string m_charset="GB2312";
///
1<summary>
2/// 服务器交互记录
3/// </summary>
private StringBuilder m_logs = new StringBuilder();
private string m_ErrCode;
///
1<summary>
2/// SMTP错误代码哈希表
3/// </summary>
private Hashtable m_ErrCodeHT = new Hashtable();
///
1<summary>
2/// SMTP正确代码哈希表
3/// </summary>
private Hashtable m_RightCodeHT = new Hashtable();
///
1<summary>
2/// 最多收件人数量
3/// </summary>
private int m_recipientMaxnum = 2;
///
1<summary>
2/// 重复时间,以秒为单位
3/// </summary>
private int m_RepeatTime = 120;
///
1<summary>
2/// 服务器出错或拒绝后的等待时间,以毫秒为单位
3/// </summary>
private int m_WaitTime = 20000;
///
1<summary>
2/// 初始化 <see cref="Lion.Web.Mail.SmtpMail"></see> 类的新实例
3/// </summary>
public SmtpMail()
{
SMTPCodeAdd();
}
#region Properties 定义属性
///
1<summary>
2/// 服务器交互记录,如发现本组件不能使用的SMTP服务器,请将出错时的Logs发给我( [email protected] ),我将尽快查明原因。
3/// </summary>
public string Logs
{
get
{
return m_logs.ToString();
}
}
///
1<summary>
2/// 最多收件人数量
3/// </summary>
public int RecipientMaxNum
{
set
{
m_recipientMaxnum = value;
}
get
{
return m_recipientMaxnum;
}
}
///
1<summary>
2/// 设定语言代码,默认设定为GB2312,如不需要可设置为""
3/// </summary>
public string Charset
{
get
{
return this.m_charset;
}
set
{
this.m_charset = value;
}
}
///
1<summary>
2/// 重复时间,以秒为单位
3/// </summary>
public int RepeatTime
{
get {return m_RepeatTime;}
set {m_RepeatTime = value;}
}
///
1<summary>
2/// 服务器出错或拒绝后的等待时间,以毫秒为单位
3/// </summary>
public int WaitTime
{
get {return m_WaitTime;}
set {m_WaitTime = value > 10000?value:10000;}
}
#endregion
#region Methods 定义方法
///
1<summary>
2/// 邮件服务器域名和验证信息
3/// 形如:"user:[email protected]:25",也可省略次要信息。如"user:[email protected]"或" www.server.com "
4/// </summary>
///
1<param name="mailDomain"/>
输入用户名、密码、邮件服务器域名、端口号
///
1<param name="mailServer"/>
返回邮件服务器域名
///
1<param name="mailServerUserName"/>
返回用户名
///
1<param name="password"/>
返回密码
///
1<param name="mailserverport"/>
返回端口号
///
1<param name="needSmtp"/>
返回是否需要SMTP验证
///
1<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;
}
///
1<summary>
2/// 添加邮件附件
3/// </summary>
///
1<param name="filePath"/>
附件绝对路径
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
1<filepath.length;i++) <summary="" else="" if(file.exists(filepath[i]))="" m_attachments.add(filepath[i]);="" m_attachments;="" m_logs.append("错误:没找到文件名为"+filepath[i]+"的附件文件!"+enter);="" return="" {="" }="">
2/// 添加一组收件人(不超过m_recipientMaxnum个),参数为字符串数组
3///
4/// <param name="recipients"/>保存有收件人地址的字符串数组(不超过m_recipientMaxnum个)
5private Hashtable AddRecipient(params string[] recipients)
6{
7if(recipients==null || recipients.Length == 0)
8{
9return null;
10}
11Hashtable recipientList=new Hashtable();// 收件人列表
12
13for(int i=0;i<recipients.length;i++) !="-1)" &&="" <summary="" if(recipient="" recipient="recipients[i].Trim();" recipient.indexof("@")="" recipientlist.add(recipientlist.count,recipients[i]);="" recipientlist;="" return="" string="" {="" }="">
14/// 发送邮件方法
15///
16/// <param name="smtpServer"/>smtp服务器信息,如"username:[email protected]:25",也可去掉部分次要信息,如" www.smtpServer.com"
17/// <param name="from"/>发件人mail地址
18/// <param name="fromname"/>发件人姓名
19/// <param name="to"/>收件人地址列表
20/// <param name="toname"/>收件人姓名
21/// <param name="html"/>是否HTML邮件
22/// <param name="subject"/>邮件主题
23/// <param name="body"/>邮件正文
24/// <param name="filePath"/>邮件附件列表
25public bool Send(string smtpServer,string from,string fromName,string[] recipientADD,string recipientName,bool isHtml,string subject,Priority priority, string body,string[] filePath)
26{
27//如果收件人多于服务器可同时发送的最大值,则分多次发送
28if(recipientADD.Length > RecipientMaxNum)
29{
30string[] recipientADD1 = new string[RecipientMaxNum];
31string[] recipientADD2 = new string[recipientADD.Length - RecipientMaxNum];
32for(int i = 0;i < recipientADD.Length; i++)
33{
34if(i < RecipientMaxNum)
35{
36recipientADD1[i] = recipientADD[i];
37}
38else
39{
40recipientADD2[i - RecipientMaxNum] = recipientADD[i];
41}
42}
43return Send(smtpServer,from,fromName,recipientADD1,recipientName,isHtml,subject,priority, body,filePath)
44&&
45Send(smtpServer,from,fromName,recipientADD2,recipientName,isHtml,subject,priority, body,filePath);
46}
47
48if(m_logs.Length > 2048)
49{
50m_logs.Remove(0,m_logs.Length);
51}
52
53string mailServer="";// 邮件服务器域名
54int mailserverport=25;// 邮件服务器端口号
55string userName="";// SMTP认证时使用的用户名
56string password="";// SMTP认证时使用的密码
57bool needSmtp=false;// 是否需要SMTP验证
58SetMailDomain(smtpServer,out mailServer,out userName,out password,
59out mailserverport,out needSmtp);
60if(mailServer.Trim()=="")
61{
62m_logs.Append("必须指定SMTP服务器"+ENTER);
63return false;
64}
65IList attachments = AddAttachment(filePath);// 邮件附件列表
66Hashtable recipients = AddRecipient(recipientADD);// 收件人列表
67if(recipients == null || recipients.Count == 0 )
68{
69m_logs.Append("必须指定收件人"+ENTER);
70return false;
71}
72if(recipients.Count > RecipientMaxNum)
73{
74m_logs.Append("一次发送的收件人太多"+ENTER);
75return false;
76}
77bool isSuccessful = false;
78lock(this)
79{
80TcpClient tcpClientObject = null;// TcpClient对象,用于连接服务器
81NetworkStream networkStreamObject = null;// NetworkStream对象
82DateTime dateTimeBegin = DateTime.Now;
83int useTime = 0;
84while(! ( useTime > RepeatTime || isSuccessful))
85{
86try
87{
88tcpClientObject=new TcpClient(mailServer,mailserverport);
89networkStreamObject = tcpClientObject.GetStream();
90isSuccessful =SendEmail(networkStreamObject,needSmtp,mailServer,userName,password,recipients,from,
91fromName,recipientName,subject,priority.ToString(),attachments, isHtml, body);
92}
93catch(Exception e)
94{
95m_logs.Append("错误:"+e.Message+ENTER);
96}
97finally
98{
99if(networkStreamObject!=null)networkStreamObject.Close();
100if(tcpClientObject!=null)tcpClientObject.Close();
101if(!isSuccessful)
102{
103string n = Thread.CurrentThread.Name;
104Thread.Sleep(WaitTime);
105}
106useTime = ((TimeSpan)(DateTime.Now - dateTimeBegin)).Seconds;
107}
108}
109}
110return isSuccessful;
111}
112
113
114#endregion
115
116#region Private Helper Functions
117
118
119/// <summary>
120/// SMTP回应代码哈希表
121/// </summary>
122private void SMTPCodeAdd()
123{
124m_ErrCodeHT.Add("500","邮箱地址错误");
125m_ErrCodeHT.Add("501","参数格式错误");
126m_ErrCodeHT.Add("502","命令不可实现");
127m_ErrCodeHT.Add("503","服务器需要SMTP验证");
128m_ErrCodeHT.Add("504","命令参数不可实现");
129m_ErrCodeHT.Add("421","服务未就绪,关闭传输信道");
130m_ErrCodeHT.Add("450","要求的邮件操作未完成,邮箱不可用(例如,邮箱忙)");
131m_ErrCodeHT.Add("550","要求的邮件操作未完成,邮箱不可用(例如,邮箱未找到,或不可访问)");
132m_ErrCodeHT.Add("451","放弃要求的操作;处理过程中出错");
133m_ErrCodeHT.Add("551","用户非本地,请尝试<forward-path>");
134m_ErrCodeHT.Add("452","系统存储不足,要求的操作未执行");
135m_ErrCodeHT.Add("552","过量的存储分配,要求的操作未执行");
136m_ErrCodeHT.Add("553","邮箱名不可用,要求的操作未执行(例如邮箱格式错误)");
137m_ErrCodeHT.Add("432","需要一个密码转换");
138m_ErrCodeHT.Add("534","认证机制过于简单");
139m_ErrCodeHT.Add("538","当前请求的认证机制需要加密");
140m_ErrCodeHT.Add("454","临时认证失败");
141m_ErrCodeHT.Add("530","需要认证");
142
143m_RightCodeHT.Add("220","服务就绪");
144m_RightCodeHT.Add("250","要求的邮件操作完成");
145m_RightCodeHT.Add("251","用户非本地,将转发向<forward-path>");
146m_RightCodeHT.Add("354","开始邮件输入,以<enter>.<enter>结束");
147m_RightCodeHT.Add("221","服务关闭传输信道");
148m_RightCodeHT.Add("334","服务器响应验证Base64字符串");
149m_RightCodeHT.Add("235","验证成功");
150}
151
152
153/// <summary>
154/// 将字符串编码为Base64字符串
155/// </summary>
156/// <param name="str"/>要编码的字符串
157private string Base64Encode(string str)
158{
159byte[] barray;
160barray=Encoding.Default.GetBytes(str);
161return Convert.ToBase64String(barray);
162}
163
164
165/// <summary>
166/// 将Base64字符串解码为普通字符串
167/// </summary>
168/// <param name="str"/>要解码的字符串
169private string Base64Decode(string str)
170{
171byte[] barray;
172barray=Convert.FromBase64String(str);
173return Encoding.Default.GetString(barray);
174}
175
176
177/// <summary>
178/// 得到上传附件的文件流
179/// </summary>
180/// <param name="filePath"/>附件的绝对路径
181private string GetStream(string filePath)
182{
183byte[] by = null;
184System.IO.FileStream FileStr = null;
185string streamString = "";
186try
187{
188//建立文件流对象
189FileStr=new System.IO.FileStream(filePath,System.IO.FileMode.Open);
190by=new byte[System.Convert.ToInt32(FileStr.Length)];
191FileStr.Read(by,0,by.Length);
192streamString = System.Convert.ToBase64String(by);
193}
194catch(Exception ex)
195{
196//写错误日志
197m_logs.Append("错误:"+ex.Message+ENTER);
198}
199finally
200{
201if(FileStr != null)
202{
203FileStr.Close();
204}
205}
206
207return streamString;
208}
209
210/// <summary>
211/// 发送SMTP命令
212/// </summary>
213private bool SendCommand(string str,NetworkStream _NetworkStreamObject)
214{
215byte[] WriteBuffer;
216if(str==null||str.Trim()==String.Empty)
217{
218return true;
219}
220m_logs.Append(str+ENTER);
221WriteBuffer = Encoding.Default.GetBytes(str);
222try
223{
224_NetworkStreamObject.Write(WriteBuffer,0,WriteBuffer.Length);
225}
226catch(Exception ex)
227{
228//写日志
229m_logs.Append("错误:"+ex.Message+ENTER);
230return false;
231}
232return true;
233}
234
235/// <summary>
236/// 接收SMTP服务器回应
237/// </summary>
238private string RecvResponse(NetworkStream _NetworkStreamObject)
239{
240int StreamSize = 0;
241string ReturnValue = String.Empty;
242byte[] ReadBuffer = new byte[1024] ;
243try
244{
245StreamSize = _NetworkStreamObject.Read(ReadBuffer,0,ReadBuffer.Length);
246}
247catch(Exception ex)
248{
249//写日志
250m_logs.Append("错误:"+ex.Message+ENTER);
251m_ErrCode = ex.Message;
252return "false";
253}
254
255if (StreamSize==0)
256{
257return ReturnValue ;
258}
259else
260{
261ReturnValue = Encoding.Default.GetString(ReadBuffer).Substring(0,StreamSize);
262m_logs.Append(ReturnValue+ENTER);
263return ReturnValue;
264}
265}
266
267/// <summary>
268/// 与服务器交互,发送一条命令并接收回应。
269/// </summary>
270/// <param name="str"/>一个要发送的命令
271private bool Dialog(string str,NetworkStream _NetworkStream)
272{
273if(str==null||str.Trim()=="")
274{
275return true;
276}
277if(SendCommand(str,_NetworkStream))
278{
279string RR=RecvResponse(_NetworkStream);
280if(RR=="false")
281{
282return false;
283}
284string RRCode=RR.Substring(0,3);
285if(m_RightCodeHT[RRCode]!=null)
286{
287return true;
288}
289else
290{
291m_ErrCode = RRCode;
292return false;
293}
294}
295else
296{
297return false;
298}
299
300}
301
302
303/// <summary>
304/// 与服务器交互,发送一组命令并接收回应。
305/// </summary>
306
307private bool Dialog(string[] str,NetworkStream _NetworkStream)
308{
309for(int i=0;i<str.length;i++) <summary="" false;="" if(!dialog(str[i],_networkstream))="" return="" true;="" {="" }="">
310/// SendEmail
311///
312/// <returns></returns>
313private bool SendEmail(NetworkStream _NetworkStream,bool needSmtp,string mailServer,string userName,string password,Hashtable recipients,string from,
314string fromName,string recipientName,string subject,string priority,IList attachments,bool isHtml,
315string body)
316{
317//验证网络连接是否正确
318if(m_RightCodeHT[RecvResponse(_NetworkStream).Substring(0,3)]==null)
319{
320return false;
321}
322
323
324string[] SendBuffer;
325string SendBufferstr;
326StringBuilder SendBufferstrBuilder = new StringBuilder();
327
328//进行SMTP验证
329if(needSmtp)
330{
331SendBuffer=new String[4];
332SendBuffer[0]="EHLO " + mailServer + ENTER;
333SendBuffer[1]="AUTH LOGIN" + ENTER;
334SendBuffer[2]=Base64Encode(userName) + ENTER;
335SendBuffer[3]=Base64Encode(password) + ENTER;
336if(!Dialog(SendBuffer,_NetworkStream))
337{
338return false;
339}
340}
341else
342{
343SendBufferstr="HELO " + mailServer + ENTER;
344if(!Dialog(SendBufferstr,_NetworkStream))
345return false;
346}
347
348//
349SendBufferstr="MAIL FROM:<" + from + ">" + ENTER;
350if(!Dialog(SendBufferstr,_NetworkStream))
351return false;
352
353//
354SendBuffer=new string[m_recipientMaxnum];
355for(int i=0;i<recipients.count;i++) +="" +"="" recipients[i].tostring()="" sendbuffer[i]="RCPT TO:<" {="">" + ENTER;
356
357}
358
359if(!Dialog(SendBuffer,_NetworkStream))
360return false;
361SendBufferstr="DATA" + ENTER;
362if(!Dialog(SendBufferstr,_NetworkStream))
363return false;
364
365SendBufferstrBuilder.Append("From:" + fromName + "<" + from +">" +ENTER);
366
367SendBufferstrBuilder.Append("To:=?"+Charset.ToUpper()+"?B?"+Base64Encode(recipientName)+"?="+"<"+recipients[0]+">"+ENTER);
368
369SendBufferstrBuilder.Append("CC:");
370for(int i=0;i<recipients.count;i++) "<"="" +="" +"="" recipients[i].tostring()="" sendbufferstrbuilder.append(recipients[i].tostring()="" {="">,");
371}
372SendBufferstrBuilder.Append(ENTER);
373
374SendBufferstrBuilder.Append(((subject==String.Empty || subject==null)?"Subject:":((Charset=="")?("Subject:" + subject):("Subject:" + "=?" + Charset.ToUpper() + "?B?" + Base64Encode(subject) +"?="))) + ENTER);
375SendBufferstrBuilder.Append("X-Priority:" + priority + ENTER);
376SendBufferstrBuilder.Append("X-MSMail-Priority:" + priority + ENTER);
377SendBufferstrBuilder.Append("Importance:" + priority + ENTER);
378SendBufferstrBuilder.Append("X-Mailer: Lion.Web.Mail.SmtpMail Pubclass [cn]" + ENTER);
379SendBufferstrBuilder.Append("MIME-Version: 1.0" + ENTER);
380
381if(attachments != null && attachments.Count!=0)
382{
383SendBufferstrBuilder.Append("Content-Type: multipart/mixed;" + ENTER);
384SendBufferstrBuilder.Append(" boundary=\"====="+(isHtml?"001_Dragon520636771063_":"001_Dragon303406132050_")+"=====\""+ENTER+ENTER);
385}
386
387if(isHtml)
388{
389if(attachments != null && attachments.Count==0)
390{
391SendBufferstrBuilder.Append("Content-Type: multipart/alternative;"+ENTER);//内容格式和分隔符
392SendBufferstrBuilder.Append(" boundary=\"=====003_Dragon520636771063_=====\""+ENTER+ENTER);
393
394SendBufferstrBuilder.Append("This is a multi-part message in MIME format."+ENTER+ENTER);
395}
396else
397{
398SendBufferstrBuilder.Append("This is a multi-part message in MIME format."+ENTER+ENTER);
399SendBufferstrBuilder.Append("--=====001_Dragon520636771063_====="+ENTER);
400SendBufferstrBuilder.Append("Content-Type: multipart/alternative;"+ENTER);//内容格式和分隔符
401SendBufferstrBuilder.Append(" boundary=\"=====003_Dragon520636771063_=====\""+ENTER+ENTER);
402}
403SendBufferstrBuilder.Append("--=====003_Dragon520636771063_====="+ENTER);
404SendBufferstrBuilder.Append("Content-Type: text/plain;"+ ENTER);
405SendBufferstrBuilder.Append(((Charset=="")?(" charset=\"iso-8859-1\""):(" charset=\"" + Charset.ToLower() + "\"")) + ENTER);
406SendBufferstrBuilder.Append("Content-Transfer-Encoding: base64" + ENTER + ENTER);
407SendBufferstrBuilder.Append(Base64Encode("邮件内容为HTML格式,请选择HTML方式查看") + ENTER + ENTER);
408
409SendBufferstrBuilder.Append("--=====003_Dragon520636771063_====="+ENTER);
410
411SendBufferstrBuilder.Append("Content-Type: text/html;" + ENTER);
412SendBufferstrBuilder.Append(((Charset=="")?(" charset=\"iso-8859-1\""):(" charset=\"" + Charset.ToLower() + "\"")) + ENTER);
413SendBufferstrBuilder.Append("Content-Transfer-Encoding: base64" + ENTER + ENTER);
414SendBufferstrBuilder.Append(Base64Encode(body) + ENTER + ENTER);
415SendBufferstrBuilder.Append("--=====003_Dragon520636771063_=====--"+ENTER);
416}
417else
418{
419if(attachments != null && attachments.Count!=0)
420{
421SendBufferstrBuilder.Append("--=====001_Dragon303406132050_====="+ENTER);
422}
423SendBufferstrBuilder.Append("Content-Type: text/plain;" + ENTER);
424SendBufferstrBuilder.Append(((Charset=="")?(" charset=\"iso-8859-1\""):(" charset=\"" + Charset.ToLower() + "\"")) + ENTER);
425SendBufferstrBuilder.Append("Content-Transfer-Encoding: base64" + ENTER + ENTER);
426SendBufferstrBuilder.Append(Base64Encode(body) + ENTER);
427}
428
429//SendBufferstr += "Content-Transfer-Encoding: base64"+ENTER;
430if(attachments != null && attachments.Count!=0)
431{
432for(int i=0;i<attachments.count;i++) "."="" #endregion="" #region="" );="" *="" +="" +"='--"+ENTER+ENTER);' 001_dragon520636771063_":"001_dragon303406132050_")="" <summary="" \\\")+1))+"?='\""+ENTER+ENTER' application="" attachment;"+enter);="" base64"+enter);="" content-type:="" enter);="" enter;="" false;="" filename='\"=?"+Charset.ToUpper()+"?B?"+Base64Encode(filepath.Substring(filepath.LastIndexOf("' filepath="(string)attachments[i];" if(!dialog(sendbufferstr,_networkstream))="" name='\"=?"+Charset.ToUpper()+"?B?"+Base64Encode(filepath.Substring(filepath.LastIndexOf("' octet-stream"+enter;="" plain;"+enter);="" return="" sendbufferstr="QUIT" sendbufferstrbuilder.append("="" sendbufferstrbuilder.append("--="+ (isHtml?" sendbufferstrbuilder.append("content-disposition:="" sendbufferstrbuilder.append("content-transfer-encoding:="" sendbufferstrbuilder.append("content-type:="" sendbufferstrbuilder.append(enter="" sendbufferstrbuilder.append(getstream(filepath)+enter+enter);="" string="" text="" true;="" {="" }="">
433/// 添加一个密件收件人
434///
435/// <param name="str"/>收件人地址
436public bool AddRecipientBCC(string str)
437{
438if(str==null||str.Trim()=="")
439return true;
440if(RecipientBCCNum<10)
441{
442RecipientBCC.Add(RecipientBCCNum,str);
443RecipientBCCNum++;
444return true;
445}
446else
447{
448m_logs.Append("错误:收件人过多");
449return false;
450}
451}
452
453
454/// <summary>
455/// 添加一组密件收件人(不超过10个),参数为字符串数组
456/// </summary>
457/// <param name="str"/>保存有收件人地址的字符串数组(不超过10个)
458public bool AddRecipientBCC(string[] str)
459{
460for(int i=0;i<str.length;i++) #endregion="" *="" <summary="" false;="" if(!addrecipientbcc(str[i]))="" return="" true;="" {="" }="">
461/// 邮件发送优先级
462///
463public enum Priority
464{
465High,
466Normal,
467Low
468}
469
470#endregion
471
472}</str.length;i++)></attachments.count;i++)></recipients.count;i++)></recipients.count;i++)></str.length;i++)></enter></enter></forward-path></forward-path></recipients.length;i++)></filepath.length;i++)>