/*public static MimePart ParsePart(string data, X509Certificate2Collection certificates, SignedCms signature) { MimePart part = new MimePart(); if (signature.Certificates.Count != 0) part.IsSigned = true; part.Signature = signature; string header = data.Substring(0,Regex.Match(data, @"\r?\n\r?\n").Index); Match m = Regex.Match(header, @"(?<=((\r?\n)|\n)|\A)\S+:(.|(\r?\n[\t ]))+(?=((\r?\n)\S)|\Z)"); while (m.Success) { if (m.Value.ToLower().StartsWith("content-type:")) part.ContentType = Parser.GetContentType(m.Value); else if (m.Value.ToLower().StartsWith("content-disposition:")) part.ContentDisposition = Parser.GetContentDisposition(m.Value); part.HeaderFields.Add(FormatFieldName(m.Value.Substring(0, m.Value.IndexOf(':'))), m.Value.Substring(m.Value.IndexOf(':') + 1)); m = m.NextMatch(); } // S/MIME support // TODO : Differenciate by ASN.1 decoding if (part.ContentType.MimeType!=null && (part.ContentType.MimeType.IndexOf("application/x-pkcs7-mime") != -1 || part.ContentType.MimeType.IndexOf("application/pkcs7-mime") != -1)) { if (part.ContentType.Parameters["smime-type"]!=null && part.ContentType.Parameters["smime-type"].ToLower().IndexOf("signed-data") != -1) { part.IsSigned = true; string contentBase64 = data.Substring(Regex.Match(data, @"\r?\n\r?\n").Index); byte[] signedData = System.Convert.FromBase64String(contentBase64); SignedCms sig = new SignedCms(); sig.Decode(signedData); return ParsePart(System.Text.Encoding.ASCII.GetString(sig.ContentInfo.Content), certificates, sig); } else { part.IsEncrypted = true; string contentBase64 = data.Substring(Regex.Match(data, @"\r?\n\r?\n").Index); EnvelopedCms env = new EnvelopedCms(); env.Decode(System.Convert.FromBase64String(contentBase64)); env.Decrypt(certificates); byte[] decryptedContent = env.ContentInfo.Content; return ParsePart(System.Text.Encoding.ASCII.GetString(decryptedContent), certificates); } } if (part.Charset==null || part.Charset.Length < 1) part.Charset = "us-ascii"; byte[] binData = System.Text.Encoding.ASCII.GetBytes(data); try { part.TextContent = System.Text.Encoding.GetEncoding(part.Charset).GetString(binData); } catch { part.TextContent = data; } m = Regex.Match(part.TextContent,@"\r?\n\r?\n"); part.TextContent = part.TextContent.Substring(m.Index+m.Length); if (part.ContentType.MimeType != null && part.ContentType.MimeType.IndexOf("multipart/signed") != -1) part.IsSigned = true; if (part.ContentTransferEncoding==ContentTransferEncoding.QuotedPrintable) part.TextContent = Codec.FromQuotedPrintable(part.TextContent,part.Charset); if (part.ContentTransferEncoding == ContentTransferEncoding.Base64) { part.TextContent = part.TextContent.Trim('\r', '\n'); part.BinaryContent = System.Convert.FromBase64String(part.TextContent); } else part.BinaryContent = System.Text.Encoding.GetEncoding(part.Charset).GetBytes(part.TextContent); return part; }*/ private static MultipartContainer ParseMultipartContainer(MimePart part) { MultipartContainer container = new MultipartContainer(); string boundary = part.ContentType.Parameters["boundary"]; string[] arrpart = Regex.Split(part.TextContent, @"\r?\n?" + Regex.Escape("--" + boundary)); for (int i = 0; i < arrpart.Length; i++) { string strpart = arrpart[i]; if (!strpart.StartsWith("--")) { container.PartTree.Add(Parser.ParseMimeTypedAndEncodedContent(strpart)); } } return container; }
public static MimeTypedAndEncodedContent ParseMimeTypedAndEncodedContent(string data) { MimeTypedAndEncodedContent part = new MimeTypedAndEncodedContent(); // Separate header and body. int headerEnd = Regex.Match(data, @".(?=\r?\n\r?\n)").Index + 1; int bodyStart = Regex.Match(data, @"(?<=\r?\n\r?\n).").Index - 1; string header = data.Substring(0,headerEnd); header = Parser.Unfold(header); header = Codec.RFC2047Decode(header); string body = data.Substring(bodyStart); // Parse header fields and their parameters. Match m = Regex.Match(header, @"(?<=((\r?\n)|\n)|\A)\S+:(.|(\r?\n[\t ]))+(?=((\r?\n)\S)|\Z)"); while (m.Success) { if (m.Value.ToLower().StartsWith("content-type:")) part.ContentType = Parser.GetContentType(m.Value); else if (m.Value.ToLower().StartsWith("content-disposition:")) part.ContentDisposition = Parser.GetContentDisposition(m.Value); part.HeaderFields.Add(FormatFieldName(m.Value.Substring(0, m.Value.IndexOf(':'))), m.Value.Substring(m.Value.IndexOf(':') + 1)); m = m.NextMatch(); } // Is it QP encoded text ? if (part.ContentTransferEncoding.Equals(ContentTransferEncoding.QuotedPrintable)) { // Get the destination charset, or default to us-ascii. string charset = "us-ascii"; if (part.Charset != null && part.Charset.Length > 0) charset = part.Charset; // Decode part.TextContent = Codec.FromQuotedPrintable(body, charset); //part.BinaryContent = System.Text.Encoding.GetEncoding(charset).GetBytes(part.TextContent); } // Is it a Base64 encoded content ? else if (part.ContentTransferEncoding.Equals(ContentTransferEncoding.Base64)) { part.TextContent = body; //part.BinaryContent = Convert.FromBase64String(part.TextContent); } // Is it plain text or binary data ? else //if (part.ContentTransferEncoding.Equals(ContentTransferEncoding.SevenBits) || part.ContentTransferEncoding.Equals(ContentTransferEncoding.SevenBits)) { // Get the destination charset, or default to us-ascii. string charset = "us-ascii"; if (part.Charset != null && part.Charset.Length > 0) charset = part.Charset; // Extract part.TextContent = body; //part.BinaryContent = System.Text.Encoding.GetEncoding(charset).GetBytes(part.TextContent); } // Now we have the decoded content and it's type. Let's take appropriate action. if (part.ContentType.Type.Equals("multipart")) { MultipartContainer multipart = Parser.ParseMultipartContainer(part); multipart.Track = DispatchTrack.MultipartContainer; return multipart; } else if (part.ContentType.Type.Equals("message")) { // TODO } //else if (part.ContentType.Type.Equals("multipart")) return part; }