private void ParseMessage(SharpMimeMessage part, MimeTopLevelMediaType types, bool html, SharpDecodeOptions options, String preferredtextsubtype, 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"
if (part.Header.TopLevelMediaType.Equals(MimeTopLevelMediaType.message))
{
// Only message/rfc822 allowed, other subtypes ignored
if (part.Header.SubType == "rfc822")
{
// If NotRecursiveRfc822 option is set, handle part as an attachment
if ((options & SharpDecodeOptions.NotRecursiveRfc822) == SharpDecodeOptions.NotRecursiveRfc822)
{
goto case anmar.SharpMimeTools.MimeTopLevelMediaType.application;
}
}
else
{
break;
}
}
if (part.Header.SubType.Equals("alternative") && part.PartsCount > 0)
{
SharpMimeMessage altenative = null;
// Get the first mime part of the alternatives that has a accepted Mime-Type
for (int i = part.PartsCount; i > 0; i--)
{
SharpMimeMessage 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 || (preferredtextsubtype != null && item.Header.SubType == preferredtextsubtype))
{
break;
}
// This one is preferred over the last part
}
else if (preferredtextsubtype != null && 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 & SharpDecodeOptions.NamedAnchors) == SharpDecodeOptions.NamedAnchors)
{
// There is a previous text body, so enclose it in <pre>
if (!HasHtmlBody && _body.Length > 0)
{
_body = String.Concat("<pre>", HttpUtility.HtmlEncode(_body), "</pre>");
HasHtmlBody = true;
}
// Add the anchor
_body = String.Concat(_body, "<a name=\"", SharpMimeTools.Rfc2392Url(MessageID), "_", SharpMimeTools.Rfc2392Url(part.Header.ContentID), "\"></a>");
}
ParseMessage(altenative, types, html, options, preferredtextsubtype, path);
}
// TODO: Take into account each subtype of "multipart" and "message"
}
else if (part.PartsCount > 0)
{
foreach (SharpMimeMessage item in part)
{
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 = HasHtmlBody;
// HTML content not allowed
if (part.Header.SubType.Equals("html"))
{
if (!html)
break;
else
HasHtmlBody = true;
}
if (html && part.Header.Contains("Content-ID") && (options & SharpDecodeOptions.NamedAnchors) == SharpDecodeOptions.NamedAnchors)
{
HasHtmlBody = true;
}
if (HasHtmlBody && !body_was_html && !String.IsNullOrEmpty(_body))
{
_body = String.Concat("<pre>", HttpUtility.HtmlEncode(_body), "</pre>");
}
// If message body is html and this part has a Content-ID field
// add an anchor to mark this body part
if (HasHtmlBody && part.Header.Contains("Content-ID") && (options & SharpDecodeOptions.NamedAnchors) == SharpDecodeOptions.NamedAnchors)
{
_body = String.Concat(_body, "<a name=\"", SharpMimeTools.Rfc2392Url(MessageID), "_", SharpMimeTools.Rfc2392Url(part.Header.ContentID), "\"></a>");
}
if (HasHtmlBody && part.Header.SubType.Equals("plain"))
{
_body = String.Concat(_body, "<pre>", HttpUtility.HtmlEncode(part.BodyDecoded), "</pre>");
}
else
_body = String.Concat(_body, part.BodyDecoded);
}
else
{
if ((types & MimeTopLevelMediaType.application) != MimeTopLevelMediaType.application)
{
return;
}
goto case anmar.SharpMimeTools.MimeTopLevelMediaType.application;
}
break;
case MimeTopLevelMediaType.application:
case MimeTopLevelMediaType.audio:
case MimeTopLevelMediaType.image:
case MimeTopLevelMediaType.video:
// Attachments not allowed.
if ((options & SharpDecodeOptions.AllowAttachments) != SharpDecodeOptions.AllowAttachments)
break;
SharpAttachment attachment = null;
// Save to a file
if (path != null)
{
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
{
using (MemoryStream stream = new MemoryStream())
{
if (part.DumpBody(stream))
{
if (stream != null && stream.CanSeek)
stream.Seek(0, SeekOrigin.Begin);
attachment = new SharpAttachment(stream);
if (part.Name != null)
attachment.Name = part.Name;
else
attachment.Name = String.Concat("generated_", part.GetHashCode(), ".", part.Header.SubType);
attachment.Size = stream.Length;
}
}
}
if (attachment != null && part.Header.SubType == "ms-tnef" && (options & SharpDecodeOptions.DecodeTnef) == SharpDecodeOptions.DecodeTnef)
{
// Try getting attachments form a tnef stream
Stream stream = attachment.Stream;
SharpTnefMessage tnef = new SharpTnefMessage(stream);
if (tnef.Parse(path))
{
if (tnef.Attachments != null)
{
Attachments.AddRange(tnef.Attachments);
}
attachment.Close();
// Delete the raw tnef file
if (attachment.SavedFile != null)
{
if (stream != null && stream.CanRead)
{
stream.Close();
stream = null;
}
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();
stream = null;
}
}
stream = null;
tnef = null;
}
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 = SharpMimeTools.parseDate(part.Header.ContentDispositionParameters["creation-date"]);
// Store attachment's LastWriteTime
if (part.Header.ContentDispositionParameters.ContainsKey("modification-date"))
attachment.LastWriteTime = SharpMimeTools.parseDate(part.Header.ContentDispositionParameters["modification-date"]);
if (part.Header.Contains("Content-ID"))
attachment.ContentID = part.Header.ContentID;
Attachments.Add(attachment);
}
break;
default:
break;
}
}