Message.cs
上传用户:hncsjykj
上传日期:2022-08-09
资源大小:461k
文件大小:39k
源码类别:

Email客户端

开发平台:

C#

  1. /******************************************************************************
  2. Copyright 2003-2004 Hamid Qureshi and Unruled Boy 
  3. OpenPOP.Net is free software; you can redistribute it and/or modify
  4. it under the terms of the Lesser GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. OpenPOP.Net is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10. Lesser GNU General Public License for more details.
  11. You should have received a copy of the Lesser GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  14. /*******************************************************************************/
  15. /*
  16. *Name: OpenPOP.MIMEParser.Message
  17. *Function: Message Parser
  18. *Author: Hamid Qureshi
  19. *Created: 2003/8
  20. *Modified: 2004/6/16 18:34 GMT+8 by Unruled Boy
  21. *Description:
  22. *Changes:
  23. * 2004/6/16 18:34 GMT+8 by Unruled Boy
  24. * 1.fixed a loop in message body decoding by .
  25. * 2004/5/17 14:20 GMT+8 by Unruled Boy
  26. * 1.Again, fixed something but do not remember :(
  27. * 2004/5/11 17:00 GMT+8 by Unruled Boy
  28. * 1.Fixed a bug in parsing ContentCharset
  29. * 2.Fixed a bug in ParseStreamLines
  30. * 2004/5/10 10:00 GMT+8 by Unruled Boy
  31. * 1.Well, fixed something but do not remember :(
  32. * 2004/5/8 17:00 GMT+8 by Unruled Boy
  33. * 1.Fixed a bug in parsing boundary
  34. * 2004/5/1 14:13 GMT+8 by Unruled Boy
  35. * 1.Adding three more constructors
  36. * 2.Adding descriptions to every public functions/property/void
  37. * 2004/4/29 19:05 GMT+8 by Unruled Boy
  38. * 1.Fixed the bug parsing headers/boundary
  39. * 2004/4/28 19:06 GMT+8 by Unruled Boy
  40. * 1.Adding DateTimeInfo property
  41. * 2.Maybe we correct the HTML content type bug
  42. * 2004/4/23 21:13 GMT+8 by Unruled Boy
  43. * 1.New Contructor
  44. * 2.Tidy up the codes to follow Hungarian Notation
  45. * 2004/3/29 10:38 GMT+8 by Unruled Boy
  46. * 1.removing bugs in decoding message
  47. * 2004/3/29 17:22 GMT+8 by Unruled Boy
  48. * 1.adding support for reply message using ms-tnef 
  49. * 2.adding support for all custom headers
  50. * 3.rewriting the header parser(adding 3 ParseStreamLines)
  51. * 4.adding detail description for every function
  52. * 5.cleaning up the codes
  53. * 2004/3/30 09:15 GMT+8 by Unruled Boy
  54. * 1.Adding ImportanceType
  55. */
  56. using System;
  57. using System.IO;
  58. using System.Collections;
  59. using System.Text;
  60. using System.Text.RegularExpressions;
  61. namespace OpenPOP.MIMEParser
  62. {
  63. /// <summary>
  64. /// Message Parser.
  65. /// </summary>
  66. public class Message
  67. {
  68. #region Member Variables
  69. private ArrayList _attachments=new ArrayList();
  70. private string _rawHeader=null;
  71. private string _rawMessage=null;
  72. private string _rawMessageBody=null;
  73. private int _attachmentCount=0;
  74.         private int _realAttachmentCount =0;
  75.         private bool _hasRealAttachment = false;
  76. private string _replyTo=null;
  77. private string _replyToEmail=null;
  78. private string _from=null;
  79. private string _fromEmail=null;
  80. private string _date=null;
  81. private string _dateTimeInfo=null;
  82. private string _subject=null;
  83. private string[] _to=new string[0];
  84. private string[] _cc=new string[0];
  85. private string[] _bcc=new string[0];
  86. private ArrayList _keywords=new ArrayList();
  87. private string _contentType=null;
  88. private string _contentCharset=null;
  89. private string _reportType=null;
  90. private string _contentTransferEncoding=null;
  91. private bool _html=false;
  92. private long _contentLength=0;
  93. private string _contentEncoding=null;
  94. private string _returnPath=null;
  95. private string _mimeVersion=null;
  96. private string _received=null;
  97. private string _importance=null;
  98. private string _messageID=null;
  99. private string _attachmentboundry=null;
  100. private string _attachmentboundry2=null;
  101. private bool _hasAttachment=false;
  102. private string _dispositionNotificationTo=null;
  103. private ArrayList _messageBody=new ArrayList();
  104. private string _basePath=null;
  105. private bool _autoDecodeMSTNEF=false;
  106. private Hashtable _customHeaders=new Hashtable();
  107. #endregion
  108. #region Properties
  109. /// <summary>
  110. /// custom headers
  111. /// </summary>
  112. public Hashtable CustomHeaders
  113. {
  114. get{return _customHeaders;}
  115. set{_customHeaders=value;}
  116. }
  117. /// <summary>
  118. /// whether auto decoding MS-TNEF attachment files
  119. /// </summary>
  120. public bool AutoDecodeMSTNEF
  121. {
  122. get{return _autoDecodeMSTNEF;}
  123. set{_autoDecodeMSTNEF=value;}
  124. }
  125. /// <summary>
  126. /// path to extract MS-TNEF attachment files
  127. /// </summary>
  128. public string BasePath
  129. {
  130. get{return _basePath;}
  131. set
  132. {
  133. try
  134. {
  135. if(value.EndsWith("\"))
  136. _basePath=value;
  137. else
  138. _basePath=value+"\";
  139. }
  140. catch
  141. {
  142. }
  143. }
  144. }
  145. /// <summary>
  146. /// message keywords
  147. /// </summary>
  148. public ArrayList Keywords
  149. {
  150. get{return _keywords;}
  151. }
  152. /// <summary>
  153. /// disposition notification
  154. /// </summary>
  155. public string DispositionNotificationTo
  156. {
  157. get{return _dispositionNotificationTo;}
  158. }
  159. /// <summary>
  160. /// received server
  161. /// </summary>
  162. public string Received
  163. {
  164. get{return _received;}
  165. }
  166. /// <summary>
  167. /// importance level
  168. /// </summary>
  169. public string Importance
  170. {
  171. get{return _importance;}
  172. }
  173. /// <summary>
  174. /// importance level type
  175. /// </summary>
  176. public MessageImportanceType ImportanceType
  177. {
  178. get
  179. {
  180. switch(_importance.ToUpper())
  181. {
  182. case "5":
  183. case "HIGH":
  184. return MessageImportanceType.HIGH;
  185. case "3":
  186. case "NORMAL":
  187. return MessageImportanceType.NORMAL;
  188. case "1":
  189. case "LOW":
  190. return MessageImportanceType.LOW;
  191. default:
  192. return MessageImportanceType.NORMAL;
  193. }
  194. }
  195. }
  196. /// <summary>
  197. /// Content Charset
  198. /// </summary>
  199. public string ContentCharset
  200. {
  201. get{return _contentCharset;}
  202. }
  203. /// <summary>
  204. /// Content Transfer Encoding
  205. /// </summary>
  206. public string ContentTransferEncoding
  207. {
  208. get{return _contentTransferEncoding;}
  209. }
  210. /// <summary>
  211. /// Message Bodies
  212. /// </summary>
  213. public ArrayList MessageBody
  214. {
  215. get{return _messageBody;}
  216. }
  217. /// <summary>
  218. /// Attachment Boundry
  219. /// </summary>
  220. public string AttachmentBoundry
  221. {
  222. get{return _attachmentboundry;}
  223. }
  224. /// <summary>
  225. /// Alternate Attachment Boundry
  226. /// </summary>
  227. public string AttachmentBoundry2
  228. {
  229. get{return _attachmentboundry2;}
  230. }
  231. /// <summary>
  232. /// Attachment Count
  233. /// </summary>
  234. public int AttachmentCount
  235. {
  236. get{return _attachmentCount;}
  237. }
  238.         public int RealAttachmentCount
  239.         {
  240.             get { return _realAttachmentCount; }
  241.         }
  242. /// <summary>
  243. /// Attachments
  244. /// </summary>
  245. public ArrayList Attachments
  246. {
  247. get{return _attachments;}
  248. }
  249. /// <summary>
  250. /// CC
  251. /// </summary>
  252. public string[] CC
  253. {
  254. get{return _cc;}
  255. }
  256. /// <summary>
  257. /// BCC
  258. /// </summary>
  259. public string[] BCC
  260. {
  261. get{return _bcc;}
  262. }
  263. /// <summary>
  264. /// TO
  265. /// </summary>
  266. public string[] TO
  267. {
  268. get{return _to;}
  269. }
  270. /// <summary>
  271. /// Content Encoding
  272. /// </summary>
  273. public string ContentEncoding
  274. {
  275. get{return _contentEncoding;}
  276. }
  277. /// <summary>
  278. /// Content Length
  279. /// </summary>
  280. public long ContentLength
  281. {
  282. get{return _contentLength;}
  283. }
  284. /// <summary>
  285. /// Content Type
  286. /// </summary>
  287. public string ContentType
  288. {
  289. get{return _contentType;}
  290. }
  291. /// <summary>
  292. /// Report Type
  293. /// </summary>
  294. public string ReportType
  295. {
  296. get{return _reportType;}
  297. }
  298. /// <summary>
  299. /// HTML
  300. /// </summary>
  301. public bool HTML
  302. {
  303. get{return _html;}
  304. }
  305. /// <summary>
  306. /// Date
  307. /// </summary>
  308. public string Date
  309. {
  310. get{return _date;}
  311. }
  312. /// <summary>
  313. /// DateTime Info
  314. /// </summary>
  315. public string DateTimeInfo
  316. {
  317. get{return _dateTimeInfo;}
  318. }
  319. /// <summary>
  320. /// From name
  321. /// </summary>
  322. public string From
  323. {
  324. get{return _from;}
  325. }
  326. /// <summary>
  327. /// From Email
  328. /// </summary>
  329. public string FromEmail
  330. {
  331. get{return _fromEmail;}
  332. }
  333. /// <summary>
  334. /// Reply to name
  335. /// </summary>
  336. public string ReplyTo
  337. {
  338. get{return _replyTo;}
  339. }
  340. /// <summary>
  341. /// Reply to email
  342. /// </summary>
  343. public string ReplyToEmail
  344. {
  345. get{return _replyToEmail;}
  346. }
  347. /// <summary>
  348. /// whether has attachment
  349. /// </summary>
  350. public bool HasAttachment
  351. {
  352. get{return _hasAttachment;}
  353. }
  354.         public bool HasRealAttachment
  355.         {
  356.             get { return _hasRealAttachment; }
  357.         }
  358. /// <summary>
  359. /// raw message body
  360. /// </summary>
  361. public string RawMessageBody
  362. {
  363. get{return _rawMessageBody;}
  364. }
  365. /// <summary>
  366. /// Message ID
  367. /// </summary>
  368. public string MessageID
  369. {
  370. get{return _messageID;}
  371. }
  372. /// <summary>
  373. /// MIME version
  374. /// </summary>
  375. public string MimeVersion
  376. {
  377. get{return _mimeVersion;}
  378. }
  379. /// <summary>
  380. /// raw header
  381. /// </summary>
  382. public string RawHeader
  383. {
  384. get{return _rawHeader;}
  385. }
  386. /// <summary>
  387. /// raw message
  388. /// </summary>
  389. public string RawMessage
  390. {
  391. get{return _rawMessage;}
  392. }
  393. /// <summary>
  394. /// return path
  395. /// </summary>
  396. public string ReturnPath
  397. {
  398. get{return _returnPath;}
  399. }
  400. /// <summary>
  401. /// subject
  402. /// </summary>
  403. public string Subject
  404. {
  405. get{return _subject;}
  406. }
  407. #endregion
  408. /// <summary>
  409. /// release all objects
  410. /// </summary>
  411. ~Message()
  412. {
  413. _attachments.Clear();
  414. _attachments=null;
  415. _keywords.Clear();
  416. _keywords=null;
  417. _messageBody.Clear();
  418. _messageBody=null;
  419. _customHeaders.Clear();
  420. _customHeaders=null;
  421. }
  422. /// <summary>
  423. /// New Message
  424. /// </summary>
  425. /// <param name="blnFinish">reference for the finishing state</param>
  426. /// <param name="strBasePath">path to extract MS-TNEF attachment files</param>
  427. /// <param name="blnAutoDecodeMSTNEF">whether auto decoding MS-TNEF attachments</param>
  428. /// <param name="blnOnlyHeader">whether only decode the header without body</param>
  429. /// <param name="strEMLFile">file of email content to load from</param>
  430. public Message(ref bool blnFinish, string strBasePath, bool blnAutoDecodeMSTNEF, bool blnOnlyHeader, string strEMLFile)
  431. {
  432. string strMessage=null;
  433. if(Utility.ReadPlainTextFromFile(strEMLFile,ref strMessage))
  434. {
  435. NewMessage(ref blnFinish,strBasePath,blnAutoDecodeMSTNEF,strMessage,blnOnlyHeader);
  436. }
  437. else
  438. blnFinish=true;
  439. }
  440. /// <summary>
  441. /// New Message
  442. /// </summary>
  443. /// <param name="blnFinish">reference for the finishing state</param>
  444. /// <param name="strBasePath">path to extract MS-TNEF attachment files</param>
  445. /// <param name="blnAutoDecodeMSTNEF">whether auto decoding MS-TNEF attachments</param>
  446. /// <param name="strMessage">raw message content</param>
  447. /// <param name="blnOnlyHeader">whether only decode the header without body</param>
  448. public Message(ref bool blnFinish, string strBasePath, bool blnAutoDecodeMSTNEF, string strMessage, bool blnOnlyHeader)
  449. {
  450. NewMessage(ref blnFinish,strBasePath,blnAutoDecodeMSTNEF,strMessage,blnOnlyHeader);
  451. }
  452. /// <summary>
  453. /// New Message
  454. /// </summary>
  455. /// <param name="blnFinish">reference for the finishing state</param>
  456. /// <param name="strMessage">raw message content</param>
  457. /// <param name="blnOnlyHeader">whether only decode the header without body</param>
  458. public Message(ref bool blnFinish, string strMessage, bool blnOnlyHeader)
  459. {
  460. NewMessage(ref blnFinish,"",false,strMessage,blnOnlyHeader);
  461. }
  462. /// <summary>
  463. /// New Message
  464. /// </summary>
  465. /// <param name="blnFinish">reference for the finishing state</param>
  466. /// <param name="strMessage">raw message content</param>
  467. public Message(ref bool blnFinish, string strMessage)
  468. {
  469. NewMessage(ref blnFinish,"",false,strMessage,false);
  470. }
  471. /// <summary>
  472. /// get valid attachment
  473. /// </summary>
  474. /// <param name="intAttachmentNumber">attachment index in the attachments collection</param>
  475. /// <returns>attachment</returns>
  476. public Attachment GetAttachment(int intAttachmentNumber)
  477. {
  478. if(intAttachmentNumber<0 || intAttachmentNumber>_attachmentCount || intAttachmentNumber>_attachments.Count)
  479. {
  480. Utility.LogError("GetAttachment():attachment not exist");
  481. throw new ArgumentOutOfRangeException("intAttachmentNumber");
  482. }
  483. return (Attachment)_attachments[intAttachmentNumber];
  484. }
  485. /// <summary>
  486. /// New Message
  487. /// </summary>
  488. /// <param name="blnFinish">reference for the finishing state</param>
  489. /// <param name="strBasePath">path to extract MS-TNEF attachment files</param>
  490. /// <param name="blnAutoDecodeMSTNEF">whether auto decoding MS-TNEF attachments</param>
  491. /// <param name="strMessage">raw message content</param>
  492. /// <param name="blnOnlyHeader">whether only decode the header without body</param>
  493. /// <returns>construction result whether successfully new a message</returns>
  494. private bool NewMessage(ref bool blnFinish, string strBasePath, bool blnAutoDecodeMSTNEF, string strMessage, bool blnOnlyHeader)
  495. {
  496. StringReader srdReader=new StringReader(strMessage);
  497. StringBuilder sbdBuilder=new StringBuilder();
  498. _basePath=strBasePath;
  499. _autoDecodeMSTNEF=blnAutoDecodeMSTNEF;
  500. _rawMessage=strMessage;
  501. string strLine=srdReader.ReadLine();
  502. while(Utility.IsNotNullTextEx(strLine))
  503. {
  504. sbdBuilder.Append(strLine + "rn");
  505. ParseHeader(sbdBuilder,srdReader,ref strLine);
  506. if(Utility.IsOrNullTextEx(strLine))
  507. break;
  508. else
  509. strLine=srdReader.ReadLine();
  510. }
  511. _rawHeader=sbdBuilder.ToString();
  512. SetAttachmentBoundry2(_rawHeader);
  513. if(_contentLength==0)
  514. _contentLength=strMessage.Length;//_rawMessageBody.Length;
  515. if(blnOnlyHeader==false)
  516. {
  517. _rawMessageBody=srdReader.ReadToEnd().Trim();
  518. //the auto reply mail by outlook uses ms-tnef format
  519. if((_hasAttachment==true && _attachmentboundry!=null)||MIMETypes.IsMSTNEF(_contentType))
  520. {
  521. set_attachments();
  522. if (this.Attachments.Count>0)
  523. {
  524. Attachment at=this.GetAttachment(0);
  525. if(at!=null&&at.NotAttachment)
  526. this.GetMessageBody(at.DecodeAsText());
  527. else
  528. {}
  529. //in case body parts as text[0] html[1]
  530. if(this.Attachments.Count>1&&!this.IsReport())
  531. {
  532. at=this.GetAttachment(1);
  533. if(at!=null&&at.NotAttachment)
  534. this.GetMessageBody(at.DecodeAsText());
  535. else
  536. {}
  537. }
  538. }
  539. else
  540. {}
  541. }
  542. else
  543. {
  544. GetMessageBody(_rawMessageBody);
  545. }
  546. }
  547. blnFinish=true;
  548. return true;
  549. }
  550. /// <summary>
  551. /// parse message body
  552. /// </summary>
  553. /// <param name="strBuffer">raw message body</param>
  554. /// <returns>message body</returns>
  555. public string GetTextBody(string strBuffer)
  556. {
  557. if(strBuffer.EndsWith("rn."))
  558. return strBuffer.Substring(0,strBuffer.Length-"rn.".Length);
  559. else
  560. return strBuffer;
  561. }
  562. /// <summary>
  563. /// parse message body
  564. /// </summary>
  565. /// <param name="strBuffer">raw message body</param>
  566. public void GetMessageBody(string strBuffer)
  567. {
  568. int end, begin;
  569. string body;
  570. string encoding="";
  571. begin = end = 0;
  572. _messageBody.Clear();
  573. try
  574. {
  575. if(Utility.IsOrNullTextEx(strBuffer))
  576. return;
  577. else if(Utility.IsOrNullTextEx(_contentType) && _contentTransferEncoding==null)
  578. {
  579. _messageBody.Add(GetTextBody(strBuffer));
  580. }
  581. else if(_contentType!=null && _contentType.IndexOf("digest") >= 0)
  582. {
  583. // this is a digest method
  584. //ParseDigestMessage(strBuffer);
  585. _messageBody.Add(GetTextBody(strBuffer));
  586. }
  587. else if(_attachmentboundry2==null)
  588. {
  589. body=GetTextBody(strBuffer);
  590. if(Utility.IsQuotedPrintable(_contentTransferEncoding))
  591. {
  592. body=DecodeQP.ConvertHexContent(body);
  593. }
  594. else if(Utility.IsBase64(_contentTransferEncoding))
  595. {
  596. body=Utility.deCodeB64s(Utility.RemoveNonB64(body));
  597. }
  598. else if(Utility.IsNotNullText(_contentCharset))
  599. {
  600. body=Encoding.GetEncoding(_contentCharset).GetString(Encoding.Default.GetBytes(body));
  601. }
  602. _messageBody.Add(Utility.RemoveNonB64(body));
  603. }
  604. else
  605. {
  606. begin =0;
  607. while(begin!=-1)
  608. {
  609. // find "rnrn" denoting end of header
  610. begin = strBuffer.IndexOf("--" + _attachmentboundry2,begin);
  611. if(begin!=-1)
  612. {
  613. encoding=MIMETypes.GetContentTransferEncoding(strBuffer,begin);
  614. begin = strBuffer.IndexOf("rnrn",begin+1);//strBuffer.LastIndexOfAny(ALPHABET.ToCharArray());
  615. // find end of text
  616. end = strBuffer.IndexOf("--" + _attachmentboundry2,begin+1);
  617. if(begin!=-1)
  618. {
  619. if(end!=-1)
  620. {
  621. begin += 4;
  622. if(begin>=end)
  623. continue;
  624. else if (this._contentEncoding!=null && this._contentEncoding.IndexOf("8bit")!=-1)
  625. body=Utility.Change(strBuffer.Substring(begin, end - begin-2 ),_contentCharset);
  626. else
  627. body=strBuffer.Substring(begin, end - begin-2);
  628. }
  629. else
  630. {
  631. body=strBuffer.Substring(begin);
  632. }
  633. if(Utility.IsQuotedPrintable(encoding))
  634. {
  635. string ret=body;
  636. ret=DecodeQP.ConvertHexContent(ret);
  637. _messageBody.Add(ret);
  638. }
  639. else if(Utility.IsBase64(encoding))
  640. {
  641. string ret=Utility.RemoveNonB64(body);
  642. ret=Utility.deCodeB64s(ret);
  643. if(ret!="")
  644. _messageBody.Add(ret);
  645. else
  646. _messageBody.Add(body);
  647. }
  648. else
  649. _messageBody.Add(body);
  650. if(end==-1)break;
  651. }
  652. else
  653. {
  654. break;
  655. }
  656. }
  657. else
  658. {
  659. if(_messageBody.Count==0)
  660. {
  661. _messageBody.Add(strBuffer);
  662. }
  663. break;
  664. }
  665. }
  666. }
  667. }
  668. catch(Exception e)
  669. {
  670. Utility.LogError("GetMessageBody():"+e.Message);
  671. _messageBody.Add(Utility.deCodeB64s(strBuffer));
  672. }
  673. if(_messageBody.Count>1)
  674. _html=true;
  675. }
  676. /// <summary>
  677. /// verify if the message is a report
  678. /// </summary>
  679. /// <returns>if it is a report message, return true, else, false</returns>
  680. public bool IsReport()
  681. {
  682. if(Utility.IsNotNullText(_contentType))
  683. return (_contentType.ToLower().IndexOf("report".ToLower())!=-1);
  684. else
  685. return false;
  686. }
  687. /// <summary>
  688. /// verify if the attachment is MIME Email file
  689. /// </summary>
  690. /// <param name="attItem">attachment</param>
  691. /// <returns>if MIME Email file, return true, else, false</returns>
  692. public bool IsMIMEMailFile(Attachment attItem)
  693. {
  694. try
  695. {
  696. return (attItem.ContentFileName.ToLower().EndsWith(".eml".ToLower()) || attItem.ContentType.ToLower()=="message/rfc822".ToLower());
  697. }
  698. catch(Exception e)
  699. {
  700. Utility.LogError("IsMIMEMailFile():"+e.Message);
  701. return false;
  702. }
  703. }
  704. /// <summary>
  705. /// translate pictures url within the body
  706. /// </summary>
  707. /// <param name="strBody">message body</param>
  708. /// <param name="hsbFiles">pictures collection</param>
  709. /// <returns>translated message body</returns>
  710. public string TranslateHTMLPictureFiles(string strBody, Hashtable hsbFiles)
  711. {
  712. try
  713. {
  714. for(int i=0;i<this.AttachmentCount;i++)
  715. {
  716.                     Attachment att = this.GetAttachment(i);
  717. if(Utility.IsPictureFile(att.ContentFileName)==true)
  718. {
  719. if(Utility.IsNotNullText(att.ContentID))
  720. //support for embedded pictures
  721. strBody=strBody.Replace("cid:"+att.ContentID,hsbFiles[att.ContentFileName].ToString());
  722. strBody=strBody.Replace(att.ContentFileName,hsbFiles[att.ContentFileName].ToString());
  723. }
  724. }
  725. }
  726. catch(Exception e)
  727. {
  728. Utility.LogError("TranslateHTMLPictureFiles():"+e.Message);
  729. }
  730. return strBody;
  731. }
  732. /// <summary>
  733. /// translate pictures url within the body
  734. /// </summary>
  735. /// <param name="strBody">message body</param>
  736. /// <param name="strPath">path of the pictures</param>
  737. /// <returns>translated message body</returns>
  738. public string TranslateHTMLPictureFiles(string strBody, string strPath)
  739. {
  740. try
  741. {
  742. if(!strPath.EndsWith("\"))
  743. {
  744. strPath+="\";
  745. }
  746. for(int i=0;i<this.AttachmentCount;i++)
  747. {
  748. Attachment att=this.GetAttachment(i);
  749. if(Utility.IsPictureFile(att.ContentFileName)==true)
  750. {
  751. if(Utility.IsNotNullText(att.ContentID))
  752. //support for embedded pictures
  753. strBody=strBody.Replace("cid:"+att.ContentID,strPath+att.ContentFileName);
  754. strBody=strBody.Replace(att.ContentFileName,strPath+att.ContentFileName);
  755. }
  756. }
  757. }
  758. catch(Exception e)
  759. {
  760. Utility.LogError("TranslateHTMLPictureFiles():"+e.Message);
  761. }
  762. return strBody;
  763. }
  764. /// <summary>
  765. /// Get the proper attachment file name
  766. /// </summary>
  767. /// <param name="attItem">attachment</param>
  768. /// <returns>propery attachment file name</returns>
  769. public string GetAttachmentFileName(Attachment attItem)
  770. {
  771. int items=0;
  772. //return unique body file names
  773. for(int i=0;i<_attachments.Count;i++)
  774. {
  775. if(attItem.ContentFileName==attItem.DefaultFileName)
  776. {
  777. items++;
  778. attItem.ContentFileName=attItem.DefaultFileName2.Replace("*",items.ToString());
  779. }
  780. }
  781. string name=attItem.ContentFileName;
  782.                 
  783. return (name==null||name==""?(IsReport()==true?(this.IsMIMEMailFile(attItem)==true?attItem.DefaultMIMEFileName:attItem.DefaultReportFileName):(attItem.ContentID!=null?attItem.ContentID:attItem.DefaultFileName)):name);
  784. }
  785. /// <summary>
  786. /// save attachments to a defined path
  787. /// </summary>
  788. /// <param name="strPath">path to have attachments to be saved to</param>
  789. /// <returns>true if save successfully, false if failed</returns>
  790. public bool SaveAttachments(string strPath)
  791. {
  792. if(Utility.IsNotNullText(strPath))
  793. {
  794. try
  795. {
  796. bool blnRet=true;
  797. if(!strPath.EndsWith("\"))
  798. {
  799. strPath+="\";
  800. }
  801. for(int i=0;i<this.Attachments.Count;i++)
  802. {
  803.                         
  804. Attachment att=GetAttachment(i);
  805.                         if (att.NotAttachment)
  806.                             continue;
  807. blnRet=SaveAttachment(att,strPath+GetAttachmentFileName(att));
  808. if(!blnRet)
  809. break;
  810. }
  811. return blnRet;
  812. }
  813. catch(Exception e)
  814. {
  815. Utility.LogError(e.Message);
  816. return false;
  817. }
  818. }
  819. else
  820. return false;
  821. }
  822. /// <summary>
  823. /// save attachment to file
  824. /// </summary>
  825. /// <param name="attItem">Attachment</param>
  826. /// <param name="strFileName">File to be saved to</param>
  827. /// <returns>true if save successfully, false if failed</returns>
  828. public bool SaveAttachment(Attachment attItem, string strFileName)
  829. {
  830. byte[] da;
  831. try
  832. {
  833. // FileStream fs=File.Create(strFileName);
  834. // byte[] da;
  835. // if(attItem.ContentFileName.Length>0)
  836. // {
  837. // da=attItem.DecodedAttachment;
  838. // }
  839. // else
  840. // {
  841. // this.GetMessageBody(attItem.DecodeAttachmentAsText());
  842. // da=Encoding.Default.GetBytes((string)this.MessageBody[this.MessageBody.Count-1]);
  843. // }
  844. // fs.Write(da,0,da.Length);
  845. // fs.Close();
  846. // return true;
  847. if(attItem.InBytes)
  848. {
  849. da=attItem.RawBytes;
  850. }
  851. else if(attItem.ContentFileName.Length>0)
  852. {
  853. da=attItem.DecodedAttachment;
  854. }
  855. else if(attItem.ContentType.ToLower()=="message/rfc822".ToLower())
  856. {
  857. da=Encoding.Default.GetBytes(attItem.RawAttachment);
  858. }
  859. else
  860. {
  861. this.GetMessageBody(attItem.DecodeAsText());
  862. da=Encoding.Default.GetBytes((string)this.MessageBody[this.MessageBody.Count-1]);
  863. }
  864. return Utility.SaveByteContentToFile(strFileName,da);
  865. }
  866. catch
  867. {
  868. /*Utility.LogError("SaveAttachment():"+e.Message);
  869. return false;*/
  870. da=Encoding.Default.GetBytes(attItem.RawAttachment);
  871. return Utility.SaveByteContentToFile(strFileName,da);
  872. }
  873. }
  874. /// <summary>
  875. /// set attachments
  876. /// </summary>
  877. private void set_attachments()
  878. {
  879. int indexOf_attachmentstart=0;
  880. int indexOfAttachmentEnd=0;
  881. bool processed=false;
  882. Attachment att=null;
  883. SetAttachmentBoundry2(_rawMessageBody);
  884. while(!processed)
  885. {
  886. if(Utility.IsNotNullText(_attachmentboundry))
  887. {
  888. indexOf_attachmentstart=_rawMessageBody.IndexOf(_attachmentboundry,indexOf_attachmentstart)+_attachmentboundry.Length;
  889. if(_rawMessageBody==""||indexOf_attachmentstart<0)return;
  890. indexOfAttachmentEnd=_rawMessageBody.IndexOf(_attachmentboundry,indexOf_attachmentstart+1);
  891. }
  892. else
  893. {
  894. indexOfAttachmentEnd=-1;
  895. }
  896. //if(indexOfAttachmentEnd<0)return;
  897. if(indexOfAttachmentEnd!=-1)
  898. {
  899. }
  900. else if(indexOfAttachmentEnd==-1&&!processed&&_attachmentCount==0) 
  901. {
  902. processed=true;
  903. indexOfAttachmentEnd=_rawMessageBody.Length;
  904. }
  905. else
  906. return;
  907. if(indexOf_attachmentstart==indexOfAttachmentEnd-9)
  908. {
  909. indexOf_attachmentstart=0;
  910. processed=true;
  911. }
  912. string strLine=_rawMessageBody.Substring(indexOf_attachmentstart,(indexOfAttachmentEnd-indexOf_attachmentstart-2));            
  913. bool isMSTNEF;
  914. isMSTNEF=MIMETypes.IsMSTNEF(_contentType);
  915. att=new Attachment(strLine.Trim(),_contentType,!isMSTNEF);
  916. //ms-tnef format might contain multiple attachments
  917. if(MIMETypes.IsMSTNEF(att.ContentType) && AutoDecodeMSTNEF && !isMSTNEF) 
  918. {
  919. Utility.LogError("set_attachments():found ms-tnef file");
  920. TNEFParser tnef=new TNEFParser();
  921. TNEFAttachment tatt=new TNEFAttachment();
  922. Attachment attNew=null;
  923.                     tnef.Verbose = false;
  924.                     tnef.BasePath = this.BasePath;
  925.                     //tnef.LogFilePath=this.BasePath + "OpenPOP.TNEF.log";
  926.                     if (tnef.OpenTNEFStream(att.DecodedAsBytes()))
  927.                     {
  928.                         if (tnef.Parse())
  929.                         {
  930.                             for (IDictionaryEnumerator i = tnef.Attachments().GetEnumerator(); i.MoveNext(); )
  931.                             {
  932.                                 tatt = (TNEFAttachment)i.Value;
  933.                                 attNew = new Attachment(tatt.FileContent, tatt.FileLength, tatt.FileName, MIMETypes.GetMimeType(tatt.FileName));
  934.                                 _attachmentCount++;
  935.                                 _attachments.Add(attNew);
  936.                             }
  937.                         }
  938.                         else
  939.                             Utility.LogError("set_attachments():ms-tnef file parse failed");
  940.                     }
  941.                     else
  942.                         Utility.LogError("set_attachments():ms-tnef file open failed");
  943.                 }
  944.                 else
  945.                 {
  946.                     _attachmentCount++;
  947.                     if (!att.NotAttachment)
  948.                     {
  949.                         _hasRealAttachment = true;
  950.                         _realAttachmentCount++;
  951.                     }
  952.                     _attachments.Add(att);
  953.                 }
  954. indexOf_attachmentstart++;
  955. }
  956. }
  957. /// <summary>
  958. /// Set alternative attachment boundry
  959. /// </summary>
  960. /// <param name="strBuffer">raw message</param>
  961. private void SetAttachmentBoundry2(string strBuffer)
  962. {
  963. int indexOfAttachmentBoundry2Begin=0;
  964. int indexOfAttachmentBoundry2End=0;
  965. indexOfAttachmentBoundry2Begin=strBuffer.ToLower().IndexOf("Multipart/Alternative".ToLower());
  966. if(indexOfAttachmentBoundry2Begin!=-1)
  967. {
  968. /* indexOfAttachmentBoundry2Begin=strBuffer.IndexOf("boundary="");
  969. indexOfAttachmentBoundry2End=strBuffer.IndexOf(""",indexOfAttachmentBoundry2Begin+10);
  970. if(indexOfAttachmentBoundry2Begin!=-1&&indexOfAttachmentBoundry2End!=-1)
  971. _attachmentboundry2=strBuffer.Substring(indexOfAttachmentBoundry2Begin+10,indexOfAttachmentBoundry2End-indexOfAttachmentBoundry2Begin-10).Trim();
  972. */
  973. indexOfAttachmentBoundry2Begin=strBuffer.IndexOf("boundary=");
  974. if(indexOfAttachmentBoundry2Begin!=-1)
  975. {
  976. int p=strBuffer.IndexOf("rn",indexOfAttachmentBoundry2Begin);
  977. string s=strBuffer.Substring(indexOfAttachmentBoundry2Begin+29,4);
  978. indexOfAttachmentBoundry2End=strBuffer.IndexOf("rn",indexOfAttachmentBoundry2Begin+9);
  979. if(indexOfAttachmentBoundry2End==-1)
  980. indexOfAttachmentBoundry2End=strBuffer.Length;
  981. _attachmentboundry2=Utility.RemoveQuote(strBuffer.Substring(indexOfAttachmentBoundry2Begin+9,indexOfAttachmentBoundry2End-indexOfAttachmentBoundry2Begin-9));
  982. }
  983. }
  984. else
  985. {
  986. _attachmentboundry2=_attachmentboundry;
  987. }
  988. }
  989. /// <summary>
  990. /// Save message content to eml file
  991. /// </summary>
  992. /// <param name="strFile"></param>
  993. /// <returns></returns>
  994. public bool SaveToMIMEEmailFile(string strFile,bool blnReplaceExists)
  995. {
  996. return Utility.SavePlainTextToFile(strFile,_rawMessage,blnReplaceExists);
  997. }
  998. /// <summary>
  999. /// parse multi-line header
  1000. /// </summary>
  1001. /// <param name="sbdBuilder">string builder to hold header content</param>
  1002. /// <param name="srdReader">string reader to get each line of the header</param>
  1003. /// <param name="strValue">first line content</param>
  1004. /// <param name="strLine">reference header line</param>
  1005. /// <param name="alCollection">collection to hold every content line</param>
  1006. private void ParseStreamLines(StringBuilder sbdBuilder
  1007. ,StringReader srdReader
  1008. ,string strValue
  1009. ,ref string strLine
  1010. ,ArrayList alCollection)
  1011. {
  1012. string strFormmated;
  1013. int intLines=0;
  1014. alCollection.Add(strValue);
  1015. sbdBuilder.Append(strLine);
  1016. strLine=srdReader.ReadLine();
  1017. while(strLine.Trim()!="" && (strLine.StartsWith("t") || strLine.StartsWith(" ")))
  1018. {
  1019. strFormmated=strLine.Substring(1);
  1020. alCollection.Add(Utility.DecodeLine(strFormmated));
  1021. sbdBuilder.Append(strLine);
  1022. strLine=srdReader.ReadLine();
  1023. intLines++;
  1024. }
  1025. if(strLine!="")
  1026. {
  1027. sbdBuilder.Append(strLine);
  1028. }
  1029. else
  1030. if(intLines==0)
  1031. {
  1032. strLine=srdReader.ReadLine();
  1033. sbdBuilder.Append(strLine);
  1034. }
  1035. ParseHeader(sbdBuilder,srdReader,ref strLine);
  1036. }
  1037. /// <summary>
  1038. /// parse multi-line header
  1039. /// </summary>
  1040. /// <param name="sbdBuilder">string builder to hold header content</param>
  1041. /// <param name="srdReader">string reader to get each line of the header</param>
  1042. /// <param name="strName">collection key</param>
  1043. /// <param name="strValue">first line content</param>
  1044. /// <param name="strLine">reference header line</param>
  1045. /// <param name="hstCollection">collection to hold every content line</param>
  1046. private void ParseStreamLines(StringBuilder sbdBuilder
  1047. ,StringReader srdReader
  1048. ,string strName
  1049. ,string strValue
  1050. ,ref string strLine
  1051. ,Hashtable hstCollection)
  1052. {
  1053. string strFormmated;
  1054. string strReturn=strValue;
  1055. int intLines=0;
  1056. //sbdBuilder.Append(strLine);
  1057. strLine=srdReader.ReadLine();
  1058. while(strLine.Trim()!="" && (strLine.StartsWith("t") || strLine.StartsWith(" ")))
  1059. {
  1060. strFormmated=strLine.Substring(1);
  1061. strReturn+=Utility.DecodeLine(strFormmated);
  1062. sbdBuilder.Append(strLine + "rn");
  1063. strLine=srdReader.ReadLine();
  1064. intLines++;
  1065. }
  1066. if(!hstCollection.ContainsKey(strName))
  1067. hstCollection.Add(strName,strReturn);
  1068. if(strLine!="")
  1069. {
  1070. sbdBuilder.Append(strLine + "rn");
  1071. }
  1072. else
  1073. if(intLines==0)
  1074. {
  1075. // strLine=srdReader.ReadLine();
  1076. // sbdBuilder.Append(strLine + "rn");
  1077. }
  1078. ParseHeader(sbdBuilder,srdReader,ref strLine);
  1079. }
  1080. /// <summary>
  1081. /// parse multi-line header
  1082. /// </summary>
  1083. /// <param name="sbdBuilder">string builder to hold header content</param>
  1084. /// <param name="srdReader">string reader to get each line of the header</param>
  1085. /// <param name="strValue">first line content</param>
  1086. /// <param name="strLine">reference header line</param>
  1087. /// <param name="strReturn">return value</param>
  1088. /// <param name="blnLineDecode">decode each line</param>
  1089. private void ParseStreamLines(StringBuilder sbdBuilder
  1090. ,StringReader srdReader
  1091. ,string strValue
  1092. ,ref string strLine
  1093. ,ref string strReturn
  1094. ,bool blnLineDecode)
  1095. {
  1096. string strFormmated;
  1097. int intLines=0;
  1098. strReturn=strValue;
  1099. sbdBuilder.Append(strLine + "rn");
  1100. if(blnLineDecode==true)
  1101. strReturn=Utility.DecodeLine(strReturn);
  1102. strLine=srdReader.ReadLine();
  1103. while(strLine.Trim()!="" && (strLine.StartsWith("t") || strLine.StartsWith(" ")))
  1104. {
  1105. strFormmated=strLine.Substring(1);
  1106. strReturn+=(blnLineDecode==true?Utility.DecodeLine(strFormmated):"rn"+strFormmated);
  1107. sbdBuilder.Append(strLine + "rn");
  1108. strLine=srdReader.ReadLine();
  1109. intLines++;
  1110. }
  1111. if(strLine!="")
  1112. {
  1113. sbdBuilder.Append(strLine + "rn");
  1114. }
  1115. else
  1116. if(intLines==0)
  1117. {
  1118. strLine=srdReader.ReadLine();
  1119. sbdBuilder.Append(strLine + "rn");
  1120. }
  1121. if(!blnLineDecode)
  1122. {
  1123. strReturn=Utility.RemoveWhiteBlanks(Utility.DecodeText(strReturn));
  1124. }
  1125. ParseHeader(sbdBuilder,srdReader,ref strLine);
  1126. }
  1127. /// <summary>
  1128. /// Parse the headers populating respective member fields
  1129. /// </summary>
  1130. /// <param name="sbdBuilder">string builder to hold the header content</param>
  1131. /// <param name="srdReader">string reader to get each line of the header</param>
  1132. /// <param name="strLine">reference header line</param>
  1133. private void ParseHeader(StringBuilder sbdBuilder,StringReader srdReader,ref string strLine)
  1134. {
  1135. string []array=Utility.GetHeadersValue(strLine);//Regex.Split(strLine,":");
  1136. switch(array[0].ToUpper())
  1137. {
  1138. case "TO":
  1139. _to=array[1].Split(',');
  1140. for(int i=0;i<_to.Length;i++)
  1141. {
  1142. _to[i]=Utility.DecodeLine(_to[i].Trim());
  1143. }
  1144. break;
  1145. case "CC":
  1146. _cc=array[1].Split(',');
  1147. for(int i=0;i<_cc.Length;i++)
  1148. {
  1149. _cc[i]=Utility.DecodeLine(_cc[i].Trim());
  1150. }
  1151. break;
  1152. case "BCC":
  1153. _bcc=array[1].Split(',');
  1154. for(int i=0;i<_bcc.Length;i++)
  1155. {
  1156. _bcc[i]=Utility.DecodeLine(_bcc[i].Trim());
  1157. }
  1158. break;
  1159. case "FROM":
  1160. Utility.ParseEmailAddress(array[1],ref _from,ref _fromEmail);
  1161. break;
  1162. case "REPLY-TO":
  1163. Utility.ParseEmailAddress(array[1],ref _replyTo,ref _replyToEmail);
  1164. break;
  1165. case "KEYWORDS": //ms outlook keywords
  1166. ParseStreamLines(sbdBuilder,srdReader,array[1].Trim(),ref strLine,_keywords);
  1167. break;
  1168. case "RECEIVED":
  1169. ParseStreamLines(sbdBuilder,srdReader,array[1].Trim(),ref strLine,ref _received,true);
  1170. break;
  1171. case "IMPORTANCE":
  1172. _importance=array[1].Trim();
  1173. break;
  1174. case "DISPOSITION-NOTIFICATION-TO":
  1175. _dispositionNotificationTo=array[1].Trim();
  1176. break;
  1177. case "MIME-VERSION":
  1178. _mimeVersion=array[1].Trim();
  1179. break;
  1180. case "SUBJECT":
  1181. case "THREAD-TOPIC":
  1182. string strRet=null;
  1183. for(int i=1;i<array.Length;i++)
  1184. {
  1185. strRet+=array[i];
  1186. }
  1187. ParseStreamLines(sbdBuilder,srdReader,strRet,ref strLine,ref _subject,false);
  1188. break;
  1189. case "RETURN-PATH":
  1190. _returnPath=array[1].Trim().Trim('>').Trim('<');
  1191. break;
  1192. case "MESSAGE-ID":
  1193. _messageID=array[1].Trim().Trim('>').Trim('<');
  1194. break;
  1195. case "DATE":
  1196. for(int i=1;i<array.Length;i++)
  1197. {
  1198. _dateTimeInfo+=array[i];
  1199. }
  1200. _dateTimeInfo=_dateTimeInfo.Trim();
  1201. _date=Utility.ParseEmailDate(_dateTimeInfo);
  1202. break;
  1203. case "CONTENT-LENGTH":
  1204. _contentLength=Convert.ToInt32(array[1]);
  1205. break;
  1206. case "CONTENT-TRANSFER-ENCODING":
  1207. _contentTransferEncoding=array[1].Trim();
  1208. break;
  1209. case "CONTENT-TYPE":
  1210. //if already content type has been assigned
  1211. if(_contentType!=null)
  1212. return;
  1213. strLine=array[1];
  1214. _contentType=strLine.Split(';')[0];
  1215. _contentType=_contentType.Trim();
  1216. int intCharset=strLine.IndexOf("charset=");
  1217. if(intCharset!=-1)
  1218. {
  1219. int intBound2=strLine.ToLower().IndexOf(";",intCharset+8);
  1220. if(intBound2==-1)
  1221. intBound2=strLine.Length;
  1222. intBound2-=(intCharset+8);
  1223. _contentCharset=strLine.Substring(intCharset+8,intBound2);
  1224. _contentCharset=Utility.RemoveQuote(_contentCharset);
  1225. }
  1226. else 
  1227. {
  1228. intCharset=strLine.ToLower().IndexOf("report-type=".ToLower());
  1229. if(intCharset!=-1)
  1230. {
  1231. int intPos=strLine.IndexOf(";",intCharset+13);
  1232. _reportType=strLine.Substring(intCharset+12,intPos-intCharset-13);
  1233. }
  1234. else if(strLine.ToLower().IndexOf("boundary=".ToLower())==-1)
  1235. {
  1236. strLine=srdReader.ReadLine();
  1237. if (strLine=="")
  1238. return;
  1239. intCharset=strLine.ToLower().IndexOf("charset=".ToLower());
  1240. if(intCharset!=-1)
  1241. _contentCharset=strLine.Substring(intCharset+9,strLine.Length-intCharset-10);
  1242. else if(strLine.IndexOf(":")!=-1)
  1243. {
  1244. sbdBuilder.Append(strLine + "rn");
  1245. ParseHeader(sbdBuilder,srdReader,ref strLine);
  1246. return;
  1247. }
  1248. else
  1249. {
  1250. sbdBuilder.Append(strLine + "rn");
  1251. }
  1252. }
  1253. }
  1254. if(_contentType=="text/plain")
  1255. return;
  1256. else if(_contentType.ToLower()=="text/html"||_contentType.ToLower().IndexOf("multipart/")!=-1)
  1257. _html=true;
  1258. if(strLine.Trim().Length==_contentType.Length+1 || strLine.ToLower().IndexOf("boundary=".ToLower())==-1)
  1259. {
  1260. strLine=srdReader.ReadLine();
  1261. if(strLine==null||strLine==""||strLine.IndexOf(":")!=-1)
  1262. {
  1263. sbdBuilder.Append(strLine + "rn");
  1264. ParseHeader(sbdBuilder,srdReader,ref strLine);
  1265. return;
  1266. }
  1267. else
  1268. {
  1269. sbdBuilder.Append(strLine + "rn");
  1270. }
  1271. if(strLine.ToLower().IndexOf("boundary=".ToLower())==-1)
  1272. {
  1273. _attachmentboundry=srdReader.ReadLine();
  1274. sbdBuilder.Append(_attachmentboundry+"rn");
  1275. }
  1276. _attachmentboundry=strLine;
  1277. }
  1278. else
  1279. {
  1280. /*if(strLine.IndexOf(";")!=-1)
  1281. _attachmentboundry=strLine.Split(';')[1];
  1282. else*/
  1283. _attachmentboundry=strLine;
  1284. }
  1285. int intBound=_attachmentboundry.ToLower().IndexOf("boundary=");
  1286. if(intBound!=-1)
  1287. {
  1288. int intBound2=_attachmentboundry.ToLower().IndexOf(";",intBound+10);
  1289. if(intBound2==-1)
  1290. intBound2=_attachmentboundry.Length;
  1291. intBound2-=(intBound+9);
  1292. _attachmentboundry=_attachmentboundry.Substring(intBound+9,intBound2);
  1293. }
  1294. _attachmentboundry=Utility.RemoveQuote(_attachmentboundry);
  1295. _hasAttachment=true;
  1296. break;
  1297. default:
  1298. if(array.Length>1) //here we parse all custom headers
  1299. {
  1300. string headerName=array[0].Trim();
  1301. if(headerName.ToUpper().StartsWith("X")) //every custom header starts with "X"
  1302. {
  1303. ParseStreamLines(sbdBuilder,srdReader,headerName,array[1].Trim(),ref strLine,_customHeaders);
  1304. }
  1305. }
  1306. break;
  1307. }
  1308. }
  1309. }
  1310. }