Multipart |
public class MultipartRelated : Multipart, IMultipartRelated, IMultipart, IMimeEntity, IDisposable, ICollection<MimeEntity>, IEnumerable<MimeEntity>, IEnumerable, IList<MimeEntity>
The MultipartRelated type exposes the following members.
Name | Description | |
---|---|---|
MultipartRelated | Initialize a new instance of the MultipartRelated class. | |
MultipartRelated(MimeEntityConstructorArgs) | Initialize a new instance of the MultipartRelated class. | |
MultipartRelated(Object) | Initialize a new instance of the MultipartRelated class. |
Name | Description | |
---|---|---|
Boundary |
Get or set the boundary.
(Inherited from Multipart) | |
ContentBase |
Get or set the base content URI.
(Inherited from MimeEntity) | |
ContentDisposition |
Get or set the content disposition.
(Inherited from MimeEntity) | |
ContentId |
Get or set the Content-Id.
(Inherited from MimeEntity) | |
ContentLocation |
Get or set the content location.
(Inherited from MimeEntity) | |
ContentType |
Get the type of the content.
(Inherited from MimeEntity) | |
Count |
Get the number of parts in the multipart.
(Inherited from Multipart) | |
Epilogue |
Get or set the epilogue.
(Inherited from Multipart) | |
Headers |
Get the list of headers.
(Inherited from MimeEntity) | |
IsAttachment |
Get a value indicating whether this MimePart is an attachment.
(Inherited from MimeEntity) | |
IsReadOnly |
Get a value indicating whether this instance is read only.
(Inherited from Multipart) | |
Item |
Get or set the MimeEntity at the specified index.
(Inherited from Multipart) | |
Preamble |
Get or set the preamble.
(Inherited from Multipart) | |
Root | Get or set the root document of the multipart/related part and the appropriate Content-Type parameters. |
Name | Description | |
---|---|---|
Accept |
Dispatches to the specific visit method for this MIME entity.
(Overrides MultipartAccept(MimeVisitor)) | |
Add |
Add an entity to the multipart.
(Inherited from Multipart) | |
Clear |
Clear a multipart.
(Inherited from Multipart) | |
Clear(Boolean) |
Clear a multipart.
(Inherited from Multipart) | |
Contains(MimeEntity) |
Check if the Multipart contains the specified entity.
(Inherited from Multipart) | |
Contains(Uri) | Check if the MultipartRelated contains a part matching the specified URI. | |
CopyTo |
Copy all of the entities in the Multipart to the specified array.
(Inherited from Multipart) | |
Dispose |
Releases all resources used by the MimeEntity object.
(Inherited from MimeEntity) | |
Dispose(Boolean) |
Release the unmanaged resources used by the Multipart and
optionally releases the managed resources.
(Inherited from Multipart) | |
Equals | (Inherited from Object) | |
Finalize |
Releases unmanaged resources and performs other cleanup operations before the
MimeEntity is reclaimed by garbage collection.
(Inherited from MimeEntity) | |
GetEnumerator |
Get the enumerator for the children of the Multipart.
(Inherited from Multipart) | |
GetHashCode | (Inherited from Object) | |
GetType | (Inherited from Object) | |
IndexOf(MimeEntity) |
Get the index of an entity.
(Inherited from Multipart) | |
IndexOf(Uri) | Get the index of the part matching the specified URI. | |
Insert |
Insert an entity into the Multipart at the specified index.
(Inherited from Multipart) | |
MemberwiseClone | (Inherited from Object) | |
OnHeadersChanged |
Called when the headers change in some way.
(Inherited from MimeEntity) | |
Open(Uri) | Open a stream for reading the decoded content of the MIME part specified by the provided URI. | |
Open(Uri, String, String) | Open a stream for reading the decoded content of the MIME part specified by the provided URI. | |
Prepare |
Prepare the MIME entity for transport using the specified encoding constraints.
(Inherited from Multipart) | |
Remove |
Remove an entity from the multipart.
(Inherited from Multipart) | |
RemoveAt |
Remove an entity from the Multipart at the specified index.
(Inherited from Multipart) | |
RemoveHeader |
Remove a header by name.
(Inherited from MimeEntity) | |
SetHeader(String, Byte) |
Set the value of a header using the raw value.
(Inherited from MimeEntity) | |
SetHeader(String, String) |
Set the value of a header.
(Inherited from MimeEntity) | |
ToString |
Return a String that represents the MimeEntity for debugging purposes.
(Inherited from MimeEntity) | |
TryGetValue |
Get the preferred message body if it exists.
(Overrides MultipartTryGetValue(TextFormat, TextPart)) | |
TryInit |
Tries to use the given object to initialize the appropriate property.
(Inherited from MimeEntity) | |
WriteTo(Stream, CancellationToken) |
Write the MimeEntity to the specified output stream.
(Inherited from MimeEntity) | |
WriteTo(String, CancellationToken) |
Write the MimeEntity to the specified file.
(Inherited from MimeEntity) | |
WriteTo(FormatOptions, Stream, CancellationToken) |
Write the MimeEntity to the specified output stream.
(Inherited from MimeEntity) | |
WriteTo(FormatOptions, String, CancellationToken) |
Write the MimeEntity to the specified file.
(Inherited from MimeEntity) | |
WriteTo(Stream, Boolean, CancellationToken) |
Write the MimeEntity to the specified output stream.
(Inherited from MimeEntity) | |
WriteTo(String, Boolean, CancellationToken) |
Write the MimeEntity to the specified file.
(Inherited from MimeEntity) | |
WriteTo(FormatOptions, String, Boolean, CancellationToken) |
Write the MimeEntity to the specified file.
(Inherited from MimeEntity) | |
WriteTo(FormatOptions, Stream, Boolean, CancellationToken) |
Write the Multipart to the specified output stream.
(Inherited from Multipart) | |
WriteToAsync(Stream, CancellationToken) |
Asynchronously write the MimeEntity to the specified output stream.
(Inherited from MimeEntity) | |
WriteToAsync(String, CancellationToken) |
Asynchronously write the MimeEntity to the specified file.
(Inherited from MimeEntity) | |
WriteToAsync(FormatOptions, Stream, CancellationToken) |
Asynchronously write the MimeEntity to the specified output stream.
(Inherited from MimeEntity) | |
WriteToAsync(FormatOptions, String, CancellationToken) |
Asynchronously write the MimeEntity to the specified file.
(Inherited from MimeEntity) | |
WriteToAsync(Stream, Boolean, CancellationToken) |
Asynchronously write the MimeEntity to the specified output stream.
(Inherited from MimeEntity) | |
WriteToAsync(String, Boolean, CancellationToken) |
Asynchronously write the MimeEntity to the specified file.
(Inherited from MimeEntity) | |
WriteToAsync(FormatOptions, String, Boolean, CancellationToken) |
Asynchronously write the MimeEntity to the specified file.
(Inherited from MimeEntity) | |
WriteToAsync(FormatOptions, Stream, Boolean, CancellationToken) |
Asynchronously write the Multipart to the specified output stream.
(Inherited from Multipart) |
/// <summary> /// Visits a MimeMessage and generates HTML suitable to be rendered by a browser control. /// </summary> class HtmlPreviewVisitor : MimeVisitor { List<MultipartRelated> stack = new List<MultipartRelated> (); List<MimeEntity> attachments = new List<MimeEntity> (); string body; /// <summary> /// Creates a new HtmlPreviewVisitor. /// </summary> public HtmlPreviewVisitor () { } /// <summary> /// The list of attachments that were in the MimeMessage. /// </summary> public IList<MimeEntity> Attachments { get { return attachments; } } /// <summary> /// The HTML string that can be set on the BrowserControl. /// </summary> public string HtmlBody { get { return body ?? string.Empty; } } protected override void VisitMultipartAlternative (MultipartAlternative alternative) { // walk the multipart/alternative children backwards from greatest level of faithfulness to the least faithful for (int i = alternative.Count - 1; i >= 0 && body == null; i--) alternative[i].Accept (this); } protected override void VisitMultipartRelated (MultipartRelated related) { var root = related.Root; // push this multipart/related onto our stack stack.Add (related); // visit the root document root.Accept (this); // pop this multipart/related off our stack stack.RemoveAt (stack.Count - 1); } // look up the image based on the img src url within our multipart/related stack bool TryGetImage (string url, out MimePart image) { UriKind kind; int index; Uri uri; if (Uri.IsWellFormedUriString (url, UriKind.Absolute)) kind = UriKind.Absolute; else if (Uri.IsWellFormedUriString (url, UriKind.Relative)) kind = UriKind.Relative; else kind = UriKind.RelativeOrAbsolute; try { uri = new Uri (url, kind); } catch { image = null; return false; } for (int i = stack.Count - 1; i >= 0; i--) { if ((index = stack[i].IndexOf (uri)) == -1) continue; image = stack[i][index] as MimePart; return image != null; } image = null; return false; } /// <summary> /// Get a data: URI for the image attachment. /// </summary> /// <remarks> /// Encodes the image attachment into a string suitable for setting as a src= attribute value in /// an img tag. /// </remarks> /// <returns>The data: URI.</returns> /// <param name="image">The image attachment.</param> string GetDataUri (MimePart image) { using (var memory = new MemoryStream ()) { image.Content.DecodeTo (memory); var buffer = memory.GetBuffer (); var length = (int) memory.Length; var base64 = Convert.ToBase64String (buffer, 0, length); return string.Format ("data:{0};base64,{1}", image.ContentType.MimeType, base64); } } // Replaces <img src=...> urls that refer to images embedded within the message with // "file://" urls that the browser control will actually be able to load. void HtmlTagCallback (HtmlTagContext ctx, HtmlWriter htmlWriter) { if (ctx.TagId == HtmlTagId.Meta && !ctx.IsEndTag) { bool isContentType = false; ctx.WriteTag (htmlWriter, false); // replace charsets with "utf-8" since our output will be in utf-8 (and not whatever the original charset was) foreach (var attribute in ctx.Attributes) { if (attribute.Id == HtmlAttributeId.Charset) { htmlWriter.WriteAttributeName (attribute.Name); htmlWriter.WriteAttributeValue ("utf-8"); } else if (isContentType && attribute.Id == HtmlAttributeId.Content) { htmlWriter.WriteAttributeName (attribute.Name); htmlWriter.WriteAttributeValue ("text/html; charset=utf-8"); } else { if (attribute.Id == HtmlAttributeId.HttpEquiv && attribute.Value != null && attribute.Value.Equals ("Content-Type", StringComparison.OrdinalIgnoreCase)) isContentType = true; htmlWriter.WriteAttribute (attribute); } } } else if (ctx.TagId == HtmlTagId.Image && !ctx.IsEndTag && stack.Count > 0) { ctx.WriteTag (htmlWriter, false); // replace the src attribute with a "data:" URL foreach (var attribute in ctx.Attributes) { if (attribute.Id == HtmlAttributeId.Src) { if (!TryGetImage (attribute.Value, out var image)) { htmlWriter.WriteAttribute (attribute); continue; } var dataUri = GetDataUri (image); htmlWriter.WriteAttributeName (attribute.Name); htmlWriter.WriteAttributeValue (dataUri); } else { htmlWriter.WriteAttribute (attribute); } } } else if (ctx.TagId == HtmlTagId.Body && !ctx.IsEndTag) { ctx.WriteTag (htmlWriter, false); // add and/or replace oncontextmenu="return false;" foreach (var attribute in ctx.Attributes) { if (attribute.Name.Equals ("oncontextmenu", StringComparison.OrdinalIgnoreCase)) continue; htmlWriter.WriteAttribute (attribute); } htmlWriter.WriteAttribute ("oncontextmenu", "return false;"); } else { // pass the tag through to the output ctx.WriteTag (htmlWriter, true); } } protected override void VisitTextPart (TextPart entity) { TextConverter converter; if (body != null) { // since we've already found the body, treat this as an attachment attachments.Add (entity); return; } if (entity.IsHtml) { converter = new HtmlToHtml { HtmlTagCallback = HtmlTagCallback }; } else if (entity.IsFlowed) { var flowed = new FlowedToHtml (); string delsp; if (entity.ContentType.Parameters.TryGetValue ("delsp", out delsp)) flowed.DeleteSpace = delsp.Equals ("yes", StringComparison.OrdinalIgnoreCase); converter = flowed; } else { converter = new TextToHtml (); } body = converter.Convert (entity.Text); } protected override void VisitTnefPart (TnefPart entity) { // extract any attachments in the MS-TNEF part attachments.AddRange (entity.ExtractAttachments ()); } protected override void VisitMessagePart (MessagePart entity) { // treat message/rfc822 parts as attachments attachments.Add (entity); } protected override void VisitMimePart (MimePart entity) { // realistically, if we've gotten this far, then we can treat this as an attachment // even if the IsAttachment property is false. attachments.Add (entity); } }