SendMail.cs
上传用户:shjujing
上传日期:2022-07-28
资源大小:11244k
文件大小:20k
源码类别:

Email客户端

开发平台:

Visual C++

  1. using System; 
  2. using System.Text; 
  3. using System.IO; 
  4. using System.Net; 
  5. using System.Net.Sockets; 
  6. using System.Collections; 
  7. using System.Runtime .InteropServices ;
  8. using System.Windows.Forms ;
  9. //正则表达式需要用到的命名空间(本程序中主要用于切割字符串)
  10. using System.Text .RegularExpressions ;
  11. namespace MailSend
  12. {
  13. public class SmtpMail 
  14. public SmtpMail()
  15. {
  16. //
  17. // TODO: 在此处添加构造函数逻辑
  18. //
  19. }
  20. //用来接收调用程序传来的附件路径
  21. private string []FilePath;
  22. // [DllImport("User32.dll")] 
  23. // public static extern int MessageBox(int h, string m, string c, int type);  
  24. //
  25. /// <summary>
  26. /// 重载的构造函数,以便把相关的附件信息传入
  27. /// </summary>
  28. /// <param name="array"></param>
  29. public SmtpMail(ArrayList array) 
  30. //在重载构造函数的同时,将FiilePath初始化
  31. FilePath=new string [array.Count ];
  32. Attachments = new System.Collections.ArrayList(); 
  33. for(int i=0;i<array.Count ;i++)
  34. {
  35. FilePath[i]=array[i].ToString ();
  36. }
  37. if(FilePath!=null)
  38. {
  39. AddAttachment(FilePath);
  40. }
  41. private string enter="rn"; 
  42. /// <summary> 
  43. /// 设定语言代码,默认设定为GB2312,如不需要可设置为"" 
  44. /// </summary> 
  45. private string _charset="GB2312"; 
  46. /// <summary> 
  47. /// 发件人地址 
  48. /// </summary> 
  49. private string _from=""; 
  50. /// <summary> 
  51. /// 发件人姓名 
  52. /// </summary> 
  53. private string _fromName=""; 
  54. /// <summary> 
  55. /// 回复邮件地址 
  56. /// </summary> 
  57. ///public string ReplyTo=""; 
  58. /// <summary> 
  59. /// 收件人列表 
  60. /// </summary> 
  61. private string Recipient; 
  62. /// <summary> 
  63. /// 邮件服务器域名 
  64. /// </summary> 
  65. private string mailserver=""; 
  66. /// <summary> 
  67. /// 邮件服务器端口号 
  68. /// </summary> 
  69. private int mailserverport=25; 
  70. /// <summary> 
  71. /// SMTP认证时使用的用户名 
  72. /// </summary> 
  73. private string username=""; 
  74. /// <summary> 
  75. /// SMTP认证时使用的密码 
  76. /// </summary> 
  77. private string password=""; 
  78. /// <summary> 
  79. /// 是否需要SMTP验证 
  80. /// </summary> 
  81. private bool ESmtp=false; 
  82. /// <summary> 
  83. /// 是否Html邮件 
  84. /// </summary> 
  85. private bool _html=false; 
  86. /// <summary> 
  87. /// 邮件附件列表 
  88. /// </summary> 
  89. private IList Attachments; 
  90. /// <summary> 
  91. /// 邮件发送优先级,可设置为"High","Normal","Low"或"1","3","5" 
  92. /// </summary> 
  93. private string priority="Normal"; 
  94. /// <summary> 
  95. /// 邮件主题 
  96. /// </summary> 
  97. private string _subject; 
  98. /// <summary> 
  99. /// 邮件正文 
  100. /// </summary> 
  101. private string _body; 
  102. /// <summary> 
  103. /// 错误消息反馈 
  104. /// </summary> 
  105. private string errmsg; 
  106. /// <summary> 
  107. /// TcpClient对象,用于连接服务器 
  108. /// </summary> 
  109. private TcpClient tc; 
  110. /// <summary> 
  111. /// NetworkStream对象 
  112. /// </summary> 
  113. private NetworkStream ns; 
  114. /// <summary> 
  115. /// SMTP错误代码哈希表 
  116. /// </summary> 
  117. private Hashtable ErrCodeHT = new Hashtable(); 
  118. /// <summary> 
  119. /// SMTP正确代码哈希表 
  120. /// </summary> 
  121. private Hashtable RightCodeHT = new Hashtable(); 
  122. /// <summary> 
  123. /// 邮件主题 
  124. /// </summary> 
  125. public string Subject 
  126. get 
  127. return this._subject; 
  128. set 
  129. this._subject = value; 
  130. /// <summary> 
  131. /// 邮件正文 
  132. /// </summary> 
  133. public string Body 
  134. get 
  135. return this._body; 
  136. set 
  137. this._body = value; 
  138. /// <summary> 
  139. /// 发件人地址 
  140. /// </summary> 
  141. public string From 
  142. get 
  143. return _from; 
  144. set 
  145. this._from = value; 
  146. /// <summary> 
  147. /// 设定语言代码,默认设定为GB2312,如不需要可设置为"" 
  148. /// </summary> 
  149. public string Charset 
  150. get 
  151. return this._charset; 
  152. set 
  153. this._charset = value; 
  154. /// <summary> 
  155. /// 发件人姓名 
  156. /// </summary> 
  157. public string FromName 
  158. get 
  159. return this._fromName; 
  160. set 
  161. this._fromName = value; 
  162. /// <summary> 
  163. /// 收件人姓名 
  164. /// </summary> 
  165. public string RecipientName 
  166. get 
  167. return this.Recipient; 
  168. set 
  169. this.Recipient = value; 
  170. /// <summary> 
  171. /// 邮件服务器域名和验证信息 
  172. /// 形如:"user:pass@www.server.com:25",也可省略次要信息。如"user:pass@www.server.com"或"www.server.com" 
  173. /// </summary> 
  174. public string MailDomain 
  175. set 
  176. mailserver=value; 
  177. /// <summary> 
  178. /// 邮件服务器端口号 
  179. /// </summary> 
  180. public int MailDomainPort 
  181. set 
  182. mailserverport=value; 
  183. /// <summary> 
  184. /// SMTP认证时使用的用户名 
  185. /// </summary> 
  186. public string MailServerUserName 
  187. set 
  188. if(value.Trim()!="") 
  189. username=value.Trim(); 
  190. ESmtp=true; 
  191. else 
  192. username=""; 
  193. ESmtp=false; 
  194. /// <summary> 
  195. /// SMTP认证时使用的密码 
  196. /// </summary> 
  197. public string MailServerPassWord 
  198. set 
  199. password=value; 
  200. /// <summary> 
  201. /// 邮件发送优先级,可设置为"High","Normal","Low"或"1","3","5" 
  202. /// </summary> 
  203. public string Priority 
  204. set 
  205. switch(value.ToLower()) 
  206. case "high": 
  207. priority="High"; 
  208. break; 
  209. case "1": 
  210. priority="High"; 
  211. break; 
  212. case "normal": 
  213. priority="Normal"; 
  214. break; 
  215. case "3": 
  216. priority="Normal"; 
  217. break; 
  218. case "low": 
  219. priority="Low"; 
  220. break; 
  221. case "5": 
  222. priority="Low"; 
  223. break; 
  224. default: 
  225. priority="Normal"; 
  226. break; 
  227. /// <summary> 
  228. /// 是否Html邮件 
  229. /// </summary> 
  230. public bool Html 
  231. get 
  232. return this._html; 
  233. set 
  234. this._html = value; 
  235. /// <summary> 
  236. /// 错误消息反馈 
  237. /// </summary> 
  238. public string ErrorMessage 
  239. get 
  240. return errmsg; 
  241. public bool eSmtp
  242. {
  243. get
  244. {
  245. return this.ESmtp;
  246. }
  247. set
  248. {
  249. this.ESmtp =value;
  250. }
  251. }
  252. /// <summary> 
  253. /// 添加邮件附件 
  254. /// </summary> 
  255. /// <param name="FilePath">附件绝对路径</param> 
  256. public void AddAttachment(params string[] FilePath) 
  257. try
  258. {
  259. if(FilePath==null) 
  260. throw(new ArgumentNullException("FilePath")); 
  261. for(int i=0;i<FilePath.Length;i++) 
  262. Attachments.Add(FilePath[i]); 
  263. }
  264. catch(Exception ex)
  265. {
  266. MessageBox.Show (ex.ToString ());
  267. }
  268. /// <summary> 
  269. /// 得到上传附件的文件流 
  270. /// </summary> 
  271. /// <param name="FilePath">附件的绝对路径</param> 
  272. private string GetStream(string FilePath) 
  273. try
  274. {
  275. //建立文件流对象 
  276. System.IO.FileStream FileStr=new System.IO.FileStream(FilePath,System.IO.FileMode.Open); 
  277. byte[] by=new byte[System.Convert.ToInt32(FileStr.Length)]; 
  278. FileStr.Read(by,0,by.Length); 
  279. FileStr.Close(); 
  280. return(System.Convert.ToBase64String(by)); 
  281. }
  282. catch
  283. {
  284. MessageBox.Show ("可能你要打开的文件的属性是只读的!","请检查权限");
  285. return null;
  286. }
  287. /// <summary> 
  288. /// 发送邮件方法,所有参数均通过属性设置。 
  289. /// </summary> 
  290. public bool Send() 
  291. if(mailserver.Trim()=="") 
  292. MessageBox.Show ("必须指定SMTP服务器"); 
  293. return false;
  294. return SendEmail(); 
  295. /// <summary> 
  296. /// 发送邮件方法 
  297. /// </summary> 
  298. /// <param name="smtpserver">smtp服务器信息,如"username:password@www.smtpserver.com:25",也可去掉部分次要信 
  299. public bool Send(string smtpserver) 
  300. MailDomain=smtpserver; 
  301. return Send(); 
  302. /// <summary> 
  303. /// 发送邮件方法 
  304. /// </summary> 
  305. /// <param name="smtpserver">smtp服务器信息,如"username:password@www.smtpserver.com:25",也可去掉部分次要信 
  306. /// <param name="from">发件人mail地址</param> 
  307. /// <param name="fromname">发件人姓名</param> 
  308. /// <param name="to">收件人地址</param> 
  309. /// <param name="toname">收件人姓名</param> 
  310. /// <param name="html">是否HTML邮件</param> 
  311. /// <param name="subject">邮件主题</param> 
  312. /// <param name="body">邮件正文</param> 
  313. public bool Send(string smtpserver,string from,string fromname,string to,bool html,string 
  314. subject,string body) 
  315. MailDomain=smtpserver; 
  316. From=from; 
  317. FromName=fromname; 
  318. Recipient=to; 
  319. Html=html; 
  320. Subject=subject; 
  321. Body=body; 
  322. return Send(); 
  323. void Dispose() 
  324. if(ns!=null)ns.Close(); 
  325. if(tc!=null)tc.Close(); 
  326. /// <summary> 
  327. /// SMTP回应代码哈希表 
  328. /// </summary> 
  329. private void SMTPCodeAdd() 
  330. ErrCodeHT.Add("500","邮箱地址错误"); 
  331. ErrCodeHT.Add("501","参数格式错误"); 
  332. ErrCodeHT.Add("502","命令不可实现"); 
  333. ErrCodeHT.Add("503","服务器需要SMTP验证"); 
  334. ErrCodeHT.Add("504","命令参数不可实现"); 
  335. ErrCodeHT.Add("421","服务未就绪,关闭传输信道"); 
  336. ErrCodeHT.Add("450","要求的邮件操作未完成,邮箱不可用(例如,邮箱忙)"); 
  337. ErrCodeHT.Add("550","要求的邮件操作未完成,邮箱不可用(例如,邮箱未找到,或不可访问)"); 
  338. ErrCodeHT.Add("451","放弃要求的操作;处理过程中出错"); 
  339. ErrCodeHT.Add("551","用户非本地,请尝试<forward-path>"); 
  340. ErrCodeHT.Add("452","系统存储不足,要求的操作未执行"); 
  341. ErrCodeHT.Add("552","过量的存储分配,要求的操作未执行"); 
  342. ErrCodeHT.Add("553","邮箱名不可用,要求的操作未执行(例如邮箱格式错误)"); 
  343. ErrCodeHT.Add("432","需要一个密码转换"); 
  344. ErrCodeHT.Add("534","认证机制过于简单"); 
  345. ErrCodeHT.Add("538","当前请求的认证机制需要加密"); 
  346. ErrCodeHT.Add("454","临时认证失败"); 
  347. ErrCodeHT.Add("530","需要认证"); 
  348. RightCodeHT.Add("220","服务就绪"); 
  349. RightCodeHT.Add("250","要求的邮件操作完成"); 
  350. RightCodeHT.Add("251","用户非本地,将转发向<forward-path>"); 
  351. RightCodeHT.Add("354","开始邮件输入,以<enter>.<enter>结束"); 
  352. RightCodeHT.Add("221","服务关闭传输信道"); 
  353. RightCodeHT.Add("334","服务器响应验证Base64字符串"); 
  354. RightCodeHT.Add("235","验证成功"); 
  355. /// <summary> 
  356. /// 将字符串编码为Base64字符串 
  357. /// </summary> 
  358. /// <param name="str">要编码的字符串</param> 
  359. private string Base64Encode(string str) 
  360. byte[] barray; 
  361. barray=Encoding.Default.GetBytes(str); 
  362. return Convert.ToBase64String(barray); 
  363. /// <summary> 
  364. /// 将Base64字符串解码为普通字符串 
  365. /// </summary> 
  366. /// <param name="str">要解码的字符串</param> 
  367. private string Base64Decode(string str) 
  368. byte[] barray; 
  369. barray=Convert.FromBase64String(str); 
  370. return Encoding.Default.GetString(barray); 
  371. /// <summary> 
  372. /// 发送SMTP命令 
  373. /// </summary> 
  374. private bool SendCommand(string str) 
  375. byte[] WriteBuffer; 
  376. if(str==null||str.Trim()==String.Empty) 
  377. return true; 
  378. WriteBuffer = Encoding.Default.GetBytes(str); 
  379. try 
  380. ns.Write(WriteBuffer,0,WriteBuffer.Length); 
  381. catch 
  382. errmsg="网络连接错误"; 
  383. return false; 
  384. return true; 
  385. /// <summary> 
  386. /// 接收SMTP服务器回应 
  387. /// </summary> 
  388. private string RecvResponse() 
  389. int StreamSize; 
  390. string ReturnValue = String.Empty; 
  391. byte[] ReadBuffer = new byte[1024] ; 
  392. try 
  393. StreamSize=ns.Read(ReadBuffer,0,ReadBuffer.Length); 
  394. catch(Exception ex)
  395. MessageBox.Show (ex.ToString ());
  396. return "false"; 
  397. if (StreamSize==0) 
  398. return ReturnValue ; 
  399. else 
  400. ReturnValue = Encoding.Default.GetString(ReadBuffer).Substring(0,StreamSize); 
  401. return ReturnValue; 
  402. /// <summary> 
  403. /// 与服务器交互,发送一条命令并接收回应。 
  404. /// </summary> 
  405. /// <param name="str">一个要发送的命令</param> 
  406. /// <param name="errstr">如果错误,要反馈的信息</param> 
  407. private bool Dialog(string str,string errstr) 
  408. if(str==null||str.Trim()=="") 
  409. return true; 
  410. if(SendCommand(str)) 
  411. string RR=RecvResponse(); 
  412. if(RR=="false") 
  413. return false; 
  414. try
  415. {
  416. string RRCode=RR.Substring(0,3); 
  417. if(RightCodeHT[RRCode]!=null) 
  418. return true; 
  419. else 
  420. if(ErrCodeHT[RRCode]!=null) 
  421. errmsg+=(RRCode+ErrCodeHT[RRCode].ToString()); 
  422. errmsg+=enter; 
  423. else 
  424. errmsg+=RR; 
  425. errmsg+=errstr; 
  426. return false; 
  427. }
  428. catch
  429. {
  430. MessageBox.Show ("发送的附件超过本服务器对个人软件的支持!","请检查附件的大小");
  431. return false;
  432. }
  433. else 
  434. return false; 
  435. }
  436. /// <summary> 
  437. /// 与服务器交互,发送一组命令并接收回应。 
  438. /// </summary> 
  439. private bool Dialog(string[] str,string errstr) 
  440. for(int i=0;i<str.Length;i++) 
  441. //如果在身份验证阶段有一个不成功,就返回错误标志位
  442. if(!Dialog(str[i],"")) 
  443. errmsg+=enter; 
  444. errmsg+=errstr; 
  445. return false; 
  446. //身份验证全部正确的话,则返回正确标志位
  447. return true; 
  448. /// <summary> 
  449. /// SendEmail 
  450. /// </summary> 
  451. /// <returns></returns> 
  452. private bool SendEmail() 
  453. try 
  454. tc=new TcpClient(mailserver,mailserverport); 
  455. catch
  456. MessageBox.Show ("连接失败","请确认");
  457. return false; 
  458. ns = tc.GetStream(); 
  459. SMTPCodeAdd(); 
  460. //验证网络连接是否正确 
  461. if(RightCodeHT[RecvResponse().Substring(0,3)]==null) 
  462. errmsg="网络连接失败"; 
  463. return false; 
  464. string[] SendBuffer; 
  465. string SendBufferstr; 
  466. //进行SMTP验证 
  467. if(ESmtp) 
  468. SendBuffer=new String[4]; 
  469. SendBuffer[0]="EHLO " + mailserver + enter; 
  470. SendBuffer[1]="AUTH LOGIN" + enter; 
  471. SendBuffer[2]=Base64Encode(username) + enter; 
  472. SendBuffer[3]=Base64Encode(password) + enter; 
  473. if(!Dialog(SendBuffer,"SMTP服务器验证失败,请核对用户名和密码。"))
  474. {
  475. MessageBox.Show ("SMTP服务器验证失败,请核对用户名和密码。");
  476. return false;
  477. }
  478. else 
  479. SendBufferstr="HELO " + mailserver + enter; 
  480. if(!Dialog(SendBufferstr,"")) 
  481. return false; 
  482. // 
  483. SendBufferstr="MAIL FROM:<" + From + ">" + enter; 
  484. if(!Dialog(SendBufferstr,"发件人地址错误,或不能为空"))
  485. {
  486. MessageBox.Show("发件人地址错误,或不能为空");
  487. return false; 
  488. }
  489.  
  490. //把传过来的收件人的地址分割然后提交给服务器
  491. string split=",";
  492. string []address=Regex.Split (RecipientName,split);
  493. SendBuffer=new string [address.Length];
  494. for(int i=0;i<SendBuffer.Length;i++)
  495. {
  496. SendBuffer[i]="RCPT TO:<" +address[i]+">" + enter;
  497. }
  498. if(!Dialog(SendBuffer,"收件人地址有误")) 
  499. {
  500. MessageBox.Show("收件人地址有误");
  501. return false; 
  502. }
  503. SendBufferstr="DATA" + enter; 
  504. if(!Dialog(SendBufferstr,"")) 
  505. return false; 
  506. SendBufferstr="From:" + FromName + "<" + From +">" +enter; 
  507. SendBufferstr += "To:<"+RecipientName+">"+enter;
  508. SendBufferstr+=((Subject==String.Empty || Subject==null)?"Subject:":((Charset=="")?("Subject:" + 
  509. Subject):("Subject:" + "=?" + Charset.ToUpper() + "?B?" + Base64Encode(Subject) +"?="))) + enter; 
  510. SendBufferstr+="X-Priority:" + priority + enter; 
  511. SendBufferstr+="X-Mailer: ArgentSwan Mail Sender" + enter; 
  512. SendBufferstr+="MIME-Version: 1.0" + enter; 
  513. //MIME定义了5个新的信头字段,可以与原有信头字段一样,用在RF822邮件的首部中。
  514. //1.MIME版本信头字段 格式:MIME-Version:1.0 <CRLF>
  515. //2.邮件唯一标识信头字段 格式:Content-ID:唯一标识信件的字符串  <CRLF>
  516. //3.邮件内容描述信头字段 格式:Content-Description:描述文本 <CRLF>
  517. //4.MIME邮件的内容类型信头字段 格式:Content-Type:主类别标识符/子类别标识符 [;参数列表]  <CRLF>
  518. //5.内容传送编码方式信头字段 格式:Content-Transfer-Encoding:编码方式标识符 <CRLF>
  519. if(Attachments.Count!=0) 
  520. //mixed  按照特定顺序的几个独立部分
  521. SendBufferstr+="Content-Type: multipart/mixed;" + enter; 
  522. SendBufferstr += " boundary="***"+ 
  523. (Html?"001_yinhu19821115":"001_yinhu19831115")+"***""+enter+enter; 
  524. if(Html) 
  525. if(Attachments.Count==0) 
  526. //multipart多部分  alternative 不同格式的同一邮件
  527. SendBufferstr += "Content-Type: multipart/alternative;"+enter;//内容格式和分隔符 
  528. SendBufferstr += " boundary="***003_yinhu19821115***""+enter+enter; 
  529. SendBufferstr += "This is a multi-part message in MIME format."+enter+enter; 
  530. else 
  531. SendBufferstr +="This is a multi-part message in MIME format."+enter+enter; 
  532. SendBufferstr += "--***001_yinhu19821115***"+enter; 
  533. SendBufferstr += "Content-Type: multipart/alternative;"+enter;//内容格式和分隔符 
  534. SendBufferstr += " boundary="***003_yinhu19821115***""+enter+enter; 
  535. }
  536. SendBufferstr += "--***003_yinhu19821115***"+enter; 
  537. SendBufferstr += "Content-Type: text/plain;"+ enter; 
  538. SendBufferstr += ((Charset=="")?(" charset="iso-8859-1""):(" charset="" + 
  539. Charset.ToLower() + """)) + enter; 
  540. SendBufferstr+="Content-Transfer-Encoding: base64" + enter + enter; 
  541. SendBufferstr+= Base64Encode("邮件内容为HTML格式,请选择HTML方式查看") + enter + enter; 
  542. SendBufferstr += "--***003_yinhu19821115***"+enter; 
  543. SendBufferstr+="Content-Type: text/html;" + enter; 
  544. SendBufferstr+=((Charset=="")?(" charset="iso-8859-1""):(" charset="" + 
  545. Charset.ToLower() + """)) + enter; 
  546. SendBufferstr+="Content-Transfer-Encoding: base64" + enter + enter; 
  547. SendBufferstr+=Base64Encode(Body)+ enter + enter; 
  548. SendBufferstr += "--***003_yinhu19821115***--"+enter; 
  549. else 
  550. if(Attachments.Count!=0) 
  551. SendBufferstr += "--***001_yinhu19831115***"+enter; 
  552. SendBufferstr+="Content-Type: text/plain;" + enter; 
  553. SendBufferstr+=((Charset=="")?(" charset="iso-8859-1""):(" charset="" + 
  554. Charset.ToLower() + """)) + enter; 
  555. SendBufferstr+="Content-Transfer-Encoding: base64" + enter + enter; 
  556. SendBufferstr+= Base64Encode(Body) + enter; 
  557. if(Attachments.Count!=0) 
  558. for(int i=0;i<Attachments.Count;i++) 
  559. string filepath = Attachments[i].ToString(); 
  560. SendBufferstr += "--***"+ 
  561. (Html?"001_yinhu19821115":"001_yinhu19831115") +"***"+enter; 
  562. //用于在电子邮件中传输一个含有任意数据的实体。内容是一个未解释的字节序列。
  563. //当内容类型未知或者对数据没有具体定义媒体类别时,通常使用它描述
  564. SendBufferstr += "Content-Type: application/octet-stream"+enter; 
  565. SendBufferstr += " name="=?"+Charset.ToUpper()+"?B?"+Base64Encode 
  566. (filepath.Substring(filepath.LastIndexOf("\")+1))+"?=""+enter; 
  567. SendBufferstr += "Content-Transfer-Encoding: base64"+enter; 
  568. SendBufferstr += "Content-Disposition: attachment;"+enter; 
  569. SendBufferstr += " filename="=?"+Charset.ToUpper()+"?B?"+Base64Encode 
  570. (filepath.Substring(filepath.LastIndexOf("\")+1))+"?=""+enter+enter; 
  571. SendBufferstr += GetStream(filepath)+enter+enter; 
  572. SendBufferstr += "--***"+ (Html?"001_yinhu19821115":"001_yinhu19831115") 
  573. +"***--"+enter+enter; 
  574. }
  575. SendBufferstr += enter + "." + enter; 
  576. if(!Dialog(SendBufferstr,"错误信件信息")) 
  577. return false; 
  578. SendBufferstr="QUIT" + enter; 
  579. if(!Dialog(SendBufferstr,"断开连接时错误")) 
  580. return false; 
  581. ns.Close(); 
  582. tc.Close();
  583. return true; 
  584. }
  585. }
  586. }