/// <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; } }