/// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="stream"></param>
 public MimeMessage(Stream stream)
 {
     MimeParser mp = new MimeParser(stream);
     Parse(ref mp, null);
     CreateDefaultHeaders();
     mp = null;
 }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="mp">MimeParser</param>
 /// <param name="parentMultipartBody">Multipart Body of parent messages</param>
 protected MimeMessage(ref MimeParser mp, MimeMultipartBody parentMultipartBody)
 {
     if (parentMultipartBody != null)
     {
         parentMultipartBody.Add(this);
     }
     Parse(ref mp, parentMultipartBody);
 }
        private void Parse(ref MimeParser mp, MimeMultipartBody parentMultipartBody)
        {
            try
            {
                string sLine = "";
                byte [] buffer = null;
                bool isEOC = false;
                bool readBinaryBody = false;

                while(sLine != null)
                {
                    //Check if the Binary encoding header is found
                    if (_headers["content-transfer-encoding"] != null &&
                        MimeBodyPart.GetMimeEncoding(_headers["content-transfer-encoding"].Value) == MimeBodyPart.MimeEncoding.Binary
                        && buffer == null)
                    {
                        readBinaryBody = true;
                    }
                    MimeParser.ChunkType chunkType = mp.ReadNextChunk(ref sLine, ref isEOC, ref readBinaryBody, ref buffer);

                    switch(chunkType)
                    {
                        case MimeParser.ChunkType.VersionHeader:
                        case MimeParser.ChunkType.Header:
                            MimeHeader mh = new MimeHeader(sLine);
                            InitializeMultipart(ref mp, mh);
                            _headers.Add(mh);
                            break;
                        case MimeParser.ChunkType.Body:
                            CreateBody(sLine, buffer);
                            break;
                        case MimeParser.ChunkType.StartBoundary:
                            if (_body == null)
                                CreateBody("", buffer);
                            MimeMessage firstMessage = new MimeMessage(ref mp, (MimeMultipartBody)_body);
                            break;
                        case MimeParser.ChunkType.Boundary:
                            MimeMessage nextMessage = new MimeMessage(ref mp, parentMultipartBody);
                            return;
                        case MimeParser.ChunkType.EndBoundary:
                            return;
                        case MimeParser.ChunkType.EOF:
                            break;
                        default:
                            break;
                    }
                }
            }
            catch(Exception err)
            {
                logger.Error(err);
                throw;
            }
        }
        private void InitializeMultipart(ref MimeParser mp, MimeHeader mh)
        {
            //Check Content-Type
            if (mh.Name.ToLower().CompareTo("content-type") == 0
                && mh.Value.StartsWith("multipart"))
            {
                _isMultiPart = true;
                mp.IsMultiPart = _isMultiPart;

                //Check boundary
                if (mh.Parameters["boundary"] != null)
                {
                    _boundary = mh.Parameters["boundary"].Value;
                    mp.Boundary = _boundary;
                }
            }
        }
        /// <summary>
        /// Parsing mime from stream
        /// </summary>
        /// <param name="mp"></param>
        /// <param name="isChildMime"></param>
        private void Parse(ref MimeParser mp, bool isChildMime)
        {
            try
            {
                string sLine = "";
                byte [] buffer = null;
                bool isEOC = false;
                bool readBinaryBody = false;

                //Read line by line
                //if line is null, end of file is detected.
                while(sLine != null)
                {
                    if (isChildMime && _headers["content-type"] != null && _headers["content-type"].Value != "multipart/related")
                    {
                        readBinaryBody = true;
                    }

                    //Read next chunk
                    //Usually the next line except for reading binary body.
                    //Reading binary body will read until the boundary is found
                    MimeParser.ChunkType chunkType = mp.ReadNextChunk(ref sLine, ref isEOC, ref readBinaryBody, ref buffer);

                    //perform task based on the chunk type
                    switch (chunkType)
                    {
                        case MimeParser.ChunkType.VersionHeader:
                        case MimeParser.ChunkType.Header:
                            MimeHeader mh = new MimeHeader(sLine);
                            InitializeMultipart(ref mp, mh);
                            _headers.Add(mh);
                            break;
                        case MimeParser.ChunkType.Body:
                            CreateBody(sLine, buffer);
                            //Check if the next line is the boundary of this child mime
                            if (isChildMime && !_isMultiPart)
                                return;
                            break;
                        case MimeParser.ChunkType.StartBoundary:
                        case MimeParser.ChunkType.Boundary:
                            Mime childMessage = new Mime(ref mp, true);
                            _mimes.Add(childMessage);
                            break;
                        case MimeParser.ChunkType.EndBoundary:
                            return;
                        case MimeParser.ChunkType.EOF:
                            break;
                        default:
                            break;
                    }
                }
            }
            catch(Exception err)
            {
                logger.Error(err);
                throw;
            }
        }
 /// <summary>
 /// Internal use to construct a child mime from mime parser
 /// </summary>
 /// <param name="mp"></param>
 /// <param name="isChildMime"></param>
 private Mime(ref MimeParser mp, bool isChildMime)
 {
     Parse(ref mp, isChildMime);
     //set filename
     if (_headers.Contains("Content-Disposition")
         && _headers["Content-Disposition"].Parameters.Contains("filename")
         && _fileName == null)
     {
         FileInfo fi = new FileInfo(_headers["Content-Disposition"].Parameters["filename"].Value);
         _fileName = fi.Name;
     }
 }
 /// <summary>
 /// Internal use to construct mime from mime parser
 /// </summary>
 /// <param name="mp">MimeParser</param>
 private Mime(MimeParser mp)
     : this(ref mp, false)
 {
     CreateDefaultHeaders();
     mp = null;
 }
 public void ParseNestedMultiPartMime()
 {
     var stream = TestDataHelper.Instance.GetTestStream("mimeNestedMultipart.txt");
     MimeParser mp = new MimeParser(stream);
     //Assuming Boundary is given.
     mp.IsMultiPart = true;
     mp.Boundary = "----_OAI_NextPart_2563710857820783";
     string sLine = "";
     bool isEOC = false;
     bool isEndOfChunk = true;
     int chunkCount = 0;
     while(sLine != null)
     {
         if (chunkCount == 5 && isEndOfChunk)
         {
             mp.Boundary = "----_OAI_NextPart_2563710857820783_FirstMessage";
         }
         else if (chunkCount == 18 && isEndOfChunk)
         {
             mp.Boundary = "----_OAI_NextPart_2563710857820783_SecondMessage";
         }
         MimeParser.ChunkType chunkType = mp.ReadNextChunk(ref sLine, ref isEOC);
         if (sLine != null)
         {
             if (isEndOfChunk)
             {
                 chunkCount++;
     //						System.Diagnostics.Trace.WriteLine("Chunk no:" + chunkCount.ToString() + ".  Chunk type is " + chunkType.ToString() + ".  The chunk string is");
             }
     //					System.Diagnostics.Trace.WriteLine(sLine);
         }
         isEndOfChunk = isEOC;
     }
     AssertionHelper.IsTrue("There are 30 chunks",chunkCount == 30);
 }