【问题标题】:Unsupported data type when getting mail JPG images获取邮件 JPG 图像时不支持的数据类型
【发布时间】:2020-06-15 16:16:42
【问题描述】:

我正在尝试获取邮件的内联图像,为此我有以下代码:

protected void setCidAttachments(Message message, MensajeEmail mensajeEmail) {

    try {

        MimeMultipart mimeMultipart = (MimeMultipart) message.getDataHandler().getContent();

        for (int k = 0; k < mimeMultipart.getCount(); k++) {

            MimeBodyPart part = (MimeBodyPart) mimeMultipart.getBodyPart(k);
            processPart(part, mensajeEmail);

        }

    }

    catch (Exception e) {
        log.error("Error obtendo adxuntos con cid", e);
    }

}

private void processPart (BodyPart part, MensajeEmail mensajeEmail) throws MessagingException, IOException {

    String type = getContentType(part);
    StringBuilder content = new StringBuilder(mensajeEmail.getContenido());

    if (isImage(type) && part.getDataHandler() != null && part.getDataHandler().getContent() != null) {

        if (part.getDataHandler().getContent() instanceof MimeMultipart) {

            MimeMultipart p = (MimeMultipart) part.getDataHandler().getContent();

            for (int i = 0; i < p.getCount(); i++) {

                BodyPart subpart = p.getBodyPart(i != p.getCount() - 1 ? i + 1 : i);
                processPart(subpart, mensajeEmail);

            }

        } else {

            mensajeEmail.setContenido(getInlineImage(part, content));

        }

    }

}

private String getInlineImage (BodyPart part, StringBuilder content) throws MessagingException, IOException {

    Base64 decoder64 = new Base64();
    ByteArrayOutputStream bos = new ByteArrayOutputStream();

    // Get type

    String type = getContentType(part);

    // Get Content-ID

    String contentId = getContentId(part);

    // Replace

    if (contentId.length() > 0) {

        part.getDataHandler().writeTo(bos);
        int start = content.indexOf("src=\"cid:" + contentId + "\"") + 5;

        if (start > 4) {

            int length = contentId.length() + 4;
            content.replace(start, start + length, "data:" + (isImage(type) ? type : "image/png;") + " base64," + decoder64.encodeToString(bos.toByteArray()));

        }

    }

    bos.close();

    return content.toString();

}

private String getContentId (BodyPart part) throws MessagingException {

    Enumeration headers = part.getAllHeaders();

    while (headers.hasMoreElements()) {

        Header header = (Header)headers.nextElement();

        if (header.getName().equalsIgnoreCase("Content-ID"))
            return cleanContentId(header.getValue());

    }

    return "";

}

private String getContentType (BodyPart part) throws MessagingException {

    return part.getContentType().split(" ")[0];

}

private boolean isImage (String mime) {

    return !mime.equals("text/html;") && !mime.equals("text/plain;");

}

private String cleanContentId (String contentId) {

    if (contentId.charAt(0) == '<') contentId = contentId.substring(1, contentId.length() - 1);
    return contentId;

}

当我发送 PNG 图像时,这非常有效(这让我认为我的代码确实是正确的)。但是,当我尝试发送 JPG 图片时,出现以下异常:

javax.activation.UnsupportedDataTypeException: Unknown image type image/jpeg; name=sony-car-796x418.jpg
at org.apache.geronimo.activation.handlers.AbstractImageHandler.getContent(AbstractImageHandler.java:57)
at javax.activation.DataSourceDataContentHandler.getContent(DataHandler.java:795)
at javax.activation.DataHandler.getContent(DataHandler.java:542)
at es.enxenio.fcpw.plinper.daemons.email.AbstractProtocoloObtencionEmail.processPart(AbstractProtocoloObtencionEmail.java:378)

...

框架真的不能处理 JPG 图像吗?有什么办法可以解决这个问题吗?

编辑:Gmail 甚至不允许我发送 JPG 图像,因此它可能不是一种非常常见的邮件图像格式,这让我认为可能不会被广泛实施,这可能是 Java 似乎没有被广泛实施的原因能够使用它

【问题讨论】:

标签: java email png jpeg unsupporteddatatypeexception


【解决方案1】:

我发现了问题。这一行

if (isImage(type) && part.getDataHandler() != null && part.getDataHandler().getContent()

不应该检查类型是否是图像,而是检查它是否是多部分。否则,我们可以将 jpg 图像作为多部分处理。出于某种原因,png图像不介意这一点,这就是它起作用的原因。以下是代码的更改部分:

protected void setCidAttachments(Message message, MensajeEmail mensajeEmail) {

    try {

        processPart(message, mensajeEmail);

    }

    catch (Exception e) {
        log.error("Error obtendo adxuntos con cid", e);
    }

}

private void processPart(Part part, MensajeEmail mensajeEmail) throws MessagingException, IOException {

    String type = getContentType(part);
    StringBuilder content = new StringBuilder(mensajeEmail.getContenido());

    if (isMultipart(type) && part.getDataHandler() != null && part.getDataHandler().getContent() != null && part.getDataHandler().getContent() instanceof MimeMultipart) {

        MimeMultipart multipart = (MimeMultipart) part.getDataHandler().getContent();

        for (int i = 0; i < multipart.getCount(); i++) {

            BodyPart subpart = multipart.getBodyPart(i);
            processPart(subpart, mensajeEmail);

        }

    } 

    else {

        mensajeEmail.setContenido(getInlineImage(part, content));

    }

}

private boolean isMultipart(String mime) {

    return (Pattern.matches("multipart/.*", mime));

}

【讨论】:

    【解决方案2】:

    我在 eclipse osgi 上使用 java 11 和捆绑包 javax.mail.glassfish 1.4.1 和 javax.activation 1.1.0 运行应用程序时遇到了类似的异常(从 https://eclipse.org/orbit 获得这两个):

    javax.activation.UnsupportedDataTypeException: Unknown image type image/jpeg; name=image001.jpg
      at org.apache.geronimo.activation.handlers.AbstractImageHandler.getContent(AbstractImageHandler.java:57)
      at javax.activation.DataHandler.getContent(DataHandler.java:147)
      at javax.mail.internet.MimeBodyPart.getContent(MimeBodyPart.java:652)
      at my.code.calling.getcontent.MyClass(MyClass.java:802)
    

    org.apache.geronimo.activation.handlers 包包含在 javax.transaction 1.1.0 包中。

    我通过在 javax.activation 包内的 META-INF/mailcap 文件中 # 注释 image/gif、image/jpeg 处理程序解决了这个问题:

    ## <apache license disclaimer> http://www.apache.org/licenses/LICENSE-2.0
    ##
    ## $Rev$ $Date: 2008/04/09 19:25:23 $
    ##
    
    text/plain;;    x-java-content-handler=org.apache.geronimo.activation.handlers.TextPlainHandler
    text/html;;     x-java-content-handler=org.apache.geronimo.activation.handlers.TextHtmlHandler
    text/xml;;      x-java-content-handler=org.apache.geronimo.activation.handlers.TextXmlHandler
    
    #image/gif;;     x-java-content-handler=org.apache.geronimo.activation.handlers.ImageGifHandler
    #image/jpeg;;    x-java-content-handler=org.apache.geronimo.activation.handlers.ImageJpegHandler
    
    multipart/*;;   x-java-content-handler=org.apache.geronimo.activation.handlers.MultipartHandler     
    

    这里没有图像/png,这就是为什么 png 最初不是问题的原因。 因此,通过注释 gif 和 jpeg 处理程序,这些类型的附件现在可以像 png 一样处理:getContent() 将只产生一个 InputStream,而不是一个 AWT 图像,我认为如果一切都按预期工作,那些 geronimo ImageHandlers 会产生它。

    一些内部结构:javax.activation 1.1.0 的 Geronimo AbstractImageHandler 尝试从 javax.mail.glassfish 1.4.1 方法 IMAPBodyPart.getContent() 确定图像的类型,但这会返回 mime 类型,包括。参数,例如“image/jpeg; name=sony-car-796x418.jpg”,无法理解并最终导致 UnsupportedDataTypeException。

    javax.mail.glassfish 也有一个 META-INF/mailcap 文件,它的 image/* 部分有趣地看起来像这样:

    # can't support image types because java.awt.Toolkit doesn't work on servers
    #
    #image/gif;;        x-java-content-handler=com.sun.mail.handlers.image_gif
    #image/jpeg;;       x-java-content-handler=com.sun.mail.handlers.image_jpeg
    

    这可能是一个线索,不过,我仍然在 gui 应用程序中得到了原始 jpeg 异常。

    另一件事,当我使用 java 8 而不是 11 运行相同的设置时,这个错误不会发生,可能与 java 8 有自己的 javax.activation 包有关。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-17
      • 1970-01-01
      • 2012-05-15
      • 2023-01-19
      • 2021-04-05
      • 2011-11-02
      • 1970-01-01
      相关资源
      最近更新 更多