/// <summary>
        /// Decode the given stream into a collection of parts.
        /// </summary>
        /// <returns></returns>
        public ITransmissionPartCollection Decode(string name, Stream stream, string mimeType, string id = null) {
            ParameterCheck.ParameterRequired(stream, "stream");
            ParameterCheck.StringRequiredAndNotWhitespace(mimeType, "mimeType");

            var transmissionPartCollection = new TransmissionPartCollection();

            try {
                int nextContentId = 1;

                var mime = new Mime(stream);
                Console.WriteLine("Parts " + mime.NumParts);
                logger.DebugFormat("Parts {0}", mime.NumParts);

                for (int partIndex = 0; partIndex < mime.NumParts; partIndex++) {
                    Mime mimePart = mime.GetPart(partIndex);
                    string contentId = mimePart.GetHeaderField("Content-id");
                    if (contentId.Trim().Length == 0) {
                        var sb = new StringBuilder();
                        sb.Append("OAIPART_"); //TODO determine better name for mime part than OAIPART_
                        sb.Append(DateTime.Now.Ticks.ToString());
                        sb.Append("_");
                        sb.Append(nextContentId.ToString());
                        contentId = sb.ToString();
                        nextContentId++;
                    }

                    string contentType = mimePart.ContentType;

                    //content type may contain ;char-encoding.  Strip it off if found.
                    if (contentType != null) {
                        contentType = contentType.NormalizeContentType();
                    }

                    //TODO We need better way to get a BodyStream from a MimePart.
                    transmissionPartCollection.Add(transmissionPartFactory.CreateTransmissionPart(name,
                                                                                                  new MemoryStream(mimePart.GetBodyBinary()),
                                                                                                  contentType, contentId));
                }
            }
            catch (Exception err) {
                logger.Error(Messages.MimeEncoding_Decode_GeneralDecodingError, err);
                throw new JdfException(Messages.MimeEncoding_Decode_GeneralDecodingError, err);
            }

            if (transmissionPartCollection.Count == 0) {
                logger.Error(Messages.MimeEncoding_Decode_NoMessagePartsToDecode);
                throw new JdfException(Messages.MimeEncoding_Decode_NoMessagePartsToDecode);
            }

            return transmissionPartCollection;
        }
 /// <summary>
 /// Remove the given Mime from the collection.
 /// </summary>
 /// <param name="part">The part to remove.</param>
 public void Remove(Mime part)
 {
     _parts.Remove(part);
 }
 /// <summary>
 /// Add a mime message.
 /// </summary>
 /// <param name="part">The part to add.</param>
 /// <returns>The newly added part.</returns>
 public Mime Add(Mime part)
 {
     _parts.Add(part);
     return part;
 }
        /// <summary>
        /// Encode a set of transmission parts into a stream suitable for 
        /// transmission with or without Binary-Encoding Attachment.
        /// </summary>
        /// <param name="parts">The parts to encode.</param>
        /// <param name="contentType">The MIME Type of the TransmissionPartCollection contents.</param>
        /// <param name="withBinaryEncodingAttachment">if true, save all Attachments with binary-encoding type. </param>
        /// <returns>An OptimalEncodingResult with the stream and the name of the backing file store if there is one.</returns>
        EncodingResult OptimalEncode(ITransmissionPartCollection parts, out string contentType, bool withBinaryEncodingAttachment) {
            using (var mime = new Mime()) {
                mime.NewMultipartRelated();

                foreach (ITransmissionPart part in parts) {
                    var mimePart = new Mime();

                    mimePart.SetHeaderField("Content-ID", part.Id);

                    //TODO optimize call to get the bytes from the stream
                    byte[] data = null;
                    using (var partStream = part.CopyOfStream()) {
                        using (var sr = new BinaryReader(partStream)) {
                            data = sr.ReadBytes((int)partStream.Length);
                        }
                    }
                    //TODO determine if this is how we should handle it.
                    if (!part.MimeType.Equals(MimeTypeHelper.JdfMimeType)
                            && !part.MimeType.Equals(MimeTypeHelper.JmfMimeType)
                            && !part.MimeType.StartsWith("text/")) {
                        //for text and jdf/jmf documents, do not base64 encode them.
                        mimePart.EncodingType = Mime.MimeEncoding.Base64;
                    }
                    else {
                        mimePart.EncodingType = Mime.MimeEncoding.Binary;
                    }
                    mimePart.SetBodyFromBinary(data);

                    mimePart.ContentType = part.MimeType;
                    mime.AppendPart(mimePart);
                }

                contentType = mime.ContentType;

                mime.CreateDefaultType();

                //TODO see if there is a more optimal way to get the stream from the mime.
                return new EncodingResult(mime.GetMimeStream(), contentType);
            }
        }
 /// <summary>
 /// Append the given part to the body
 /// </summary>
 /// <param name="part"></param>
 public void AppendPart(Mime part)
 {
     _mimes.Add(part);
 }
 /// <summary>
 /// Add child message
 /// </summary>
 /// <param name="childMime"></param>
 public void Add(Mime childMime)
 {
     _mimes.Add(childMime);
 }
        /// <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;
            }
        }