【问题标题】:How to read inline image in email body using Mailkit如何使用 Mailkit 读取电子邮件正文中的内联图像
【发布时间】:2019-09-16 21:35:40
【问题描述】:

我给自己发了一封测试邮件,邮件正文中有一张图片。此图片不是附件,只是粘贴到电子邮件正文中。

我正在使用 MailKit 阅读这封传入的电子邮件,但找不到如何访问该图像。

我正在使用:

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

如果我使用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...

我假设 base64 编码的行是实际的图像,但我该如何理解呢?

编辑

这是我的测试代码:

    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
    }

【问题讨论】:

  • 你在message.Body得到了什么?
  • 我会说在html中搜索标签“img”并读取他的值,然后转换为base64或者如果是链接下载图像
  • 我希望有比自己解析原始电子邮件正文更简单的方法(这就是我选择 MailKit 的原因)。也许我会看看那里还有什么。
  • 为什么需要自己解析邮件正文?你没有任何意义...... MailKit 已经为你解析了它。
  • 这就是我所希望的。我只需要知道如何获取这个内联图像。有一个 htmlbody 属性,但它只包含一个指向文件名的 img 标签,但我如何获得实际的“文件”。它不是附件,所以不在message.Attachments 中。我还必须解析 img 标签才能找到文件名,但我可以忍受。

标签: c# mailkit


【解决方案1】:

我真的,真的真的建议阅读 FAQ 和/或 README 以了解 MIME 的结构这样这样的问题的答案就变得显而易见了,但与此同时......

首先让我们了解 MIME 是一个树结构,这意味着有一个根节点(可能是也可能不是叶节点),可能有分支节点(例如multipart/mixedmultipart/alternativemultipart/related 等)并且有叶节点(例如text/plaintext/htmlimage/jpegapplication/octet-stream 等)。

MIME 结构的根节点是MimeMessage.Body 属性。

如果消息仅包含text/plain MIME 实体,则MimeMessage.Body 节点将成为text/plain MIME 实体。

在您的情况下,听起来您至少有一个 text/html 实体和一个 image/png 实体。

对您的消息结构一无所知,我们可以得出结论,MimeMessage.Body 既不是text/html 实体也不是image/png 实体,因为您只能有1 个根节点和text/*image/*部分是叶节点实体,而不是分支节点实体。

这意味着MimeMessage.Body 将是一个multipart/*,它将由Multipart(或其子类)表示。

因为很明显你的MimeMessage.BodyMultipart,我们可以转换它:

var multipart = (Multipart) message.Body;

一旦我们有了multipart,我们就可以迭代它的孩子:

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

此时我们需要确定孩子是另一个MultipartMimePart(将表示文本或图像数据)还是嵌入消息(又名MessagePart)。

您可以使用as 转换来快速推断它是什么。

然后您只需继续遍历 MIME 实体树,直到找到您要查找的内容,这可能需要使用上述方法进行一些递归。

但是,MimeKit 有几种替代方法可以做到这一点:

  1. MimeMessage.BodyParts
  2. MimeIterator
  3. MimeVisitor

下面是使用 BodyParts 属性的快速解决方案:

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

【讨论】:

  • 是的,已经阅读了这些位。您解决我问题的一点答案是The root node of the MIME structure is the MimeMessage.Body property. 这就是我需要的一点,所以谢谢你。它被称为Body 的事实让我大吃一惊。
  • FWIW、TextBody 和 HtmlBody 是方便的属性,可扫描树以查找最有可能代表消息正文的文本部分
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-26
  • 1970-01-01
  • 2020-09-21
  • 2016-07-10
  • 2023-03-18
  • 1970-01-01
  • 2013-11-18
相关资源
最近更新 更多