/// <summary>
        /// Add alternate views and attachments to the existing message object.
        /// Each component is separated boundary text defined in the contentType.Boundary variable.
        /// Each component within a boundary has its own headers defining the payload.
        /// Media types text/plain and text/html go into AlternateView objects.
        /// All other media types will be treated as attachments.
        /// </summary>
        /// <param name="message"></param>
        /// <param name="reader"></param>
        /// <param name="contentType"></param>
        private static void LoadBodyMultipart(ReceivedMessage message, TextReader reader, ContentType contentType)
        {
            /* http://www.w3.org/Protocols/rfc1341/7_2_Multipart.html */
            //each component of the multipart message will be separated by a boundary.
            //each section of text within a boundary should have headers to describe it or in the absence of headers
            //assumed to be ASCII text/plain.
            //a valid message component is preceded and followed by a the boundary text
            //which is two hyphens followed by the value Boundary property of the main ContentType object.

            //UNDONE: Unsupported for now: In the case of multipart/related, the attachments should be done as LinkedResources of the text/html AlternativeView.
            //This is a nice to have but not critical. Last time I checked, Gmail didn't even support these kinds
            //of internal references, either.

            /*******************************************************************************************
             * the text following the message headers and preceding the first boundary is to be ignored.
             * any text at after the final boundary is also to be ignored.
             * /*******************************************************************************************/

            foreach (var part in LoadMultipart(reader, contentType))
            {
                if (part is AlternateView)
                {
                    message.AlternateViews.Add(part as AlternateView);
                }
                else if (part is Attachment)
                {
                    message.Attachments.Add(part as Attachment);
                }
            }
            //scroll past epilogue
            string buff;

            while (null != (buff = reader.ReadLine()) && (LineType.EOF != GetLineType(buff, contentType)))
            {
                ;
            }
        }
        /// <summary>
        /// Parse a TextReader. The calling code is responsible for closing the reader and the stream.
        /// </summary>
        /// <param name="reader"></param>
        /// <returns>Returns a ReceivedMessage object loaded from the TextReader. Return null if the TextReader is null.</returns>
        public ReceivedMessage Parse( TextReader reader )
        {
            if( reader == null )
                return null;

            ReceivedMessage message = new ReceivedMessage();
            if( !LoadHeaders( reader, message.ReceivedHeaders, message.RawReceivedHeaders ) )
                throw new InvalidDataException( "MIME Stream must contain headers." );

            LoadMailAddresses( message );
            Debug.WriteLine( message.ReceivedHeaders["subject"] );
            message.Subject = message.ReceivedHeaders["subject"];

            //Load message body and attachments

            /*
             * http://tools.ietf.org/html/rfc2046
             * http://en.wikipedia.org/wiki/MIME#Content-Type
             *
             * fully supported simple messages:
             * text/plain, text/html (text/html is not compliant, should be multipart/alternative)
             * text/(unrecognized subtype) treated as application/octet-stream
             *
             * supported multipart messages:
             * multipart/mixed, multipart/alternative
             * multipart/digest
             *
             * partially supported
             * multipart/related => treat as multipart/mixed. related parts are not linked.
             * multipart/signed -> treat as multipart/mixed
             * multipart/encrypted -> treat as multipart/mixed
             * mutipart/form-data -> treat as multipart/mixed
             * multipart/report -> treat as multipart/mixed
             * multipart/appledouble (RFC 1740) -> resource fork is discarded and the data fork becomes an attachment.
             */

            //Load text/plain and text/html as a simple body text. Otherwise, treat the message as multipart.
            //Anything that is text/plain or text/html should become an alternative view. Everything else becomes an attachment.

            ContentType contentType = GetContentType( message.ReceivedHeaders );
            if( 0 == string.Compare( contentType.MediaType, MediaTypeNames.Text.Plain, true ) ||
                0 == string.Compare( contentType.MediaType, MediaTypeNames.Text.Html, true ) )
            {
                LoadBodyText( message, reader, contentType );
            }
            else
            {
                LoadBodyMultipart( message, reader, contentType );
            }

            return message;
        }
        /// <summary>
        /// Loads From, To, CC and Bcc properties using the values stored in the headers.
        /// </summary>
        /// <param name="message"></param>
        private static void LoadMailAddresses( ReceivedMessage message )
        {
            try
            {
                if( !string.IsNullOrEmpty( message.ReceivedHeaders["from"] ) )
                    message.From = new MailAddress( message.ReceivedHeaders["from"] );
                if( !string.IsNullOrEmpty( message.ReceivedHeaders["reply-to"] ) )
            #if NET_FX4
                    message.ReplyToList.Add(new MailAddress(message.ReceivedHeaders["reply-to"]));
            #else
                    message.ReplyTo = new MailAddress( message.ReceivedHeaders["reply-to"] );
            #endif
            }
            catch( Exception ex )
            {
                //swallow exception thrown by bad data.
                if( !(ex is FormatException) )
                    throw ex;
            }

            LoadMailAddresses( message.To, message.ReceivedHeaders["to"] );
            LoadMailAddresses( message.CC, message.ReceivedHeaders["cc"] );
            LoadMailAddresses( message.Bcc, message.ReceivedHeaders["bcc"] );
        }
 private static void LoadBodyText( ReceivedMessage message, TextReader reader, ContentType contentType )
 {
     LineType lastLineType; //not used, because the message is not multipart
     message.Body = LoadBodyString( reader, message.ReceivedHeaders, contentType, out lastLineType );
     message.IsBodyHtml = (contentType.MediaType == MediaTypeNames.Text.Html);
 }
        /// <summary>
        /// Add alternate views and attachments to the existing message object.
        /// Each component is separated boundary text defined in the contentType.Boundary variable.
        /// Each component within a boundary has its own headers defining the payload.
        /// Media types text/plain and text/html go into AlternateView objects.
        /// All other media types will be treated as attachments.
        /// </summary>
        /// <param name="message"></param>
        /// <param name="reader"></param>
        /// <param name="contentType"></param>
        private static void LoadBodyMultipart( ReceivedMessage message, TextReader reader, ContentType contentType )
        {
            /* http://www.w3.org/Protocols/rfc1341/7_2_Multipart.html */
            //each component of the multipart message will be separated by a boundary.
            //each section of text within a boundary should have headers to describe it or in the absence of headers
            //assumed to be ASCII text/plain.
            //a valid message component is preceded and followed by a the boundary text
            //which is two hyphens followed by the value Boundary property of the main ContentType object.

            //UNDONE: Unsupported for now: In the case of multipart/related, the attachments should be done as LinkedResources of the text/html AlternativeView.
            //This is a nice to have but not critical. Last time I checked, Gmail didn't even support these kinds
            //of internal references, either.

            /*******************************************************************************************
             * the text following the message headers and preceding the first boundary is to be ignored.
             * any text at after the final boundary is also to be ignored.
            /*******************************************************************************************/

            foreach( var part in LoadMultipart( reader, contentType ) )
            {
                if( part is AlternateView )
                    message.AlternateViews.Add( part as AlternateView );
                else if( part is Attachment )
                    message.Attachments.Add( part as Attachment );
            }
            //scroll past epilogue
            string buff;
            while( null != (buff = reader.ReadLine()) && (LineType.EOF != GetLineType( buff, contentType )) );
        }