2

我有String一封包含附件的电子邮件。

(全文String约2000行,这里只列出主要部分。)

开始String:_

--_002_0BB5B2121E0AF543BC9F9664030EF5991ADD1C89SWBNTSRV26sorec_
Content-Type: text/html; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

<html xmlns:v=3D"urn:schemas-microsoft-com:vml" xmlns:o=3D"urn:schemas-micr=
osoft-com:office:office" ......

邮件内容的结尾和附件的开头

</div>
</body>
</html>

--_002_0BB5B2121E0AF543BC9F9664030EF5991ADD1C89SWBNTSRV26sorec_
Content-Type: image/jpeg; name="IMAG0205.jpg"
Content-Description: IMAG0205.jpg
...
/9j/4TokRXhpZgAATU0AKgAAAAgACAEPAAIAAABcAAAAbgEQAAIAAABcAAAAy... (base64 file)

所以现在我需要将这个很长的内容解析String为 ajavax.mail.MultiPart或将其保留为 a String,如果邮件没有任何附件。
注意:我没有机会直接收到邮件MultiPart,我只有这个String

这是我到目前为止所拥有的:

/**
 * Return the primary text content of the message.
 */
private boolean textIsHtml = false;

private String getText(Part p) throws MessagingException, IOException {
    if (p.getContent() instanceof ByteArrayInputStream) {
        ByteArrayInputStream stream = (ByteArrayInputStream) p.getContent(); // This ByteArrayInputStream contains the long String mentioned in this question.
        MimeMessage message = new MimeMessage(session, stream); // here I try to create a MimeMessage from that String, but this doesn't work.
        p = message;
    }
    if (p.isMimeType("text/*")) {
        String s = (String) p.getContent();
        textIsHtml = p.isMimeType("text/html");
        return s;
    }

    if (p.isMimeType("multipart/alternative")) {
        // prefer html text over plain text
        Multipart mp = (Multipart) p.getContent();
        String text = null;
        for (int i = 0; i < mp.getCount(); i++) {
            Part bp = mp.getBodyPart(i);
            if (bp.isMimeType("text/plain")) {
                if (text == null) {
                    text = getText(bp);
                }
                continue;
            } else if (bp.isMimeType("text/html")) {
                String s = getText(bp);
                if (s != null) {
                    return s;
                }
            } else {
                return getText(bp);
            }
        }
        return text;
    } else if (p.isMimeType("multipart/*")) {
        Multipart mp = (Multipart) p.getContent();
        for (int i = 0; i < mp.getCount(); i++) {
            String s = getText(mp.getBodyPart(i));
            if (s != null) {
                return s;
            }
        }
    }

    return null;
}

代码示例是来自官方 Oracle FAQ 页面的代码,但稍作修改以将所Object提供的转换getContent()为新的MimeMessage。该代码不起作用,因为创建的MimeMessage具有 mime-typetext/html而不是multipart/*.
因此,在第一个 if 块之后执行这些行时会引发 ClassCastException:

    if (p.isMimeType("text/*")) {
        String s = (String) p.getContent();
        textIsHtml = p.isMimeType("text/html");
        return s;
    }

有没有人对如何在String不编写巨大的解析器的情况下解析有一个聪明的想法?
先感谢您!

4

2 回答 2

1

您的示例字符串不是完整的消息,它似乎只是消息的多部分正文。假设字符串始终是多部分的,您将需要使用带有 DataSource 的 MimeMultipart 构造函数。您需要创建自己的 DataSource 实现,该实现返回一个 InputStream,其中字节来自字符串。您的 DataSource 实现还需要返回一个 ContentType 字符串,其中包含多部分内容的“边界”参数;或者您需要将系统属性“mail.mime.multipart.ignoremissingboundaryparameter”设置为“true”;请参阅javax.mail.internet 包的 javadocs

有了所有这些,您应该能够使用 JavaMail FAQ 中的示例代码。

如果您的字符串并不总是多部分,您将需要访问原始消息中的 Content-Type 标头。没有这个,你就完蛋了。

在这一点上问一个公平的问题,为什么你以一种使处理它变得如此困难的方式得到这个字符串。为什么不保存整个原始 MIME 邮件内容而不仅仅是邮件正文?您是否使用 JavaMail 来提取/保存此字符串?

于 2013-11-08T20:10:29.300 回答
0

javax.mail.internet.MimeMessage如果您有一些可以解析为MimeMessageParser.

然后,您可以编写一个这样的辅助方法:

private String extractContentFromMail(String rawMessage) throws Exception {
    Session session = Session.getDefaultInstance(new Properties());
    MimeMessage msg = new MimeMessage(session, new ByteArrayInputStream(rawMessage.getBytes()));

    MimeMessageParser parser = new MimeMessageParser(msg);
    parser.parse();
    if (parser.hasHtmlContent()) {
        log.debug("extracted mail with HTML content.");
        return parser.getHtmlContent();
    } else {
        log.debug("extracted mail with plaintext content.");
        return parser.getPlainContent();
    }
}
于 2019-08-28T13:48:50.690 回答