ITextPart Interface

An interface for a textual MIME part.

Definition

Namespace: MimeKit
Assembly: MimeKit.Core (in MimeKit.Core.dll) Version: 5.0.0
C#
public interface ITextPart : IMimePart, 
	IMimeEntity, IDisposable
Implements
IMimeEntity, IMimePart, IDisposable

Remarks

Unless overridden, all textual parts parsed by the IMimeParser, such as text/plain or text/html, will be represented by a TextPart.

For more information about text media types, see section 4.1 of rfc2046.

Example

C#
                    /// <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 {
            // 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
        using (var tnef = entity.LoadTnefMessage ()) {
            // the converted message (and its attachments) outlives the TnefMessage
            var result = tnef.ConvertToMime ();

            attachments.AddRange (result.Message.Attachments);
        }
    }

    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);
    }
}
                  

Properties

Content Get or set the MIME content.
(Inherited from IMimePart)
ContentBase Get or set the base content URI.
(Inherited from IMimeEntity)
ContentDescription Get or set the description of the content if available.
(Inherited from IMimePart)
ContentDisposition Get or set the content disposition.
(Inherited from IMimeEntity)
ContentDuration Get or set the duration of the content if available.
(Inherited from IMimePart)
ContentId Get or set the Content-Id.
(Inherited from IMimeEntity)
ContentLocation Get or set the content location.
(Inherited from IMimeEntity)
ContentMd5 Get or set the md5sum of the content.
(Inherited from IMimePart)
ContentTransferEncoding Get or set the content transfer encoding.
(Inherited from IMimePart)
ContentType Get the type of the content.
(Inherited from IMimeEntity)
FileName Get or set the name of the file.
(Inherited from IMimePart)
Format Get the text format of the content.
Headers Get the list of headers.
(Inherited from IMimeEntity)
IsAttachment Get a value indicating whether this entity is an attachment.
(Inherited from IMimeEntity)
IsEnriched Get whether this text part contains enriched text.
IsFlowed Get whether this text part contains flowed text.
IsHtml Get whether this text part contains HTML.
IsPlain Get whether this text part contains plain text.
IsRichText Get whether this text part contains RTF.
Text Get the decoded text content.

Methods

Accept Dispatches to the specific visit method for this MIME entity.
(Inherited from IMimeEntity)
ComputeContentMd5 Compute the MD5 checksum of the content.
(Inherited from IMimePart)
Dispose Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
(Inherited from IDisposable)
GetBestEncoding(EncodingConstraint, CancellationToken) Calculate the most efficient content encoding given the specified constraint.
(Inherited from IMimePart)
GetBestEncoding(EncodingConstraint, Int32, CancellationToken) Calculate the most efficient content encoding given the specified constraint.
(Inherited from IMimePart)
GetText(Encoding) Get the decoded text content using the provided charset encoding to override the charset specified in the Content-Type parameters.
GetText(Encoding) Get the decoded text and the encoding used to convert it into unicode.
GetText(String) Get the decoded text content using the provided charset to override the charset specified in the Content-Type parameters.
Prepare Prepare the MIME entity for transport using the specified encoding constraints.
(Inherited from IMimeEntity)
SetText(Encoding, String) Set the text content and the charset parameter in the Content-Type header.
SetText(String, String) Set the text content and the charset parameter in the Content-Type header.
TryDetectEncoding Try to detect the encoding of the text content.
VerifyContentMd5 Verify the Content-Md5 value against an independently computed md5sum.
(Inherited from IMimePart)
WriteTo(Stream, CancellationToken) Write the IMimeEntity to the specified output stream.
(Inherited from IMimeEntity)
WriteTo(String, CancellationToken) Write the IMimeEntity to the specified file.
(Inherited from IMimeEntity)
WriteTo(FormatOptions, Stream, CancellationToken) Write the IMimeEntity to the specified output stream.
(Inherited from IMimeEntity)
WriteTo(FormatOptions, String, CancellationToken) Write the IMimeEntity to the specified file.
(Inherited from IMimeEntity)
WriteTo(Stream, Boolean, CancellationToken) Write the IMimeEntity to the specified output stream.
(Inherited from IMimeEntity)
WriteTo(String, Boolean, CancellationToken) Write the IMimeEntity to the specified file.
(Inherited from IMimeEntity)
WriteTo(FormatOptions, Stream, Boolean, CancellationToken) Write the IMimeEntity to the specified output stream.
(Inherited from IMimeEntity)
WriteTo(FormatOptions, String, Boolean, CancellationToken) Write the IMimeEntity to the specified file.
(Inherited from IMimeEntity)
WriteToAsync(Stream, CancellationToken) Asynchronously write the IMimeEntity to the specified output stream.
(Inherited from IMimeEntity)
WriteToAsync(String, CancellationToken) Asynchronously write the IMimeEntity to the specified file.
(Inherited from IMimeEntity)
WriteToAsync(FormatOptions, Stream, CancellationToken) Asynchronously write the IMimeEntity to the specified output stream.
(Inherited from IMimeEntity)
WriteToAsync(FormatOptions, String, CancellationToken) Asynchronously write the IMimeEntity to the specified file.
(Inherited from IMimeEntity)
WriteToAsync(Stream, Boolean, CancellationToken) Asynchronously write the IMimeEntity to the specified output stream.
(Inherited from IMimeEntity)
WriteToAsync(String, Boolean, CancellationToken) Asynchronously write the IMimeEntity to the specified file.
(Inherited from IMimeEntity)
WriteToAsync(FormatOptions, Stream, Boolean, CancellationToken) Asynchronously write the IMimeEntity to the specified output stream.
(Inherited from IMimeEntity)
WriteToAsync(FormatOptions, String, Boolean, CancellationToken) Asynchronously write the IMimeEntity to the specified file.
(Inherited from IMimeEntity)

See Also

Reference