简体   繁体   English

如何使用Mailkit读取电子邮件正文中的嵌入式图像

[英]How to read inline image in email body using Mailkit

I have sent myself a test email which has an image in the body of the email. 我给自己发送了一封测试电子邮件,该电子邮件的正文中有一个图像。 This image is not an attachment, just pasted into the body of the email. 该图像不是附件,只是粘贴到电子邮件正文中。

I am using MailKit to read this incoming email, but cannot find how to access that image. 我正在使用MailKit读取此传入的电子邮件,但找不到如何访问该图像。

I'm using: 我正在使用:

MimeMessage message = client.Inbox.GetMessage(uid);

If I use message.ToString() , I can see that it is there: 如果我使用message.ToString() ,我可以看到它在那里:

...
Content-Disposition: inline; filename="image001.png"; size=4570;
        creation-date="Mon, 16 Sep 2019 09:21:07 GMT";
        modification-date="Mon, 16 Sep 2019 09:21:07 GMT"
Content-ID: <image001.png@01D56A4B.7CD234E0>
Content-Transfer-Encoding: base64

iVBORw0KGgoAAAANSUhEUgAAAJUAAAAlCAY...

And I assume the base64 encoded lines are the actual image, but how do I get at it? 而且我假设base64编码的行是实际的图像,但是如何得到它呢?

EDIT 编辑

Here is my test code: 这是我的测试代码:

    static void Main(string[] args)
    {
        ImapClient client = new ImapClient();
        client.Connect("...
        client.Authenticate("...
        client.Inbox.Open(FolderAccess.ReadWrite);
        IList<UniqueId> uids = client.Inbox.Search(SearchQuery.All);
        foreach (UniqueId uid in uids)
        {
            MimeMessage message = client.Inbox.GetMessage(uid);

            IList<IMessageSummary> info = client.Inbox.Fetch(new[] { uid }, MessageSummaryItems.All);

            foreach (MimeEntity me in message.Attachments)
                HandleMimeEntity(me, 1);
        }
        client.Disconnect(true);
    }

    static void HandleMimeEntity(MimeEntity entity)
    {
        int i, j;

        Multipart multipart = entity as Multipart;

        if (multipart != null)
        {
            Console.WriteLine("multipart");
            for (i = 0; i < multipart.Count; i++)
            {
                Console.WriteLine(i + " - " + multipart[i].ContentType.MimeType + " (" + multipart[i].IsAttachment + ")");
                HandleMimeEntity(multipart[i]);
            }
            return;
        }

        MessagePart rfc822 = entity as MessagePart;

        if (rfc822 != null)
        {
            MimeMessage message = rfc822.Message;
            Console.WriteLine("mimemessage - " + message.Subject);

            HandleMimeEntity(message.Body, lvl + 1);
            return;
        }

        MimePart part = (MimePart)entity;
        Console.WriteLine("mimepart - " + part.FileName);

        // do something with the MimePart, such as save content to disk
    }

I would really, really , really recommend reading the FAQ and/or the README to understand how MIME is structured so that answers to questions like this become obvious, but in the meantime... 我真的, 真的真的建议阅读FAQ和/或README,以了解MIME的结构,以便对此类问题的答案变得显而易见,但与此同时...

Let's start with the understanding that MIME is a tree structure, which means there's a root node (which may or may not be a leaf-node), there can be branch nodes (ex. multipart/mixed , multipart/alternative , multipart/related , etc.) and there are leaf-nodes (ex. text/plain , text/html , image/jpeg , application/octet-stream , etc.). 让我们首先了解MIME是一个树形结构,这意味着有一个根节点(可能是也可能不是叶节点),可能有分支节点(例如multipart/mixedmultipart/alternativemultipart/related等),并且有叶节点(例如text/plaintext/htmlimage/jpegapplication/octet-stream等)。

The root node of the MIME structure is the MimeMessage.Body property. MIME结构的根节点是MimeMessage.Body属性。

If the message contains only a text/plain MIME entity, then the MimeMessage.Body node will be that text/plain MIME entity. 如果消息仅包含text/plain MIME实体,则MimeMessage.Body节点将text/plain MIME实体。

In your case, it sounds like you have at least a text/html entity and an image/png entity. 就您而言,听起来您至少有一个text/html实体和一个image/png实体。

Knowing nothing else about the structure of your message, we can conclude that MimeMessage.Body isn't the text/html entity nor the image/png entity because you can only have 1 root node and text/* and image/* parts are leaf-node entities, not branch node entities. 对消息的结构一无所知,我们可以得出结论, MimeMessage.Body既不是text/html实体也不是image/png实体,因为您只能有1个根节点,并且text/*image/*部分是叶子-节点实体,而不是分支节点实体。

That means that MimeMessage.Body will be a multipart/* which will be represented by the Multipart (or a subclass thereof). 这意味着MimeMessage.Body将是multipart/* ,将由Multipart (或其子类)表示。

Since it's clear that the MimeMessage.Body in your case is a Multipart , we can cast it: 既然您的案例中的MimeMessage.Body很明显是Multipart ,我们可以将其MimeMessage.Body为:

var multipart = (Multipart) message.Body;

Once we have the multipart , we can iterate over its children: 一旦有了multipart ,就可以遍历其子级:

foreach (var child in multipart) {
    // ...
}

At this point we will need to figure out if the child is another Multipart , a MimePart (which will represent text or image data), or an embedded message (aka MessagePart ). 在这一点上,我们需要确定孩子是另一个MultipartMimePart (将代表文本或图像数据)还是嵌入式消息(即MessagePart )。

You can use an as cast to quickly deduce what it is. 您可以使用as强制转换快速推断出它是什么。

And then you just continue walking the tree of MIME entities until you find what you are looking for which will likely require some recursion using the above approach. 然后,您只需继续遍历MIME实体的树,直到找到您要查找的内容为止,使用上述方法可能需要进行一些递归。

MimeKit has a few alternative ways to do this, however: MimeKit有几种替代方法可以执行此操作:

  1. MimeMessage.BodyParts MimeMessage.BodyParts
  2. MimeIterator MimeIterator
  3. and MimeVisitor MimeVisitor

Here's a quick solution to your problem using the BodyParts property: 这是使用BodyParts属性快速解决问题的方法:

var myImage = message.BodyParts.OfType<MimePart> ().FirstOrDefault (x => x.IsMimeType ("image", "png"));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM