private static MimeHeader Encode(MimeHeader header) { var format = header.Format ?? MimeFormat.Unspecified; return new MimeHeader(header.Name, EncodeHeaderFieldBody(header, format.Folding - 1/*HT*/, header.Name.Length + 2, format.GetHeaderFoldingString())); }
private static MimeHeaderCollection ParseHeader(LineOrientedStream stream) { var headers = new MimeHeaderCollection(); MimeHeader current = null; for (;;) { var lineBytes = stream.ReadLine(false); if (lineBytes == null) break; // unexpected end of stream var line = new ByteString(lineBytes); if (line.IsEmpty) break; // end of headers if (line[0] == Octets.HT || line[0] == Octets.SP) { // LWSP-char // folding if (current == null) // ignore incorrect formed header continue; current.Value += Chars.SP; current.Value += line.TrimStart().ToString(); } else { // field = field-name ":" [ field-body ] CRLF // field-name = 1*<any CHAR, excluding CTLs, SPACE, and ":"> var delim = line.IndexOf(MimeHeader.NameBodyDelimiter); // ':' if (delim < 0) { // ignore incorrect formed header current = null; continue; } var header = new MimeHeader(line.Substring(0, delim).TrimEnd().ToString(), line.Substring(delim + 1).TrimStart().ToString()); headers.Add(header); current = header; } } return headers; }
/// <summary> /// Add Content type to the given header /// </summary> /// <param name="headers">headers to add content typ</param> public void AddContentType(MimeHeaderCollection headers) { if (!headers.Contains("Content-Type") && _contentType != null) { MimeHeader mh = new MimeHeader("Content-Type", _contentType); //if it is a text type, add the character set if (_contentType.StartsWith("text/") || _contentType.StartsWith("application/vnd.cip4-j")) { mh.Parameters.Add(new MimeHeaderParam("charset", Mime.MimeCharsetToString(_charset))); } headers.Add(mh); } }
/// <summary> /// This method checks and adds additional required header fields. /// 1. If it is a text type, add the character set /// 2. Check and add Content-Transfer-Encoding /// 3. Calculates the content length. For base64 encoding, this /// requires encoding the buffer. Therefore, the encoded data is stored in /// _encodedString for use during the body right when base64 encoding is used. /// </summary> public void AddAdditionalHeader(MimeHeaderCollection headers) { //Add Content-Type AddContentType(headers); //Add Content-Transfer-Encoding if (!headers.Contains("Content-Transfer-Encoding") && _encoding != MimeEncoding.E7Bit) { headers.Add(new MimeHeader("Content-Transfer-Encoding", Mime.MimeEncodingToString(_encoding))); } //Add Content-Disposition: attachment; filename="Job_10235.jdf" if (!headers.Contains("Content-Disposition") && _fileName != null) { FileInfo fi = new FileInfo(_fileName); MimeHeader mh = new MimeHeader("Content-Disposition", "attachment"); mh.Parameters.Add(new MimeHeaderParam("filename", fi.Name)); headers.Add(mh); } //Add Content-Length if (_buffer != null) { int contentLength = 0; if (_encoding == MimeEncoding.Base64) { if (EncodedString.Length % 76 > 0) { contentLength = EncodedString.Length / 76 * 2 + EncodedString.Length + 1; } else { contentLength = EncodedString.Length / 76 * 2 + EncodedString.Length; } } else { _encodedString = null; contentLength = _buffer.Length; } if (contentLength != 0) { if (!headers.Contains("Content-Length")) { headers.Add(new MimeHeader("Content-Length", contentLength.ToString())); } else { headers["Content-Length"].Value = contentLength.ToString(); } } } }
/// <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; } }
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; } } }