Java Mail:从String创建消息

时间:2013-11-08 14:59:54

标签: java javamail

我有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解析为javax.mail.MultiPart,或者如果邮件没有任何附件,则将其保留为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;
}

代码示例是来自the official Oracle FAQ page的代码,但稍作修改后,将Object提供的getContent()转换为新的MimeMessage。代码不起作用,因为创建的MimeMessage具有mime-type text/html而不是multipart/*
因此在第一个if-block之后执行这些行时抛出ClassCastException:

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

有没有人对如何在不编写大量解析器的情况下解析String有明智的想法? 提前谢谢!

2 个答案:

答案 0 :(得分:0)

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

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

如果您的字符串不总是多部分,则需要访问原始邮件中的Content-Type标头。没有它,你几乎搞砸了。

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

答案 1 :(得分:0)

如果您可以将某些内容解析为javax.mail.internet.MimeMessage,则最好使用Apache commons-email,它具有非常方便的MimeMessageParser实用程序类,可用于提取正文来自HTML MIME部分或纯文本部分的文本。

然后您可以编写这样的帮助方法:

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();
    }
}