private System.String ReplaceUrlTokens(System.String url, SharpAttachment attachment) { if (string.IsNullOrEmpty(url) || url.IndexOf('[') == -1 || url.IndexOf(']') == -1) return url; if (url.IndexOf("[MessageID]", System.StringComparison.Ordinal) != -1) { url = url.Replace("[MessageID]", System.Web.HttpUtility.UrlEncode(MimeTools.Rfc2392Url(this.MessageID))); } if (attachment != null && attachment.ContentID != null) { if (url.IndexOf("[ContentID]", System.StringComparison.Ordinal) != -1) { url = url.Replace("[ContentID]", System.Web.HttpUtility.UrlEncode(MimeTools.Rfc2392Url(attachment.ContentID))); } if (url.IndexOf("[Name]", System.StringComparison.Ordinal) != -1) { url = url.Replace("[Name]", attachment.SavedFile != null ? System.Web.HttpUtility.UrlEncode(attachment.SavedFile.Name) : System.Web.HttpUtility.UrlEncode(attachment.Name)); } } return url; }
private void UuDecode(System.String path) { if (this._body.Length == 0 || this._body.IndexOf("begin ", System.StringComparison.Ordinal) == -1 || this._body.IndexOf("end", System.StringComparison.Ordinal) == -1) return; System.Text.StringBuilder sb = new System.Text.StringBuilder(); System.IO.StringReader reader = new System.IO.StringReader(this._body); System.IO.Stream stream = null; SharpAttachment attachment = null; for (System.String line = reader.ReadLine(); line != null; line = reader.ReadLine()) { if (stream == null) { // Found the start point of uuencoded content if (line.Length > 10 && line[0] == 'b' && line[1] == 'e' && line[2] == 'g' && line[3] == 'i' && line[4] == 'n' && line[5] == ' ' && line[9] == ' ') { System.String name = System.IO.Path.GetFileName(line.Substring(10)); System.Console.WriteLine(System.String.Concat("uuencoded content found. name[", name, "]")); // In-Memory decoding if (path == null) { attachment = new SharpAttachment(new System.IO.MemoryStream()); stream = attachment.Stream; // Filesystem decoding } else { attachment = new SharpAttachment(new System.IO.FileInfo(System.IO.Path.Combine(path, name))); stream = attachment.SavedFile.OpenWrite(); } attachment.Name = name; // Not uuencoded line, so add it to new body } else { sb.Append(line); sb.Append(System.Environment.NewLine); } } else { // Content finished if (line.Length == 3 && line == "end") { stream.Flush(); if (stream.Length > 0) { System.Console.WriteLine(System.String.Concat("uuencoded content finished. name[", attachment.Name, "] size[", stream.Length, "]")); attachment.Size = stream.Length; this._attachments.Add(attachment); } // When decoding to a file, close the stream. if (attachment.SavedFile != null || stream.Length == 0) { stream.Close(); } attachment = null; stream = null; // Decode and write uuencoded line } else { MimeTools.UuDecodeLine(line, stream); } } } if (stream != null && stream.CanRead) { stream.Close(); } reader.Close(); this._body = sb.ToString(); }
private void ParseMessage(MimeMessage part, MimeTopLevelMediaType types, bool html, DecodeOptions options, System.String preferredtextsubtype, System.String path) { if ((types & part.Header.TopLevelMediaType) != part.Header.TopLevelMediaType) { return; } switch (part.Header.TopLevelMediaType) { case MimeTopLevelMediaType.multipart: case MimeTopLevelMediaType.message: // TODO: allow other subtypes of "message" // Only message/rfc822 allowed, other subtypes ignored if (part.Header.TopLevelMediaType.Equals(MimeTopLevelMediaType.message) && !part.Header.SubType.Equals("rfc822")) break; if (part.Header.SubType.Equals("alternative")) { if (part.PartsCount > 0) { MimeMessage altenative = null; // Get the first mime part of the alternatives that has a accepted Mime-Type for (int i = part.PartsCount; i > 0; i--) { MimeMessage item = part.GetPart(i - 1); if ((types & part.Header.TopLevelMediaType) != part.Header.TopLevelMediaType || (!html && item.Header.TopLevelMediaType.Equals(MimeTopLevelMediaType.text) && item.Header.SubType.Equals("html")) ) { continue; } // First allowed one. if (altenative == null) { altenative = item; // We don't have to select body part based on subtype if not asked for, or not a text one // or it's already the preferred one if (preferredtextsubtype == null || item.Header.TopLevelMediaType != MimeTopLevelMediaType.text || (item.Header.SubType == preferredtextsubtype)) { break; } // This one is preferred over the last part } else if (item.Header.TopLevelMediaType == MimeTopLevelMediaType.text && item.Header.SubType == preferredtextsubtype) { altenative = item; break; } } if (altenative != null) { // If message body as html is allowed and part has a Content-ID field // add an anchor to mark this body part if (html && part.Header.Contains("Content-ID") && (options & DecodeOptions.NamedAnchors) == DecodeOptions.NamedAnchors) { // There is a previous text body, so enclose it in <pre> if (!this._bodyHtml && this._body.Length > 0) { this._body = System.String.Concat("<pre>", System.Web.HttpUtility.HtmlEncode(this._body), "</pre>"); this._bodyHtml = true; } // Add the anchor this._body = System.String.Concat(this._body, "<a name=\"", MimeTools.Rfc2392Url(this.MessageID), "_", MimeTools.Rfc2392Url(part.Header.ContentID), "\"></a>"); } this.ParseMessage(altenative, types, html, options, preferredtextsubtype, path); } } // TODO: Take into account each subtype of "multipart" } else if (part.PartsCount > 0) { foreach (MimeMessage item in part) { this.ParseMessage(item, types, html, options, preferredtextsubtype, path); } } break; case MimeTopLevelMediaType.text: if ((part.Disposition == null || !part.Disposition.Equals("attachment")) && (part.Header.SubType.Equals("plain") || part.Header.SubType.Equals("html"))) { bool body_was_html = this._bodyHtml; // HTML content not allowed if (part.Header.SubType.Equals("html")) { if (!html) break; this._bodyHtml = true; } if (html && part.Header.Contains("Content-ID") && (options & DecodeOptions.NamedAnchors) == DecodeOptions.NamedAnchors) { this._bodyHtml = true; } if (this._bodyHtml && !body_was_html && this._body.Length > 0) { this._body = System.String.Concat("<pre>", System.Web.HttpUtility.HtmlEncode(this._body), "</pre>"); } // If message body is html and this part has a Content-ID field // add an anchor to mark this body part if (this._bodyHtml && part.Header.Contains("Content-ID") && (options & DecodeOptions.NamedAnchors) == DecodeOptions.NamedAnchors) { this._body = System.String.Concat(this._body, "<a name=\"", MimeTools.Rfc2392Url(this.MessageID), "_", MimeTools.Rfc2392Url(part.Header.ContentID), "\"></a>"); } if (this._bodyHtml && part.Header.SubType.Equals("plain")) { this._body = System.String.Concat(this._body, "<pre>", System.Web.HttpUtility.HtmlEncode(part.BodyDecoded), "</pre>"); } else this._body = System.String.Concat(this._body, part.BodyDecoded); } else { if ((types & MimeTopLevelMediaType.application) != MimeTopLevelMediaType.application) { return; } goto case MimeTopLevelMediaType.application; } break; case MimeTopLevelMediaType.application: case MimeTopLevelMediaType.audio: case MimeTopLevelMediaType.image: case MimeTopLevelMediaType.video: // Attachments not allowed. if ((options & DecodeOptions.AllowAttachments) != DecodeOptions.AllowAttachments) break; SharpAttachment attachment = null; // Save to a file if (path != null) { System.IO.FileInfo file = part.DumpBody(path, true); if (file != null) { attachment = new SharpAttachment(file); attachment.Name = file.Name; attachment.Size = file.Length; } // Save to a stream } else { System.IO.MemoryStream stream = new System.IO.MemoryStream(); part.DumpBody(stream); attachment = new SharpAttachment(stream); attachment.Name = part.Name ?? System.String.Concat("generated_", part.GetHashCode(), ".", part.Header.SubType); attachment.Size = stream.Length; } if (attachment != null && part.Header.SubType == "ms-tnef" && (options & DecodeOptions.DecodeTnef) == DecodeOptions.DecodeTnef) { // Try getting attachments form a tnef stream System.IO.Stream stream = attachment.Stream; if (stream != null && stream.CanSeek) stream.Seek(0, System.IO.SeekOrigin.Begin); TnefMessage tnef = new TnefMessage(stream); if (tnef.Parse(path)) { if (tnef.Attachments != null) { this._attachments.AddRange(tnef.Attachments); } attachment.Close(); // Delete the raw tnef file if (attachment.SavedFile != null) { if (stream != null && stream.CanRead) stream.Close(); attachment.SavedFile.Delete(); } attachment = null; tnef.Close(); } else { // The read-only stream is no longer needed and locks the file if (attachment.SavedFile != null && stream != null && stream.CanRead) stream.Close(); } } if (attachment != null) { if (part.Disposition != null && part.Disposition == "inline") { attachment.Inline = true; } attachment.MimeTopLevelMediaType = part.Header.TopLevelMediaType; attachment.MimeMediaSubType = part.Header.SubType; // Store attachment's CreationTime if (part.Header.ContentDispositionParameters.ContainsKey("creation-date")) attachment.CreationTime = MimeTools.parseDate(part.Header.ContentDispositionParameters["creation-date"]); // Store attachment's LastWriteTime if (part.Header.ContentDispositionParameters.ContainsKey("modification-date")) attachment.LastWriteTime = MimeTools.parseDate(part.Header.ContentDispositionParameters["modification-date"]); if (part.Header.Contains("Content-ID")) attachment.ContentID = part.Header.ContentID; this._attachments.Add(attachment); } break; } }