Mimekit/mailkit download message body?
Asked Answered
B

1

5

I have been making my own mail client recently and added a receive option, I used mimekit and mailkit as plugins and was able to download most of my mails with a reader that is supposed to show content(right now it shows subject, to, from, date)

The way I downloaded the subject, to, ... is msg.envelope.subject, msg.envelope.to But I cannot download the body like this :( when doing either msg.body, msg.textbody, msg.bodyparts, ... they all result in NOTHING, the place where it should be is just empty, I can't get it downloaded :(

Can anyone help me?

Bootlick answered 11/9, 2015 at 18:26 Comment(0)
F
8

There are 2 ways to get the message body:

1. Download the Whole Message

This method is probably the easiest way.

To do this, all you need to do is call:

var message = folder.GetMessage (uid);

or

var message = folder.GetMessage (index);

I would recommend always using the UniqueId of the message. Since you are already using the Fetch method, all you need to do to make sure that you have the UniqueId of the message is to include the MessageSummaryItems.UniqueId in your fetch request:

var messages = folder.Fetch (0, -1, MessageSummaryItems.UniqueId |
    MessageSummaryItems.Envelope | ...);

Once you have the message, you can do whatever you want with it.

For rendering the message, I would recommend taking a look at the MessageReader sample included in the MimeKit GitHub repository.

It will show you how to properly render a MimeMessage.

2. Download Only What You Need

This method is a bit harder but can be more efficient as far as network bandwidth usage goes.

The first thing you need to do is to make sure to include the MessageSummaryItems.BodyStructure bit flag in the Fetch method. For example:

var messages = folder.Fetch (0, -1, MessageSummaryItems.Envelope | 
    MessageSummaryItems.BodyStructure);

(You'll probably want other fields, but that's just an example to show you how to bitwise-or flags together to request multiple message summary items).

By requesting the BodyStructure of the messages, you'll be able to make use of the msg.Body property.

Each msg.Body will be a BodyPart object which is an abstract class. The 2 main subclasses are BodyPartMultipart and BodyPartBasic. You can use the as cast or the is keyword to figure out which one it is:

var multipart = msg.Body as BodyPartMultipart;

if (multipart != null) {
    // the top-level body part is a multi-part
} else {
    // the body is a basic singleton part
}

This is how you would iterate over the subparts of a BodyPartMultipart:

foreach (var part in multipart.BodyParts) {
    // each part will either be a BodyPartMultipart
    // or a BodyPartBasic, just like before...
}

There are also 2 subclasses of BodyPartBasic which are: BodyPartText and BodyPartMessage. A BodyPartText is a textual-based MIME part (meaning it has a MIME-type of text/*) whereas a BodyPartMessage is an embedded message (and will have a MIME-type of message/rfc822).

Since MIME is recursive, you'll need to implement a recursive function to walk the MIME tree structure to find whatever MIME part you are looking for.

For your convenience, the TextBody and HtmlBody properties on the IMessageSummary interface will locate and return the text/plain and text/html body parts, respectively.

It should be noted, however, that these properties only work in cases where the structure of the message follows the standard convention (notice I said convention, there is no formal standard dictating the location of the message text within a MIME hierarchy).

It should also be noted that if your mail client will be rendering the HTML body, the HTML body part may be part of a group of related MIME parts (i.e. a child of a multipart/related), but the HtmlBody property will not be able to return that and so implementing your own recursive logic will be a better option.

For an example of how to do this, check out the ImapClientDemo sample in the MailKit GitHub repository. The logic currently resides in the MainWindow.cs code.

Fourhanded answered 14/9, 2015 at 0:45 Comment(6)
Thanks but I have one question, on the mimekit documentation it keeps referring to "stream" (e.g. var message = MimeMessage.Load (STREAM);) I have no idea where this is coming from, I tried creating a memory stream but it threw an exception: value cannot be nullBootlick
Well, the Load() method parses a stream... so if you are passing in an empty stream, then it can't parse it, can it? If you are actually writing content into the stream before passing it to the Load() method, make sure to seek back to the beginning of the stream.Fourhanded
BTW, the stream can be from File.OpenRead() or new FileStream() and that's generally what they'll be from.Fourhanded
Is there just a simple sample code which can be reused to download and extract the html and text body parts without downloading the attachments? the MailKit GitHub sample code isn't very intuitiveGrandchild
Read my answer above, it answers your question: For your convenience, the TextBody and HtmlBody properties on the IMessageSummary interface will locate and return the text/plain and text/html body parts, respectively.Fourhanded
Once you have the BodyPart, all you need to do is call one of these GetBodyPart() overloads: mimekit.net/docs/html/…Fourhanded

© 2022 - 2024 — McMap. All rights reserved.