MIME is a tree structure of parts. There are multiparts which contain other parts (even other multiparts). There are message parts which contain messages. And there are leaf-node parts which contain content.
There are a few common message structures:
-
The message contains only a
text/plain
ortext/html
part (easy, just use that). -
The message contains a
multipart/alternative
which will typically look a bit like this:multipart/alternative text/plain text/html
-
Same as above, but the html part is inside a
multipart/related
so that it can embed images:multipart/alternative text/plain multipart/related text/html image/jpeg image/png
-
The message contains a textual body part as well as some attachments:
multipart/mixed text/plain or text/html application/octet-stream application/zip
-
the same as above, but with the first part replaced with either #2 or #3. To illustrate:
multipart/mixed multipart/alternative text/plain text/html application/octet-stream application/zip
or...
multipart/mixed multipart/alternative text/plain multipart/related text/html image/jpeg image/png application/octet-stream application/zip
Now, if you don't care about any of that and just want to get the text of the first text/plain
or
text/html
part you can find, that's easy.
Just look for a node that is of type TextPart
and then get the Text
property value.
For example, using LINQ, you could do this:
var body = message.BodyParts.OfType<TextPart> ().FirstOrDefault ();
Now that you've got the body, you can just use body.Text
.
Some PGP-enabled mail clients, such as Thunderbird, embed encrypted PGP blurbs within the text/plain body of the message rather than using the PGP/MIME format that MimeKit prefers.
These messages often look something like this:
Return-Path: <[email protected]>
Received: from [127.0.0.1] (hostname.example.com. [201.95.8.17])
by mx.google.com with ESMTPSA id l67sm26628445yha.8.2014.04.27.13.49.44
for <[email protected]>
(version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128);
Sun, 27 Apr 2014 13:49:44 -0700 (PDT)
Message-ID: <[email protected]>
Date: Sun, 27 Apr 2014 17:49:43 -0300
From: Die-Hard PGP Fan <[email protected]>
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:24.0) Gecko/20100101 Thunderbird/24.4.0
MIME-Version: 1.0
To: undisclosed-recipients:;
Subject: Test of inline encrypted PGP blocks
X-Enigmail-Version: 1.6
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
X-Antivirus: avast! (VPS 140427-1, 27/04/2014), Outbound message
X-Antivirus-Status: Clean
-----BEGIN PGP MESSAGE-----
Charset: ISO-8859-1
Version: GnuPG v2.0.22 (MingW32)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/
SGFoISBJIGZvb2xlZCB5b3UsIHRoaXMgdGV4dCBpc24ndCBhY3R1YWxseSBlbmNy
eXB0ZWQgd2l0aCBQR1AsCml0J3MgYWN0dWFsbHkgb25seSBiYXNlNjQgZW5jb2Rl
ZCEKCkknbSBqdXN0IHVzaW5nIHRoaXMgYXMgYW4gZXhhbXBsZSwgdGhvdWdoLCBz
byBpdCBkb2Vzbid0IHJlYWxseSBtYXR0ZXIuCgpGb3IgdGhlIHNha2Ugb2YgYXJn
dW1lbnQsIHdlJ2xsIHByZXRlbmQgdGhhdCB0aGlzIGlzIGFjdHVhbGx5IGFuIGVu
Y3J5cHRlZApibHVyYi4gTW1ta2F5PyBUaGFua3MuCg==
-----END PGP MESSAGE-----
To deal with these kinds of messages, I've added a method to OpenPgpContext called GetDecryptedStream
which
can be used to get the raw decrypted stream.
There are actually 2 variants of this methods:
public Stream GetDecryptedStream (Stream encryptedData, out DigitalSignatureCollection signatures)
and
public Stream GetDecryptedStream (Stream encryptedData)
The first variant is useful in cases where the encrypted PGP blurb is also digitally signed, allowing you to get your hands on the list of digitial signatures in order for you to verify each of them.
To decrypt the content of the message, you'll want to locate the TextPart
(in this case, it'll just be message.Body
)
and then do this:
static Stream DecryptEmbeddedPgp (TextPart text)
{
using (var memory = new MemoryStream ()) {
text.ContentObject.DecodeTo (memory);
memory.Position = 0;
using (var ctx = new MyGnuPGContext ()) {
return ctx.GetDecryptedStream (memory);
}
}
}
What you do with that decrypted stream is up to you. It's up to you to figure out what the decrypted content is (is it text? a jpeg image? a video?) and how to display it to the user.