现在的位置: 首页 > 综合 > 正文

给 OpenPOP.Net 加一个小功能,可用于收取邮件时监测数据流量!

2012年11月06日 ⁄ 综合 ⁄ 共 40634字 ⁄ 字号 评论关闭

/*

最近写了一个自动收邮件的机器人,原来一开始偷懒"娶"了 COM 组件 JMail:

封装 JMail 4.4 的 POP3 为 .Net 组件 (.dll 程序集),实现 "邮件(附件) 到达" 等 "事件"!

后来经人介绍认识了 OpenPOP.Net

我就移情别恋,再后来我们就相爱了,再后来我就修理她:

加一个小功能(红色字体代码部分),可用于收取邮件时监测数据流量!

老规矩: 我的代码随便 Copy & Paste 到任意一个 .cs 文件中 csc 即可测试! (结构不够清晰,目的就是方便测试代码)

*/

//OpenPOP.Net

namespace OpenPOP.MIMEParser

{

 using System;

 using System.IO;

 using System.Text;

 using System.Text.RegularExpressions;

 using System.Collections;

 using System.Globalization;

 /// <summary>

 /// Summary description for Attachment.

 /// </summary>

 public class Attachment : IComparable

 {

  #region Member Variables

  private string _contentType = null;

  private string _contentCharset = null;

  private string _contentFormat = null;

  private string _contentTransferEncoding = null;

  private string _contentDescription = null;

  private string _contentDisposition = null;

  private string _contentFileName = "";

  private string _defaultFileName = "body.htm";

  private string _defaultFileName2 = "body*.htm";

  private string _defaultReportFileName = "report.htm";

  private string _defaultMIMEFileName = "body.eml";

  private string _defaultMSTNEFFileName = "winmail.dat";

  private string _contentID = null;

  private long _contentLength = 0;

  private string _rawAttachment = null;

  private bool _inBytes = false;

  private byte[] _rawBytes = null;

  #endregion

  #region Properties

  /// <summary>

  /// raw attachment content bytes

  /// </summary>

  public byte[] RawBytes

  {

   get

   {

    return _rawBytes;

   }

   set

   {

    _rawBytes = value;

   }

  }

  /// <summary>

  /// whether attachment is in bytes

  /// </summary>

  public bool InBytes

  {

   get

   {

    return _inBytes;

   }

   set

   {

    _inBytes = value;

   }

  }

  /// <summary>

  /// Content length

  /// </summary>

  public long ContentLength

  {

   get

   {

    return _contentLength;

   }

  }

  /// <summary>

  /// verify the attachment whether it is a real attachment or not

  /// </summary>

  /// <remarks>this is so far not comprehensive and needs more work to finish</remarks>

  public bool NotAttachment

  {

   get

   {

    /*    if (_contentDisposition==null||_contentType==null)

         return true;

        else

         return (_contentDisposition.IndexOf("attachment")==-1 && _contentType.IndexOf("text/plain")!=-1); */

    /*    if (_contentType==null)

         return true;

        else

         return (_contentFileName!="");*/

    if ((_contentType == null || _contentFileName == "") && _contentID == null) //&&_contentType.ToLower().IndexOf("text/")!=-1)

     return true;

    else

     return false;

   }

  }

  /// <summary>

  /// Content format

  /// </summary>

  public string ContentFormat

  {

   get

   {

    return _contentFormat;

   }

  }

  /// <summary>

  /// Content charset

  /// </summary>

  public string ContentCharset

  {

   get

   {

    return _contentCharset;

   }

  }

  /// <summary>

  /// default file name

  /// </summary>

  public string DefaultFileName

  {

   get

   {

    return _defaultFileName;

   }

   set

   {

    _defaultFileName = value;

   }

  }

  /// <summary>

  /// default file name 2

  /// </summary>

  public string DefaultFileName2

  {

   get

   {

    return _defaultFileName2;

   }

   set

   {

    _defaultFileName2 = value;

   }

  }

  /// <summary>

  /// default report file name

  /// </summary>

  public string DefaultReportFileName

  {

   get

   {

    return _defaultReportFileName;

   }

   set

   {

    _defaultReportFileName = value;

   }

  }

  /// <summary>

  /// default MIME File Name

  /// </summary>

  public string DefaultMIMEFileName

  {

   get

   {

    return _defaultMIMEFileName;

   }

   set

   {

    _defaultMIMEFileName = value;

   }

  }

  /// <summary>

  /// Content Type

  /// </summary>

  public string ContentType

  {

   get

   {

    return _contentType;

   }

  }

  /// <summary>

  /// Content Transfer Encoding

  /// </summary>

  public string ContentTransferEncoding

  {

   get

   {

    return _contentTransferEncoding;

   }

  }

  /// <summary>

  /// Content Description

  /// </summary>

  public string ContentDescription

  {

   get

   {

    return _contentDescription;

   }

  }

  /// <summary>

  /// Content File Name

  /// </summary>

  public string ContentFileName

  {

   get

   {

    return _contentFileName;

   }

   set

   {

    _contentFileName = value;

   }

  }

  /// <summary>

  /// Content Disposition

  /// </summary>

  public string ContentDisposition

  {

   get

   {

    return _contentDisposition;

   }

  }

  /// <summary>

  /// Content ID

  /// </summary>

  public string ContentID

  {

   get

   {

    return _contentID;

   }

  }

  /// <summary>

  /// Raw Attachment

  /// </summary>

  public string RawAttachment

  {

   get

   {

    return _rawAttachment;

   }

  }

  /// <summary>

  /// decoded attachment in bytes

  /// </summary>

  public byte[] DecodedAttachment

  {

   get

   {

    return DecodedAsBytes();

   }

  }

  #endregion

  /// <summary>

  /// release all objects

  /// </summary>

  ~Attachment()

  {

   _rawBytes = null;

   _rawAttachment = null;

  }

  /// <summary>

  /// New Attachment

  /// </summary>

  /// <param name="bytAttachment">attachment bytes content</param>

  /// <param name="lngFileLength">file length</param>

  /// <param name="strFileName">file name</param>

  /// <param name="strContentType">content type</param>

  public Attachment(byte[] bytAttachment, long lngFileLength, string strFileName, string strContentType)

  {

   _inBytes = true;

   _rawBytes = bytAttachment;

   _contentLength = lngFileLength;

   _contentFileName = strFileName;

   _contentType = strContentType;

  }

  /// <summary>

  /// New Attachment

  /// </summary>

  /// <param name="bytAttachment">attachment bytes content</param>

  /// <param name="strFileName">file name</param>

  /// <param name="strContentType">content type</param>

  public Attachment(byte[] bytAttachment, string strFileName, string strContentType)

  {

   _inBytes = true;

   _rawBytes = bytAttachment;

   _contentLength = bytAttachment.Length;

   _contentFileName = strFileName;

   _contentType = strContentType;

  }

  /// <summary>

  /// New Attachment

  /// </summary>

  /// <param name="strAttachment">attachment content</param>

  /// <param name="strContentType">content type</param>

  /// <param name="blnParseHeader">whether only parse the header or not</param>

  public Attachment(string strAttachment, string strContentType, bool blnParseHeader)

  {

   if (!blnParseHeader)

   {

    _contentFileName = _defaultMSTNEFFileName;

    _contentType = strContentType;

   }

   this.NewAttachment(strAttachment, blnParseHeader);

  }

  /// <summary>

  /// New Attachment

  /// </summary>

  /// <param name="strAttachment">attachment content</param>

  public Attachment(string strAttachment)

  {

   this.NewAttachment(strAttachment, true);

  }

  /// <summary>

  /// create attachment

  /// </summary>

  /// <param name="strAttachment">raw attachment text</param>

  /// <param name="blnParseHeader">parse header</param>

  private void NewAttachment(string strAttachment, bool blnParseHeader)

  {

   _inBytes = false;

   if (strAttachment == null)

    throw new ArgumentNullException("strAttachment");

   StringReader srReader = new StringReader(strAttachment);

   if (blnParseHeader)

   {

    string strLine = srReader.ReadLine();

    while (Utility.IsNotNullTextEx(strLine))

    {

     ParseHeader(srReader, ref strLine);

     if (Utility.IsOrNullTextEx(strLine))

      break;

     else

      strLine = srReader.ReadLine();

    }

   }

   this._rawAttachment = srReader.ReadToEnd();

   _contentLength = this._rawAttachment.Length;

  }

  /// <summary>

  /// Parse header fields and set member variables

  /// </summary>

  /// <param name="srReader">string reader</param>

  /// <param name="strLine">header line</param>

  private void ParseHeader(StringReader srReader, ref string strLine)

  {

   string[] array = Utility.GetHeadersValue(strLine); //Regex.Split(strLine,":");

   string[] values = Regex.Split(array[1], ";"); //array[1].Split(';');

   string strRet = null;

   switch (array[0].ToUpper())

   {

    case "CONTENT-TYPE":

     if (values.Length > 0)

      _contentType = values[0].Trim();

     if (values.Length > 1)

     {

      _contentCharset = Utility.GetQuotedValue(values[1], "=", "charset");

     }

     if (values.Length > 2)

     {

      _contentFormat = Utility.GetQuotedValue(values[2], "=", "format");

     }

     _contentFileName = Utility.ParseFileName(strLine);

     if (_contentFileName == "")

     {

      strRet = srReader.ReadLine();

      if (strRet == "")

      {

       strLine = "";

       break;

      }

      _contentFileName = Utility.ParseFileName(strLine);

      if (_contentFileName == "")

       ParseHeader(srReader, ref strRet);

     }

     break;

    case "CONTENT-TRANSFER-ENCODING":

     _contentTransferEncoding = Utility.SplitOnSemiColon(array[1])[0].Trim();

     break;

    case "CONTENT-DESCRIPTION":

     _contentDescription = Utility.DecodeText(Utility.SplitOnSemiColon(array[1])[0].Trim());

     break;

    case "CONTENT-DISPOSITION":

     if (values.Length > 0)

      _contentDisposition = values[0].Trim();

     ///<bug>reported by grandepuffo @ https://sourceforge.net/forum/message.php?msg_id=2589759

     //_contentFileName=values[1];

     if (values.Length > 1)

     {

      _contentFileName = values[1];

     }

     else

     {

      _contentFileName = "";

     }

     if (_contentFileName == "")

      _contentFileName = srReader.ReadLine();

     _contentFileName = _contentFileName.Replace("\t", "");

     _contentFileName = Utility.GetQuotedValue(_contentFileName, "=", "filename");

     _contentFileName = Utility.DecodeText(_contentFileName);

     break;

    case "CONTENT-ID":

     _contentID = Utility.SplitOnSemiColon(array[1])[0].Trim('<').Trim('>');

     break;

   }

  }

  /// <summary>

  /// verify the encoding

  /// </summary>

  /// <param name="encoding">encoding to verify</param>

  /// <returns>true if encoding</returns>

  private bool IsEncoding(string encoding)

  {

   return _contentTransferEncoding.ToLower().IndexOf(encoding.ToLower()) != -1;

  }

  /// <summary>

  /// Decode the attachment to text

  /// </summary>

  /// <returns>Decoded attachment text</returns>

  public string DecodeAsText()

  {

   string decodedAttachment = null;

   try

   {

    if (_contentType.ToLower() == "message/rfc822".ToLower())

     decodedAttachment = Utility.DecodeText(_rawAttachment);

    else if (_contentTransferEncoding != null)

    {

     decodedAttachment = _rawAttachment;

     if (!IsEncoding("7bit"))

     {

      if (IsEncoding("8bit") && _contentCharset != null & _contentCharset != "")

       decodedAttachment = Utility.Change(decodedAttachment, _contentCharset);

      if (Utility.IsQuotedPrintable(_contentTransferEncoding))

       decodedAttachment = DecodeQP.ConvertHexContent(decodedAttachment);

      else if (IsEncoding("8bit"))

       decodedAttachment = decodedAttachment;

      else

       decodedAttachment = Utility.deCodeB64s(Utility.RemoveNonB64(decodedAttachment));

     }

    }

    else if (_contentCharset != null)

     decodedAttachment = Utility.Change(_rawAttachment, _contentCharset); //Encoding.Default.GetString(Encoding.GetEncoding(_contentCharset).GetBytes(_rawAttachment));

    else

     decodedAttachment = _rawAttachment;

   }

   catch

   {

    decodedAttachment = _rawAttachment;

   }

   return decodedAttachment;

  }

  /// <summary>

  /// decode attachment to be a message object

  /// </summary>

  /// <returns>message</returns>

  public Message DecodeAsMessage()

  {

   bool blnRet = false;

   return new Message(ref blnRet, "", false, _rawAttachment, false);

  }

  /// <summary>

  /// Decode the attachment to bytes

  /// </summary>

  /// <returns>Decoded attachment bytes</returns>

  public byte[] DecodedAsBytes()

  {

   if (_rawAttachment == null)

    return null;

   if (_contentFileName != "")

   {

    byte[] decodedBytes = null;

    if (_contentType != null && _contentType.ToLower() == "message/rfc822".ToLower())

     decodedBytes = Encoding.Default.GetBytes(Utility.DecodeText(_rawAttachment));

    else if (_contentTransferEncoding != null)

    {

     string bytContent = _rawAttachment;

     if (!IsEncoding("7bit"))

     {

      if (IsEncoding("8bit") && _contentCharset != null & _contentCharset != "")

       bytContent = Utility.Change(bytContent, _contentCharset);

      if (Utility.IsQuotedPrintable(_contentTransferEncoding))

       decodedBytes = Encoding.Default.GetBytes(DecodeQP.ConvertHexContent(bytContent));

      else if (IsEncoding("8bit"))

       decodedBytes = Encoding.Default.GetBytes(bytContent);

      else

       decodedBytes = Convert.FromBase64String(Utility.RemoveNonB64(bytContent));

     }

     else

      decodedBytes = Encoding.Default.GetBytes(bytContent);

    }

    else if (_contentCharset != null)

     decodedBytes = Encoding.Default.GetBytes(Utility.Change(_rawAttachment, _contentCharset)); //Encoding.Default.GetString(Encoding.GetEncoding(_contentCharset).GetBytes(_rawAttachment));

    else

     decodedBytes = Encoding.Default.GetBytes(_rawAttachment);

    return decodedBytes;

   }

   else

   {

    return null;

   }

  }

  public int CompareTo(object attachment)

  {

   return (this.RawAttachment.CompareTo(((Attachment) (attachment)).RawAttachment));

  }

 }

 public enum MessageImportanceType

 {

  HIGH = 5,

  NORMAL = 3,

  LOW = 1

 }

 /// <summary>

 /// Decoding Quoted-Printable text

 ///

 /// </summary>

 public class DecodeQP

 {

  public DecodeQP()

  {

  }

  /// <summary>

  /// Decoding Quoted-Printable string

  /// </summary>

  /// <param name="Hexstring">Quoted-Printable encoded string</param>

  /// <param name="encode">encoding method</param>

  /// <returns>decoded string</returns>

  public static string ConvertHexToString(string Hexstring, string Encoding)

  {

   try

   {

    return ConvertHexToString(Hexstring, System.Text.Encoding.GetEncoding(Encoding));

   }

   catch

   {

    return ConvertHexContent(Hexstring);

   }

  }

  /// <summary>

  /// Decoding Quoted-Printable string

  /// </summary>

  /// <param name="Hexstring">Quoted-Printable encoded string</param>

  /// <param name="encode">encoding method</param>

  /// <returns>decoded string</returns>

  public static string ConvertHexToString(string Hexstring, Encoding encode)

  {

   try

   {

    if (Hexstring == null || Hexstring.Equals("")) return "";

    if (Hexstring.StartsWith("=")) Hexstring = Hexstring.Substring(1);

    string[] aHex = Hexstring.Split(new char[1] {'='});

    byte[] abyte = new Byte[aHex.Length];

    for (int i = 0; i < abyte.Length; i++)

    {

     // Console.WriteLine(aHex[i]);

     abyte[i] = (byte) int.Parse(aHex[i], NumberStyles.HexNumber);

    }

    return encode.GetString(abyte);

   }

   catch

   {

    return Hexstring;

   }

  }

  /// <summary>

  /// Decoding Quoted-Printable string at a position

  /// </summary>

  /// <param name="Hexstring">Quoted-Printable encoded string</param>

  /// <param name="encode">encoding method, "Default" is suggested</param>

  /// <param name="nStart">position to start, normally 0</param>

  /// <returns>decoded string</returns>

  public static string ConvertHexContent(string Hexstring, Encoding encode, long nStart)

  {

   if (nStart >= Hexstring.Length) return Hexstring;

   //to hold string to be decoded

   StringBuilder sbHex = new StringBuilder();

   sbHex.Append("");

   //to hold decoded string

   StringBuilder sbEncoded = new StringBuilder();

   sbEncoded.Append("");

   //wether we reach Quoted-Printable string

   bool isBegin = false;

   string temp;

   int i = (int) nStart;

   while (i < Hexstring.Length)

   {

    //init next loop

    sbHex.Remove(0, sbHex.Length);

    isBegin = false;

    int count = 0;

    while (i < Hexstring.Length)

    {

     temp = Hexstring.Substring(i, 1); //before reaching Quoted-Printable string, one char at a time

     if (temp.StartsWith("="))

     {

      temp = Hexstring.Substring(i, 3); //get 3 chars

      if (temp.EndsWith("\r\n")) //return char

      {

       if (isBegin && (count%2 == 0))

        break;

       // sbEncoded.Append("");

       i = i + 3;

      }

      else if (!temp.EndsWith("3D"))

      {

       sbHex.Append(temp);

       isBegin = true; //we reach Quoted-Printable string, put it into buffer

       i = i + 3;

       count++;

      }

      else //if it ends with 3D, it is "="

      {

       if (isBegin && (count%2 == 0)) //wait until even items to handle all character sets

        break;

       sbEncoded.Append("=");

       i = i + 3;

      }

     }

     else

     {

      if (isBegin) //we have got the how Quoted-Printable string, break it

       break;

      sbEncoded.Append(temp); //not Quoted-Printable string, put it into buffer

      i++;

     }

    }

    //decode Quoted-Printable string

    sbEncoded.Append(ConvertHexToString(sbHex.ToString(), encode));

   }

   return sbEncoded.ToString();

  }


  /// <summary>

  /// Decoding Quoted-Printable string using default encoding and begin at 0

  /// </summary>

  /// <param name="Hexstring">Quoted-Printable encoded string</param>

  /// <returns>decoded string</returns>

  public static string ConvertHexContent(string Hexstring)

  {

   if (Hexstring == null || Hexstring.Equals("")) return Hexstring;

   return ConvertHexContent(Hexstring, Encoding.Default, 0);

  }

 }

 /// <summary>

 /// Message Parser.

 /// </summary>

 public class Message

 {

  #region Member Variables

  private ArrayList _attachments = new ArrayList();

  private string _rawHeader = null;

  private string _rawMessage = null;

  private string _rawMessageBody = null;

  private int _attachmentCount = 0;

  private string _replyTo = null;

  private string _replyToEmail = null;

  private string _from = null;

  private string _fromEmail = null;

  private string _date = null;

  private string _dateTimeInfo = null;

  private string _subject = null;

  private string[] _to = new string[0];

  private string[] _cc = new string[0];

  private string[] _bcc = new string[0];

  private ArrayList _keywords = new ArrayList();

  private string _contentType = null;

  private string _contentCharset = null;

  private string _reportType = null;

  private string _contentTransferEncoding = null;

  private bool _html = false;

  private long _contentLength = 0;

  private string _contentEncoding = null;

  private string _returnPath = null;

  private string _mimeVersion = null;

  private string _received = null;

  private string _importance = null;

  private string _messageID = null;

  private string _attachmentboundry = null;

  private string _attachmentboundry2 = null;

  private bool _hasAttachment = false;

  private string _dispositionNotificationTo = null;

  private ArrayList _messageBody = new ArrayList();

  private string _basePath = null;

  private bool _autoDecodeMSTNEF = false;

  private Hashtable _customHeaders = new Hashtable();

  #endregion

  #region Properties

  /// <summary>

  /// custom headers

  /// </summary>

  public Hashtable CustomHeaders

  {

   get

   {

    return _customHeaders;

   }

   set

   {

    _customHeaders = value;

   }

  }

  /// <summary>

  /// whether auto decoding MS-TNEF attachment files

  /// </summary>

  public bool AutoDecodeMSTNEF

  {

   get

   {

    return _autoDecodeMSTNEF;

   }

   set

   {

    _autoDecodeMSTNEF = value;

   }

  }

  /// <summary>

  /// path to extract MS-TNEF attachment files

  /// </summary>

  public string BasePath

  {

   get

   {

    return _basePath;

   }

   set

   {

    try

    {

     if (value.EndsWith("\\"))

      _basePath = value;

     else

      _basePath = value + "\\";

    }

    catch

    {

    }

   }

  }

  /// <summary>

  /// message keywords

  /// </summary>

  public ArrayList Keywords

  {

   get

   {

    return _keywords;

   }

  }

  /// <summary>

  /// disposition notification

  /// </summary>

  public string DispositionNotificationTo

  {

   get

   {

    return _dispositionNotificationTo;

   }

  }

  /// <summary>

  /// received server

  /// </summary>

  public string Received

  {

   get

   {

    return _received;

   }

  }

  /// <summary>

  /// importance level

  /// </summary>

  public string Importance

  {

   get

   {

    return _importance;

   }

  }

  /// <summary>

  /// importance level type

  /// </summary>

  public MessageImportanceType ImportanceType

  {

   get

   {

    switch (_importance.ToUpper())

    {

     case "5":

     case "HIGH":

      return MessageImportanceType.HIGH;

     case "3":

     case "NORMAL":

      return MessageImportanceType.NORMAL;

     case "1":

     case "LOW":

      return MessageImportanceType.LOW;

     default:

      return MessageImportanceType.NORMAL;

    }

   }

  }

  /// <summary>

  /// Content Charset

  /// </summary>

  public string ContentCharset

  {

   get

   {

    return _contentCharset;

   }

  }

  /// <summary>

  /// Content Transfer Encoding

  /// </summary>

  public string ContentTransferEncoding

  {

   get

   {

    return _contentTransferEncoding;

   }

  }

  /// <summary>

  /// Message Bodies

  /// </summary>

  public ArrayList MessageBody

  {

   get

   {

    return _messageBody;

   }

  }

  /// <summary>

  /// Attachment Boundry

  /// </summary>

  public string AttachmentBoundry

  {

   get

   {

    return _attachmentboundry;

   }

  }

  /// <summary>

  /// Alternate Attachment Boundry

  /// </summary>

  public string AttachmentBoundry2

  {

   get

   {

    return _attachmentboundry2;

   }

  }

  /// <summary>

  /// Attachment Count

  /// </summary>

  public int AttachmentCount

  {

   get

   {

    return _attachmentCount;

   }

  }

  /// <summary>

  /// Attachments

  /// </summary>

  public ArrayList Attachments

  {

   get

   {

    return _attachments;

   }

  }

  /// <summary>

  /// CC

  /// </summary>

  public string[] CC

  {

   get

   {

    return _cc;

   }

  }

  /// <summary>

  /// BCC

  /// </summary>

  public string[] BCC

  {

   get

   {

    return _bcc;

   }

  }

  /// <summary>

  /// TO

  /// </summary>

  public string[] TO

  {

   get

   {

    return _to;

   }

  }

  /// <summary>

  /// Content Encoding

  /// </summary>

  public string ContentEncoding

  {

   get

   {

    return _contentEncoding;

   }

  }

  /// <summary>

  /// Content Length

  /// </summary>

  public long ContentLength

  {

   get

   {

    return _contentLength;

   }

  }

  /// <summary>

  /// Content Type

  /// </summary>

  public string ContentType

  {

   get

   {

    return _contentType;

   }

  }

  /// <summary>

  /// Report Type

  /// </summary>

  public string ReportType

  {

   get

   {

    return _reportType;

   }

  }

  /// <summary>

  /// HTML

  /// </summary>

  public bool HTML

  {

   get

   {

    return _html;

   }

  }

  /// <summary>

  /// Date

  /// </summary>

  public string Date

  {

   get

   {

    return _date;

   }

  }

  /// <summary>

  /// DateTime Info

  /// </summary>

  public string DateTimeInfo

  {

   get

   {

    return _dateTimeInfo;

   }

  }

  /// <summary>

  /// From name

  /// </summary>

  public string From

  {

   get

   {

    return _from;

   }

  }

  /// <summary>

  /// From Email

  /// </summary>

  public string FromEmail

  {

   get

   {

    return _fromEmail;

   }

  }

  /// <summary>

  /// Reply to name

  /// </summary>

  public string ReplyTo

  {

   get

   {

    return _replyTo;

   }

  }

  /// <summary>

  /// Reply to email

  /// </summary>

  public string ReplyToEmail

  {

   get

   {

    return _replyToEmail;

   }

  }

  /// <summary>

  /// whether has attachment

  /// </summary>

  public bool HasAttachment

  {

   get

   {

    return _hasAttachment;

   }

  }

  /// <summary>

  /// raw message body

  /// </summary>

  public string RawMessageBody

  {

   get

   {

    return _rawMessageBody;

   }

  }

  /// <summary>

  /// Message ID

  /// </summary>

  public string MessageID

  {

   get

   {

    return _messageID;

   }

  }

  /// <summary>

  /// MIME version

  /// </summary>

  public string MimeVersion

  {

   get

   {

    return _mimeVersion;

   }

  }

  /// <summary>

  /// raw header

  /// </summary>

  public string RawHeader

  {

   get

   {

    return _rawHeader;

   }

  }

  /// <summary>

  /// raw message

  /// </summary>

  public string RawMessage

  {

   get

   {

    return _rawMessage;

   }

  }

  /// <summary>

  /// return path

  /// </summary>

  public string ReturnPath

  {

   get

   {

    return _returnPath;

   }

  }

  /// <summary>

  /// subject

  /// </summary>

  public string Subject

  {

   get

   {

    return _subject;

   }

  }

  #endregion

  /// <summary>

  /// release all objects

  /// </summary>

  ~Message()

  {

   _attachments.Clear();

   _attachments = null;

   _keywords.Clear();

   _keywords = null;

   _messageBody.Clear();

   _messageBody = null;

   _customHeaders.Clear();

   _customHeaders = null;

  }

  /// <summary>

  /// New Message

  /// </summary>

  /// <param name="blnFinish">reference for the finishing state</param>

  /// <param name="strBasePath">path to extract MS-TNEF attachment files</param>

  /// <param name="blnAutoDecodeMSTNEF">whether auto decoding MS-TNEF attachments</param>

  /// <param name="blnOnlyHeader">whether only decode the header without body</param>

  /// <param name="strEMLFile">file of email content to load from</param>

  public Message(ref bool blnFinish, string strBasePath, bool blnAutoDecodeMSTNEF, bool blnOnlyHeader, string strEMLFile)

  {

   string strMessage = null;

   if (Utility.ReadPlainTextFromFile(strEMLFile, ref strMessage))

   {

    NewMessage(ref blnFinish, strBasePath, blnAutoDecodeMSTNEF, strMessage, blnOnlyHeader);

   }

   else

    blnFinish = true;

  }

  /// <summary>

  /// New Message

  /// </summary>

  /// <param name="blnFinish">reference for the finishing state</param>

  /// <param name="strBasePath">path to extract MS-TNEF attachment files</param>

  /// <param name="blnAutoDecodeMSTNEF">whether auto decoding MS-TNEF attachments</param>

  /// <param name="strMessage">raw message content</param>

  /// <param name="blnOnlyHeader">whether only decode the header without body</param>

  public Message(ref bool blnFinish, string strBasePath, bool blnAutoDecodeMSTNEF, string strMessage, bool blnOnlyHeader)

  {

   NewMessage(ref blnFinish, strBasePath, blnAutoDecodeMSTNEF, strMessage, blnOnlyHeader);

  }

  /// <summary>

  /// New Message

  /// </summary>

  /// <param name="blnFinish">reference for the finishing state</param>

  /// <param name="strMessage">raw message content</param>

  /// <param name="blnOnlyHeader">whether only decode the header without body</param>

  public Message(ref bool blnFinish, string strMessage, bool blnOnlyHeader)

  {

   NewMessage(ref blnFinish, "", false, strMessage, blnOnlyHeader);

  }

  /// <summary>

  /// New Message

  /// </summary>

  /// <param name="blnFinish">reference for the finishing state</param>

  /// <param name="strMessage">raw message content</param>

  public Message(ref bool blnFinish, string strMessage)

  {

   NewMessage(ref blnFinish, "", false, strMessage, false);

  }

  /// <summary>

  /// get valid attachment

  /// </summary>

  /// <param name="intAttachmentNumber">attachment index in the attachments collection</param>

  /// <returns>attachment</returns>

  public Attachment GetAttachment(int intAttachmentNumber)

  {

   if (intAttachmentNumber < 0 || intAttachmentNumber > _attachmentCount || intAttachmentNumber > _attachments.Count)

   {

    Utility.LogError("GetAttachment():attachment not exist");

    throw new ArgumentOutOfRangeException("intAttachmentNumber");

   }

   return (Attachment) _attachments[intAttachmentNumber];

  }

  /// <summary>

  /// New Message

  /// </summary>

  /// <param name="blnFinish">reference for the finishing state</param>

  /// <param name="strBasePath">path to extract MS-TNEF attachment files</param>

  /// <param name="blnAutoDecodeMSTNEF">whether auto decoding MS-TNEF attachments</param>

  /// <param name="strMessage">raw message content</param>

  /// <param name="blnOnlyHeader">whether only decode the header without body</param>

  /// <returns>construction result whether successfully new a message</returns>

  private bool NewMessage(ref bool blnFinish, string strBasePath, bool blnAutoDecodeMSTNEF, string strMessage, bool blnOnlyHeader)

  {

   StringReader srdReader = new StringReader(strMessage);

   StringBuilder sbdBuilder = new StringBuilder();

   _basePath = strBasePath;

   _autoDecodeMSTNEF = blnAutoDecodeMSTNEF;

   _rawMessage = strMessage;

   string strLine = srdReader.ReadLine();

   while (Utility.IsNotNullTextEx(strLine))

   {

    sbdBuilder.Append(strLine + "\r\n");

    ParseHeader(sbdBuilder, srdReader, ref strLine);

    if (Utility.IsOrNullTextEx(strLine))

     break;

    else

     strLine = srdReader.ReadLine();

   }

   _rawHeader = sbdBuilder.ToString();

   SetAttachmentBoundry2(_rawHeader);

   if (_contentLength == 0)

    _contentLength = strMessage.Length; //_rawMessageBody.Length;

   if (blnOnlyHeader == false)

   {

    _rawMessageBody = srdReader.ReadToEnd().Trim();

    //the auto reply mail by outlook uses ms-tnef format

    if ((_hasAttachment == true && _attachmentboundry != null) || MIMETypes.IsMSTNEF(_contentType))

    {

     set_attachments();

     if (this.Attachments.Count > 0)

     {

      Attachment at = this.GetAttachment(0);

      if (at != null && at.NotAttachment)

       this.GetMessageBody(at.DecodeAsText());

      else

      {

      }

      //in case body parts as text[0] html[1]

      if (this.Attachments.Count > 1 && !this.IsReport())

      {

       at = this.GetAttachment(1);

       if (at != null && at.NotAttachment)

        this.GetMessageBody(at.DecodeAsText());

       else

       {

       }

      }

     }

     else

     {

     }

    }

    else

    {

     GetMessageBody(_rawMessageBody);

    }

   }

   blnFinish = true;

   return true;

  }

  /// <summary>

  /// parse message body

  /// </summary>

  /// <param name="strBuffer">raw message body</param>

  /// <returns>message body</returns>

  public string GetTextBody(string strBuffer)

  {

   if (strBuffer.EndsWith("\r\n."))

    return strBuffer.Substring(0, strBuffer.Length - "\r\n.".Length);

   else

    return strBuffer;

  }

  /// <summary>

  /// parse message body

  /// </summary>

  /// <param name="strBuffer">raw message body</param>

  public void GetMessageBody(string strBuffer)

  {

   int end, begin;

   string body;

   string encoding = "";

   begin = end = 0;

   _messageBody.Clear();

   try

   {

    if (Utility.IsOrNullTextEx(strBuffer))

     return;

    else if (Utility.IsOrNullTextEx(_contentType) && _contentTransferEncoding == null)

    {

     _messageBody.Add(GetTextBody(strBuffer));

    }

    else if (_contentType != null && _contentType.IndexOf("digest") >= 0)

    {

     // this is a digest method

     //ParseDigestMessage(strBuffer);

     _messageBody.Add(GetTextBody(strBuffer));

    }

    else if (_attachmentboundry2 == null)

    {

     body = GetTextBody(strBuffer);

     if (Utility.IsQuotedPrintable(_contentTransferEncoding))

     {

      body = DecodeQP.ConvertHexContent(body);

     }

     else if (Utility.IsBase64(_contentTransferEncoding))

     {

      body = Utility.deCodeB64s(Utility.RemoveNonB64(body));

     }

     else if (Utility.IsNotNullText(_contentCharset))

     {

      body = Encoding.GetEncoding(_contentCharset).GetString(Encoding.Default.GetBytes(body));

     }

     _messageBody.Add(Utility.RemoveNonB64(body));

    }

    else

    {

     begin = 0;

     while (begin != -1)

     {

      // find "\r\n\r\n" denoting end of header

      begin = strBuffer.IndexOf("--" + _attachmentboundry2, begin);

      if (begin != -1)

      {

       encoding = MIMETypes.GetContentTransferEncoding(strBuffer, begin);

       begin = strBuffer.IndexOf("\r\n\r\n", begin + 1); //strBuffer.LastIndexOfAny(ALPHABET.ToCharArray());

       // find end of text

       end = strBuffer.IndexOf("--" + _attachmentboundry2, begin + 1);

       if (begin != -1)

       {

        if (end != -1)

        {

         begin += 4;

         if (begin >= end)

          continue;

         else if (this._contentEncoding != null && this._contentEncoding.IndexOf("8bit") != -1)

          body = Utility.Change(strBuffer.Substring(begin, end - begin - 2), _contentCharset);

         else

          body = strBuffer.Substring(begin, end - begin - 2);

        }

        else

        {

         body = strBuffer.Substring(begin);

        }

        if (Utility.IsQuotedPrintable(encoding))

        {

         string ret = body;

         ret = DecodeQP.ConvertHexContent(ret);

         _messageBody.Add(ret);

        }

        else if (Utility.IsBase64(encoding))

        {

         string ret = Utility.RemoveNonB64(body);

         ret = Utility.deCodeB64s(ret);

         if (ret != "\0")

          _messageBody.Add(ret);

         else

          _messageBody.Add(body);

        }

        else

         _messageBody.Add(body);

        if (end == -1) break;

       }

       else

       {

        break;

       }

      }

      else

      {

       if (_messageBody.Count == 0)

       {

        _messageBody.Add(strBuffer);

       }

       break;

      }

     }

    }

   }

   catch (Exception e)

   {

    Utility.LogError("GetMessageBody():" + e.Message);

    _messageBody.Add(Utility.deCodeB64s(strBuffer));

   }

   if (_messageBody.Count > 1)

    _html = true;

  }

  /// <summary>

  /// verify if the message is a report

  /// </summary>

  /// <returns>if it is a report message, return true, else, false</returns>

  public bool IsReport()

  {

   if (Utility.IsNotNullText(_contentType))

    return (_contentType.ToLower().IndexOf("report".ToLower()) != -1);

   else

    return false;

  }

  /// <summary>

  /// verify if the attachment is MIME Email file

  /// </summary>

  /// <param name="attItem">attachment</param>

  /// <returns>if MIME Email file, return true, else, false</returns>

  public bool IsMIMEMailFile(Attachment attItem)

  {

   try

   {

    return (attItem.ContentFileName.ToLower().EndsWith(".eml".ToLower()) || attItem.ContentType.ToLower() == "message/rfc822".ToLower());

   }

   catch (Exception e)

   {

    Utility.LogError("IsMIMEMailFile():" + e.Message);

    return false;

   }

  }

  /// <summary>

  /// translate pictures url within the body

  /// </summary>

  /// <param name="strBody">message body</param>

  /// <param name="hsbFiles">pictures collection</param>

  /// <returns>translated message body</returns>

  public string TranslateHTMLPictureFiles(string strBody, Hashtable hsbFiles)

  {

   try

   {

    for (int i = 0; i < this.AttachmentCount; i++)

    {

     Attachment att = this.GetAttachment(i);

     if (Utility.IsPictureFile(att.ContentFileName) == true)

     {

      if (Utility.IsNotNullText(att.ContentID))

       //support for embedded pictures

       strBody = strBody.Replace("cid:" + att.ContentID, hsbFiles[att.ContentFileName].ToString());

      strBody = strBody.Replace(att.ContentFileName, hsbFiles[att.ContentFileName].ToString());

     }

    }

   }

   catch (Exception e)

   {

    Utility.LogError("TranslateHTMLPictureFiles():" + e.Message);

   }

   return strBody;

  }

  /// <summary>

  /// translate pictures url within the body

  /// </summary>

  /// <param name="strBody">message body</param>

  /// <param name="strPath">path of the pictures</param>

  /// <returns>translated message body</returns>

  public string TranslateHTMLPictureFiles(string strBody, string strPath)

  {

   try

   {

    if (!strPath.EndsWith("\\"))

    {

     strPath += "\\";

    }

    for (int i = 0; i < this.AttachmentCount; i++)

    {

     Attachment att = this.GetAttachment(i);

     if (Utility.IsPictureFile(att.ContentFileName) == true)

     {

      if (Utility.IsNotNullText(att.ContentID))

       //support for embedded pictures

       strBody = strBody.Replace("cid:" + att.ContentID, strPath + att.ContentFileName);

      strBody = strBody.Replace(att.ContentFileName, strPath + att.ContentFileName);

     }

    }

   }

   catch (Exception e)

   {

    Utility.LogError("TranslateHTMLPictureFiles():" + e.Message);

   }

   return strBody;

  }

  /// <summary>

  /// Get the proper attachment file name

  /// </summary>

  /// <param name="attItem">attachment</param>

  /// <returns>propery attachment file name</returns>

  public string GetAttachmentFileName(Attachment attItem)

  {

   int items = 0;

   //return unique body file names

   for (int i = 0; i < _attachments.Count; i++)

   {

    if (attItem.ContentFileName == attItem.DefaultFileName)

    {

     items++;

     attItem.ContentFileName = attItem.DefaultFileName2.Replace("*", items.ToString());

    }

   }

   string name = attItem.ContentFileName;

   return (name == null || name == "" ? (IsReport() == true ? (this.IsMIMEMailFile(attItem) == true ? attItem.DefaultMIMEFileName : attItem.DefaultReportFileName) : (attItem.ContentID != null ? attItem.ContentID : attItem.DefaultFileName)) : name);

  }

  /// <summary>

  /// save attachments to a defined path

  /// </summary>

  /// <param name="strPath">path to have attachments to be saved to</param>

  /// <returns>true if save successfully, false if failed</returns>

  public bool SaveAttachments(string strPath)

  {

   if (Utility.IsNotNullText(strPath))

   {

    try

    {

     bool blnRet = true;

     if (!strPath.EndsWith("\\"))

     {

      strPath += "\\";

     }

     for (int i = 0; i < this.Attachments.Count; i++)

     {

      Attachment att = GetAttachment(i);

      blnRet = SaveAttachment(att, strPath + GetAttachmentFileName(att));

      if (!blnRet)

       break;

     }

     return blnRet;

    }

    catch (Exception e)

    {

     Utility.LogError(e.Message);

     return false;

    }

   }

   else

    return false;

  }

  /// <summary>

  /// save attachment to file

  /// </summary>

  /// <param name="attItem">Attachment</param>

  /// <param name="strFileName">File to be saved to</param>

  /// <returns>true if save successfully, false if failed</returns>

  public bool SaveAttachment(Attachment attItem, string strFileName)

  {

   byte[] da;

   try

   {

    //    FileStream fs=File.Create(strFileName);

    //    byte[] da;

    //    if(attItem.ContentFileName.Length>0)

    //    {

    //     da=attItem.DecodedAttachment;

    //    }

    //    else

    //    {

    //     this.GetMessageBody(attItem.DecodeAttachmentAsText());

    //     da=Encoding.Default.GetBytes((string)this.MessageBody[this.MessageBody.Count-1]);

    //    }

    //    fs.Write(da,0,da.Length);

    //    fs.Close();

    //    return true;

    if (attItem.InBytes)

    {

     da = attItem.RawBytes;

    }

    else if (attItem.ContentFileName.Length > 0)

    {

     da = attItem.DecodedAttachment;

    }

    else if (attItem.ContentType.ToLower() == "message/rfc822".ToLower())

    {

     da = Encoding.Default.GetBytes(attItem.RawAttachment);

    }

    else

    {

     this.GetMessageBody(attItem.DecodeAsText());

     da = Encoding.Default.GetBytes((string) this.MessageBody[this.MessageBody.Count - 1]);

    }

    return Utility.SaveByteContentToFile(strFileName, da);

   }

   catch

   {

    /*Utility.LogError("SaveAttachment():"+e.Message);

    return false;*/

    da = Encoding.Default.GetBytes(attItem.RawAttachment);

    return Utility.SaveByteContentToFile(strFileName, da);

   }

  }

  /// <summary>

  /// set attachments

  /// </summary>

  private void set_attachments()

  {

   int indexOf_attachmentstart = 0;

   int indexOfAttachmentEnd = 0;

   bool processed = false;

   Attachment att = null;

   SetAttachmentBoundry2(_rawMessageBody);

   while (!processed)

   {

    if (Utility.IsNotNullText(_attachmentboundry))

    {

     indexOf_attachmentstart = _rawMessageBody.IndexOf(_attachmentboundry, indexOf_attachmentstart) + _attachmentboundry.Length;

     if (_rawMessageBody == "" || indexOf_attachmentstart < 0) return;

     indexOfAttachmentEnd = _rawMessageBody.IndexOf(_attachmentboundry, indexOf_attachmentstart + 1);

    }

    else

    {

     indexOfAttachmentEnd = -1;

    }

    //if(indexOfAttachmentEnd<0)return;

    if (indexOfAttachmentEnd != -1)

    {

    }

    else if (indexOfAttachmentEnd == -1 && !processed && _attachmentCount == 0)

    {

     processed = true;

     indexOfAttachmentEnd = _rawMessageBody.Length;

    }

    else

     return;

    if (indexOf_attachmentstart == indexOfAttachmentEnd - 9)

    {

     indexOf_attachmentstart = 0;

     processed = true;

    }

    string strLine = _rawMessageBody.Substring(indexOf_attachmentstart, (indexOfAttachmentEnd - indexOf_attachmentstart - 2));

    bool isMSTNEF;

    isMSTNEF = MIMETypes.IsMSTNEF(_contentType);

    att = new Attachment(strLine.Trim(), _contentType, !isMSTNEF);

    //ms-tnef format might contain multiple attachments

    if (MIMETypes.IsMSTNEF(att.ContentType) && AutoDecodeMSTNEF && !isMSTNEF)

    {

     Utility.LogError("set_attachments():found ms-tnef file");

     TNEFParser tnef = new TNEFParser();

     TNEFAttachment tatt = new TNEFAttachment();

     Attachment attNew = null;

     tnef.Verbose = false;

     tnef.BasePath = this.BasePath;

     //tnef.LogFilePath=this.BasePath + "OpenPOP.TNEF.log";

     if (tnef.OpenTNEFStream(att.DecodedAsBytes()))

     {

      if (tnef.Parse())

      {

       for (IDictionaryEnumerator i = tnef.Attachments().GetEnumerator(); i.MoveNext(); )

       {

        tatt = (TNEFAttachment) i.Value;

        attNew = new Attachment(tatt.FileContent, tatt.FileLength, tatt.FileName, MIMETypes.GetMimeType(tatt.FileName));

        _attachmentCount++;

        _attachments.Add(attNew);

       }

      }

      else

       Utility.LogError("set_attachments():ms-tnef file parse failed");

     }

     else

      Utility.LogError("set_attachments():ms-tnef file open failed");

    }

    else

    {

     _attachmentCount++;

     _attachments.Add(att);

    }

    indexOf_attachmentstart++;

   }

  }

  /// <summary>

  /// Set alternative attachment boundry

  /// </summary>

  /// <param name="strBuffer">raw message</param>

  private void SetAttachmentBoundry2(string strBuffer)

  {

   int indexOfAttachmentBoundry2Begin = 0;

   int indexOfAttachmentBoundry2End = 0;

   indexOfAttachmentBoundry2Begin = strBuffer.ToLower().IndexOf("Multipart/Alternative".ToLower());

   if (indexOfAttachmentBoundry2Begin != -1)

   {

    /*    indexOfAttachmentBoundry2Begin=strBuffer.IndexOf("boundary=\"");

        indexOfAttachmentBoundry2End=strBuffer.IndexOf("\"",indexOfAttachmentBoundry2Begin+10);

        if(indexOfAttachmentBoundry2Begin!=-1&&indexOfAttachmentBoundry2End!=-1)

         _attachmentboundry2=strBuffer.Substring(indexOfAttachmentBoundry2Begin+10,indexOfAttachmentBoundry2End-indexOfAttachmentBoundry2Begin-10).Trim();

    */

    indexOfAttachmentBoundry2Begin = strBuffer.IndexOf("boundary=");

    if (indexOfAttachmentBoundry2Begin != -1)

    {

     int p = strBuffer.IndexOf("\r\n", indexOfAttachmentBoundry2Begin);

     string s = strBuffer.Substring(indexOfAttachmentBoundry2Begin + 29, 4);

     indexOfAttachmentBoundry2End = strBuffer.IndexOf("\r\n", indexOfAttachmentBoundry2Begin + 9);

     if (indexOfAttachmentBoundry2End == -1)

      indexOfAttachmentBoundry2End = strBuffer.Length;

     _attachmentboundry2 = Utility.RemoveQuote(strBuffer.Substring(indexOfAttachmentBoundry2Begin + 9, indexOfAttachmentBoundry2End - indexOfAttachmentBoundry2Begin - 9));

    }

   }

   else

   {

    _attachmentboundry2 = _attachmentboundry;

   }

  }

  /// <summary>

  /// Save message content to eml file

  /// </summary>

  /// <param name="strFile"></param>

  /// <returns></returns>

  public bool SaveToMIMEEmailFile(string strFile, bool blnReplaceExists)

  {

   return Utility.SavePlainTextToFile(strFile, _rawMessage, blnReplaceExists);

  }

  /// <summary>

  /// parse multi-line header

  /// </summary>

  /// <param name="sbdBuilder">string builder to hold header content</param>

  /// <param name="srdReader">string reader to get each line of the header</param>

  /// <param name="strValue">first line content</param>

  /// <param name="strLine">reference header line</param>

  /// <param name="alCollection">collection to hold every content line</param>

  private void ParseStreamLines(StringBuilder sbdBuilder

                                , StringReader srdReader

                                , string strValue

                                , ref string strLine

                                , ArrayList alCollection)

  {

   string strFormmated;

   int intLines = 0;

   alCollection.Add(strValue);

   sbdBuilder.Append(strLine);

   strLine = srdReader.ReadLine();

   while (strLine.Trim() != "" && (strLine.StartsWith("\t") || strLine.StartsWith(" ")))

   {

    strFormmated = strLine.Substring(1);

    alCollection.Add(Utility.DecodeLine(strFormmated));

    sbdBuilder.Append(strLine);

    strLine = srdReader.ReadLine();

    intLines++;

   }

   if (strLine != "")

   {

    sbdBuilder.Append(strLine);

   }

   else if (intLines == 0)

   {

    strLine = srdReader.ReadLine();

    sbdBuilder.Append(strLine);

   }

   ParseHeader(sbdBuilder, srdReader, ref strLine);

  }

  /// <summary>

  /// parse multi-line header

  /// </summary>

  /// <param name="sbdBuilder">string builder to hold header content</param>

  /// <param name="srdReader">string reader to get each line of the header</param>

  /// <param name="strName">collection key</param>

  /// <param name="strValue">first line content</param>

  /// <param name="strLine">reference header line</param>

  /// <param name="hstCollection">collecti

抱歉!评论已关闭.