【问题标题】:Java embedding more than 1 image into body of emailJava 将多于 1 个图像嵌入到电子邮件正文中
【发布时间】:2019-02-07 15:04:03
【问题描述】:

大家好,我正在尝试将图像嵌入到我的电子邮件正文中,该图像将在 Outlook 2016 中查看。

我遇到的问题是,如果我希望在邮件正文中嵌入多个图像,那么我该怎么做呢?

我目前正在创建如下所示的正文消息:

我有一些附件给你。 %img

其中 %img每个循环 替换为 图像 cid 名称 ("")

当前有效的代码,但只有 1 个嵌入图像

private static boolean createEmbeddedImg(MimeBodyPart messageBodyPart, Multipart multipart) throws MessagingException, IOException {
        int seq = 0;
        int c = (seq++) % 100000;

        String cid = c + "." + System.currentTimeMillis();

        messageBodyPart.setText(""
                  + "<html>"
                  + " <body>"
                  + "  <p>Here is my image:</p>"
                  + "  <img src=\"cid:" + cid + "\" />"
                  + " </body>"
                  + "</html>" 
                  ,"US-ASCII", "html");
        multipart.addBodyPart(messageBodyPart);

        MimeBodyPart imagePart = new MimeBodyPart();

        try {
            byte[] decodedImg = Base64.getDecoder().decode(B64.getBytes(StandardCharsets.UTF_8));
            Path destinationFile = Paths.get("c:/temp", "homer.gif");
            Files.write(destinationFile, decodedImg);
        } catch (IOException e) {
            e.printStackTrace();
             return false;
        }

        imagePart.attachFile("c:/temp/homer.gif");
        imagePart.setContentID("<" + cid + ">");
        imagePart.setDisposition(MimeBodyPart.INLINE);
        multipart.addBodyPart(imagePart);
        multipart.addBodyPart(messageBodyPart);

        return true;
    }

上面的代码会生成一封带有嵌入图像和正文的电子邮件:

下面的代码是我想出的不仅仅是 1 个嵌入图像在正文中:

private static void _createEmbeddedImgs(MimeBodyPart messageBodyPart, Multipart multipart, String message,
        String[] embeddedImgs) throws MessagingException, IOException {
    UUID uuid = UUID.randomUUID();
    String cid = null;
    List<String> savedCIDS = new ArrayList<String>();

    if (embeddedImgs != null && embeddedImgs.length > 0) {
        for (String filePath : embeddedImgs) {
            cid = String.valueOf(uuid.variant());
            message = message.replaceFirst("%img", "<img src=\"cid:" + cid + "\" />");

            MimeBodyPart imagePart = new MimeBodyPart();

            byte[] decodedImg = Base64.getDecoder().decode(B64.getBytes(StandardCharsets.UTF_8));
            Path destinationFile = Paths.get("c:/temp", cid + ".gif");

            try {
                Files.write(destinationFile, decodedImg);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            imagePart.attachFile("c:/temp/" + cid + ".gif");
            imagePart.setContentID("<" + cid + ">");
            imagePart.setDisposition(MimeBodyPart.INLINE);
            multipart.addBodyPart(imagePart);
            savedCIDS.add(String.valueOf(cid));
        }

        messageBodyPart.setText("<html><body>" + message + "</html></body>", "US-ASCII", "html");
        multipart.addBodyPart(messageBodyPart);
    }
}

这确实会产生一封电子邮件,但看起来像这样:

所以正文中什么都没有,但它确实有嵌入的图像 (2.gif)

我似乎无法掌握我所缺少的东西,以便它也能按我的预期工作。

我可能想多了,但我们将不胜感激!

更新

将 UUID 替换为默认随机序列会产生以下结果:

尊敬的代码已更改:

int seq = 0;
        int c = (seq++) % 100000;

        String cid = c + "." + System.currentTimeMillis();

        if (embeddedImgs != null && embeddedImgs.length > 0) {
            for (String filePath : embeddedImgs) {
                message = message.replaceFirst("%img", "<img src=\"cid:" + cid + "\" />");

【问题讨论】:

  • 这只是一个猜测,但这可能是cid 包含无效字符的问题吗?在您的单图像代码中,您有数字和点,而在多图像代码中,您使用 uuid,其中包含字符和减号(这可能是问题所在)。
  • 顺便说一句,String.valueOf(cid) 是多余的,因为 cid 已经是一个字符串。
  • @Thomas 我更新了我的 OP 以显示您的建议,但它似乎也不起作用。
  • 另一个问题可能是正确解码图像。您是否验证了 gif 是否有效?您发布的代码表明 filePath 包含图像文件的 base64 编码内容,但您不使用它,而是使用 byte[] decodedImg = Base64.getDecoder().decode(B64.getBytes(StandardCharsets.UTF_8));

标签: java image email outlook jakarta-mail


【解决方案1】:

请参阅JavaMail FAQ

您想创建一个多部分/相关消息,其中文本作为第一部分,图像作为后面的部分。

请注意,在将图像数据包含在消息中之前,您无需将其写入文件;有关详细信息,请参阅常见问题解答。

【讨论】:

    【解决方案2】:

    您可以将图像直接插入 HTML

        messageBodyPart.setText(""
                  + "<html>"
                  + " <body>"
                  + "  <p>Here is my image:</p>"
                  + "  <img src=\"data:image/jpg;base64," + Base64.getEncoder().encodeToString(YOUR_IMAGE_DATA) + "\" />"
                  + " </body>"
                  + "</html>" 
                  ,"US-ASCII", "html");
        multipart.addBodyPart(messageBodyPart);
    

    如果您不使用 JPEG,请更改图像的 mimetype。

    【讨论】:

    • 并非所有邮件客户端都支持data:image/jpg 嵌入图像。只有当您知道您的收件人支持时,您才应该这样做。
    • @MarkRotteveel 你是对的。但最受欢迎的是 - 见stackoverflow.com/questions/6070196/…
    • IIRC,最近的 Outlook 版本仍然不支持它(即使 Outlook 2003 支持它,但他们切换到不支持的不同渲染引擎),这涵盖了很大一部分业务。
    猜你喜欢
    • 1970-01-01
    • 2011-07-12
    • 1970-01-01
    • 2014-02-16
    • 2022-09-25
    • 2011-10-30
    • 1970-01-01
    • 2011-10-26
    相关资源
    最近更新 更多