我有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
有明智的想法?
提前谢谢!
答案 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();
}
}