private void ProcessSingleBody() { string[] lines = _body.Split('\n'); _partBuilder.Length = 0; if (_content_type.ToLower().IndexOf("/html") < 0) { ProcessSinglePlainBody(lines); } else { ProcessSingleHtmlBody(lines); } if (_bodyBuilder.Length > 0 || _htmlBodyBuilder.Length > 0) { string cte = _content_transfer_encoding; if (Utils.StartsWith(cte, "quoted-printable", true)) { string body = _bodyBuilder.ToString(); _bodyBuilder.Length = 0; _bodyBuilder.Append(MIMEParser.DecodeQuotedPrintable(_charset, body)); body = _htmlBodyBuilder.ToString(); _htmlBodyBuilder.Length = 0; _htmlBodyBuilder.Append(MIMEParser.DecodeQuotedPrintable(_charset, body)); } else if (Utils.StartsWith(cte, "base64", true)) { string body = _bodyBuilder.ToString(); _bodyBuilder.Length = 0; _bodyBuilder.Append(MIMEParser.DecodeBase64(_charset, body)); body = _htmlBodyBuilder.ToString(); _htmlBodyBuilder.Length = 0; _htmlBodyBuilder.Append(MIMEParser.DecodeBase64(_charset, body)); } else { string body = _bodyBuilder.ToString(); _bodyBuilder.Length = 0; _bodyBuilder.Append(MIMEParser.TranslateRawStringInCharset(_charset, body)); body = _htmlBodyBuilder.ToString(); _htmlBodyBuilder.Length = 0; _htmlBodyBuilder.Append(MIMEParser.TranslateRawStringInCharset(_charset, body)); for (int i = 0; i < _parts.Count; ++i) { MessagePart attachment = (MessagePart)_parts[i]; attachment.Name = MIMEParser.TranslateRawStringInCharset(_charset, attachment.Name); } } } }
private static string DecodeLine(string line, MessagePartEncoding MIME_encoding, string bodyCharset) { if (MIME_encoding == MessagePartEncoding.QuotedPrintable) { line = MIMEParser.DecodeQuotedPrintable(bodyCharset, line); } else if (MIME_encoding == MessagePartEncoding.Base64) { line = MIMEParser.DecodeBase64(bodyCharset, line); } else { line = MIMEParser.TranslateRawStringInCharset(bodyCharset, line); } return(line); }
private static string EscapeSinglePeriodsAndTranslateToCharset(string body, string charset) { string[] lines; lines = body.Split('\n'); bool areSinglePeriods = false; for (int i = 0; i < lines.Length; ++i) { if (lines[i].StartsWith(".")) { lines[i] = lines[i].Insert(0, "."); areSinglePeriods = true; } } StringBuilder bodyBuilder = StringBuilderPool.Alloc(); try { if (areSinglePeriods) { for (int i = 0; i < lines.Length; ++i) { bodyBuilder.Append(lines[i]); bodyBuilder.Append('\n'); } body = bodyBuilder.ToString(); } bodyBuilder.Length = 0; byte[] bytes = MIMEParser.GetEncodingExceptionSafe(charset).GetBytes(body); for (int i = 0; i < bytes.Length; ++i) { bodyBuilder.Append((char)bytes[i]); } return(bodyBuilder.ToString()); } finally { StringBuilderPool.Dispose(bodyBuilder); } }
/** * builds MIME mail/news body for plaintext bodies */ public static string BuildMIMEBody(string body, string bodyCharset, string bodyEncoding, out string boundary, params string[] fullnames) { string newBoundary = "----++Omea_Parts_Splitter" + new Random().NextDouble().ToString().Substring(1); StringBuilder bodyBuilder = StringBuilderPool.Alloc(); try { // add MIME help string bodyBuilder.Append("This is a multi-part message in MIME format.\r\n"); // encode and add body bodyEncoding = bodyEncoding.ToLower(); bodyBuilder.Append(newBoundary); bodyBuilder.Append("\r\nContent-Type: text/plain"); if (bodyCharset.Length > 0) { bodyBuilder.Append("; charset="); bodyBuilder.Append(bodyCharset); } if (bodyEncoding == "quoted-printable") { bodyBuilder.Append("\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\n"); string[] lines = body.Split('\n'); foreach (string line in lines) { bodyBuilder.Append(MIMEParser.EncodeQuotedPrintable(bodyCharset, line.TrimEnd('\r'))); bodyBuilder.Append("\r\n"); } } else if (bodyEncoding == "base64") { body = MIMEParser.EncodeBase64(bodyCharset, body); bodyBuilder.Append("\r\nContent-Transfer-Encoding: base64\r\n"); /** * split base64 body onto several lines */ string line; int i = 0; int lineLen = _UULinePreferredLen * 4 / 3; while (i < body.Length) { line = body.Substring(i, (lineLen <= body.Length - i) ? lineLen : body.Length - i); bodyBuilder.Append("\r\n"); bodyBuilder.Append(line); i += line.Length; } } else { bodyBuilder.Append("\r\nContent-Transfer-Encoding: 8bit\r\n\r\n"); bodyBuilder.Append(EscapeSinglePeriodsAndTranslateToCharset(body, bodyCharset)); } // encode and add attachments byte[] bytes = new byte[_UULinePreferredLen]; foreach (string fullname in fullnames) { FileStream fs = OpenAttachment(fullname); if (fs != null) { string filename = Path.GetFileName(fullname); if (MIMEParser.Has8BitCharacters(filename)) { filename = MIMEParser.CreateBase64MIMEString(bodyCharset, filename); } bodyBuilder.Append("\r\n"); bodyBuilder.Append(newBoundary); string contentType = MIMEContentTypes.GetContentType(Path.GetExtension(fullname)); if (contentType == null) { bodyBuilder.Append("\r\nContent-Type: application/octet-stream; name=\""); } else { bodyBuilder.Append("\r\nContent-Type: "); bodyBuilder.Append(contentType); bodyBuilder.Append("; name=\""); } bodyBuilder.Append(filename); bodyBuilder.Append("\"\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment; filename=\""); bodyBuilder.Append(filename); bodyBuilder.Append("\"\r\n"); int read; while ((read = fs.Read(bytes, 0, bytes.Length)) > 0) { bodyBuilder.Append("\r\n"); bodyBuilder.Append(MIMEParser.EncodeBase64(bytes, read)); } } } // finish multipart message bodyBuilder.Append("\r\n"); bodyBuilder.Append(newBoundary); bodyBuilder.Append("--"); // ignore the "--" prefix boundary = newBoundary.Substring(2); return(bodyBuilder.ToString()); } finally { StringBuilderPool.Dispose(bodyBuilder); } }
private void ProcessMutipartBody() { /** * extract boundary from content-type */ string boundary = string.Empty; int boundaryBegin = _content_type.ToLower().IndexOf("boundary="); if (boundaryBegin > 0) { boundaryBegin += 9; int boundaryEnd = _content_type.IndexOfAny(_boundaryDelimiters, boundaryBegin); if (boundaryEnd < 0) { boundaryEnd = _content_type.Length; } if (boundaryEnd > boundaryBegin) { boundary = _content_type.Substring( boundaryBegin, boundaryEnd - boundaryBegin).Replace("\"", string.Empty).Trim(); } } if (boundary.Length == 0) { _bodyBuilder.Append("Bad multipart message: the \"Content-Type\" header doesn't contain valid boundary. Message source follows as plain text.\r\n\r\n"); _bodyBuilder.Append(_body); return; } boundary = "--" + boundary; string finishingBoundary = boundary + "--"; string[] lines = _body.Split('\n'); string line = string.Empty; int i = 0; bool inHeaders = true; bool isHtmlBody = false; bool isAttachment = false; bool isInline = false; bool isAlternative = false; MessagePartEncoding MIME_encoding = MessagePartEncoding.None; string bodyCharset = string.Empty; string filename = string.Empty; string altBoundary = string.Empty; string contentId = string.Empty; _partBuilder.Length = 0; /** * search for the first boundary */ for ( ; i < lines.Length; ++i) { line = lines[i].TrimEnd('\r'); if (line.StartsWith(boundary)) { ++i; break; } } for ( ; i < lines.Length && !line.StartsWith(finishingBoundary); ++i) { line = lines[i].TrimEnd('\r'); /** * if not in headers then process next part */ if (!inHeaders) { /** * if filename not present process body */ if (filename.Length == 0) { if (isHtmlBody) { i = ProcessHTMLBody(lines, i, boundary, MIME_encoding, bodyCharset); } else { i = ProcessBody(lines, i, boundary, MIME_encoding, bodyCharset); /** * if body is nested multipart/alternative then parse it in its turn */ if (isAlternative && altBoundary.Length > 0) { MultiPartBodyParser parser = new MultiPartBodyParser( _bodyBuilder.ToString(), "multipart/alternative; boundary=" + altBoundary, _content_transfer_encoding, _charset); _bodyBuilder.Length = 0; _htmlBodyBuilder.Length = 0; _parts.AddRange(parser.GetParts()); } } } else /** * if filename present then we are to extract attacment */ { i = ProcessAttachment(lines, i, boundary, MIME_encoding); if (MIMEParser.IsMIMEString(filename)) { filename = MIMEParser.DecodeMIMEString(filename); } string partStr = _partBuilder.ToString(); MessagePart attachment = null; switch (MIME_encoding) { case MessagePartEncoding.QuotedPrintable: { attachment = new MessagePart(MIMEParser.DecodeQuotedPrintable(partStr), filename); break; } case MessagePartEncoding.Base64: { byte[] bytes = MIMEParser.DecodeBase64(partStr); if (bytes != null) { attachment = new MessagePart(bytes, filename); } break; } default: { attachment = new MessagePart( MIMEParser.GetEncodingExceptionSafe(bodyCharset).GetBytes(partStr), filename); break; } } if (attachment != null) { if (isInline) { attachment.PartType = MessagePartTypes.Inline; } else { if (contentId.Length > 0) { attachment.PartType = MessagePartTypes.Embedded; attachment.ContentId = contentId; } } _parts.Add(attachment); } _partBuilder.Length = 0; } /** * reset encoding, charset, filename, alternative boundary, content-id and flags */ MIME_encoding = MessagePartEncoding.None; bodyCharset = _charset; filename = altBoundary = contentId = string.Empty; inHeaders = true; isHtmlBody = isAttachment = isInline = false; } else { if (line.Length == 0) { inHeaders = false; } else { string lowerLine = line.ToLower(); if (lowerLine.StartsWith("content-type:")) { string content_type = lowerLine.Substring(14); if (content_type.StartsWith("multipart/alternative") || content_type.StartsWith("multipart/related")) { isAlternative = true; } else if (content_type.StartsWith("application/") || content_type.StartsWith("image/")) { isAttachment = true; } else { if (content_type.StartsWith("text/html")) { isHtmlBody = true; } bodyCharset = DetectCharset(lowerLine, line, _charset); } } else if (lowerLine.StartsWith("content-transfer-encoding:")) { string encoding = lowerLine.Substring(27); if (encoding.StartsWith("quoted-printable")) { MIME_encoding = MessagePartEncoding.QuotedPrintable; } else if (encoding.StartsWith("base64")) { MIME_encoding = MessagePartEncoding.Base64; } } else if (lowerLine.StartsWith("content-disposition:")) { string headerValue = lowerLine.Substring(21); if (headerValue.StartsWith("attachment")) { isAttachment = true; } else if (headerValue.StartsWith("inline")) { isInline = true; } } else if (lowerLine.StartsWith("content-id:")) { contentId = line.Substring(12).Replace("<", "").Replace(">", ""); } if ((isAttachment || isInline) && filename.Length == 0) { int nameBegin; if ((nameBegin = lowerLine.IndexOf("filename=")) > 0) { filename = line.Substring(nameBegin + 9).Replace("\"", string.Empty).Trim(); } if ((nameBegin = lowerLine.IndexOf("name=")) > 0) { filename = line.Substring(nameBegin + 5).Replace("\"", string.Empty).Trim(); } } if (isAlternative && altBoundary.Length == 0) { if ((boundaryBegin = lowerLine.IndexOf("boundary=")) > 0) { altBoundary = line.Substring(boundaryBegin + 9).Replace("\"", string.Empty).Trim(); } } } } } }