使用outlook消息解析器库解析outlook电子邮件



我正试图从远程邮箱的INBOX加载电子邮件,并对其进行解析,以提取HTML格式的附件和转换后的正文。

我使用下面的代码片段来使用outlook消息解析器jar 进行解析

ResultSuccess insertMessage(Message currentMsg) {
final OutlookMessageParser msgp = new OutlookMessageParser();
final OutlookMessage msg = parseMsg(currentMsg.getInputStream());
}

并且当前Msg是类型javax.mail.Message

从服务器获取电子邮件的代码片段如下

Properties props = new Properties();
Message currentMessage;
Session session = Session.getInstance(props, null);
session.setDebug(debug);
store = session.getStore(PROTOCOL);
store.connect(host, username, password);
Message message[] = inboxfolder.getMessages();
Message copyMessage[] = new Message[1];
int n = message.length;
for (int j = 0; j < n; j++) {
currentMessage = message[j];
ResultSuccess result = insertMessage(currentMessage);

异常详细信息如下

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
org.apache.poi.poifs.filesystem.NotOLE2FileException: Invalid header signature; read 0x615F3430305F2D2D, expected 0xE11AB1A1E011CFD0 - Your file appears not to be a valid OLE2 document
at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:151)
at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:117)
at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:285)
at org.simplejavamail.outlookmessageparser.OutlookMessageParser.parseMsg(OutlookMessageParser.java:133)
at com.email.Email_Parse.loadMessages(Email_Parse.java:38)
at com.email.Email_Parse.getMessages(Email_Parse.java:116)
at com.email.Email_Parse.main(Email_Parse.java:26)

然而,当我尝试从本地磁盘加载电子邮件并解析它们时,问题并没有发生。

你知道如何解决这个问题吗?

我想您正在使用outlook消息解析器来解析存储在磁盘上的电子邮件。

从邮件服务器检索到的邮件不是Outlook文件格式(即使远程服务器是Microsoft Exchange服务器或Microsoft的Outlook电子邮件服务),因此Outlook邮件解析器将无法解析这些邮件。

您应该使用JavaMailApi来检索邮件的正文及其附件。

本页介绍了阅读带有附件的邮件所需的步骤(并附有几个示例)。以下是摘录:

问:如何阅读带有附件的消息并保存附件

A: 如上所述,带有附件的消息是在MIME中表示为多部分消息。在简单的情况下Message对象的getContent方法的结果将是MimeMultipart对象。多部分对象的第一个主体部分wil是消息的主要文本。其他身体部位附件。msgshow.java演示程序展示了如何遍历所有消息中的多部分对象,并提取每个身体部位。getDisposition方法将提示您身体部位是应该内联显示还是应该被视为附件(但请注意,并非所有邮件都提供此附件信息)。因此,要将身体部位的内容保存在文件中,请使用MimeBodyPart的saveFile方法。

要将车身零件中的数据保存到文件中(例如),请使用getInputStream方法访问附件内容并复制数据到FileOutputStream。请注意,在复制数据时,您可以不使用可用的方法来确定附件相反,您必须读取数据,直到EOF。saveFileMimeBodyPart的方法将为您完成此操作。但是,你不应该直接使用getFileName方法的结果将文件命名为被保存;这样做可能会导致您无意中覆盖文件,包括系统文件。

请注意,还有更复杂的案件需要处理。例如,一些邮件以纯文本和html。这通常会显示为多部分/备选内容(和MimeMultipart对象)来代替简单的文本正文部分。此外,经过数字签名或加密的消息甚至更多复杂的处理所有这些案件可能具有挑战性。请参阅我们的主页上列出了各种MIME规范和其他资源页

电子邮件并不总是用html格式,有时它们只是纯文本。大多数时候,它们是";多部分";。例如,一封电子邮件可以有一个html部分,它将由支持html的电子邮件客户端(gmail、thunderbird…)显示,另一个纯文本部分可以由其他无法显示html的电子邮件客户使用(想想基于文本的电子邮件客户端)。

因此,在转储电子邮件内容之前,您必须检查其内容类型(或者,如果它有多个部分,请检查这些部分的内容类型)。

对于html部分,根据图像的引用方式,逐字逐句地转储内容可以得到所需的结果。

如果使用http URL(如<img src="https://example.com/a.png"/>)引用图像,则无需进一步的工作来在浏览器中显示结果。

如果使用内容Id URL(如<img src="cid:image002.gif@01D44EB0.904DB790"/>)引用图像,则必须做额外的工作才能在浏览器中正确显示结果。

您必须在电子邮件部分中查找正确的图像,并决定如何将其包含在最终结果中。

例如,将其保存到磁盘,并将html中的引用替换为其在磁盘上的路径,使<img src="cid:image002.gif@01D44EB0.904DB790"/>变成类似于<img src="/path/to/saved/images/imagexyz.png"/>的内容

或者将其转换为base64格式,并用数据URI替换html中的引用,使<img src="cid:image002.gif@01D44EB0.904DB790"/>变成类似于<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="/>的内容。

我不知道是否有一个java库可以自动做到这一点。

JavaMail api网站提供了一些示例,您可以阅读这些示例来了解如何使用它。您可以从示例中查看msgshow.java,了解如何使用该api来检索消息的内容。

这里有一个简单的示例程序,可以将最后一条消息从gmail收件箱下载到本地目录(它可能有错误。别忘了放上你自己的帐户和密码,并在你的计算机上用有效的目录替换"/tmp/messages")。

import javax.mail.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Properties;
public class MessageDownloader {
private File destDir;
public MessageDownloader(File destDir){
this.destDir = destDir;
}
public void download(Part message, String basename) throws MessagingException, IOException {
System.out.println("Type : " + message.getContentType());
if(message.isMimeType("text/plain")) {
downloadTextPart((String) message.getContent(), basename + ".txt");
}else if(message.isMimeType("text/html")) {
downloadTextPart((String) message.getContent(), basename + ".html");
}else if(message.isMimeType("image/*") || Part.ATTACHMENT.equalsIgnoreCase(message.getDisposition())){
downloadDataPart(message, basename);
}else if(message.isMimeType("multipart/*")){
downloadMultiPart((Multipart) message.getContent(), basename);
}else{
System.out.println("Unrecognized type");
}
}
private void downloadDataPart(Part dataPart, String basename) throws IOException, MessagingException {
File dataFile = new File(destDir, basename + "_" + dataPart.getFileName());
Files.copy(dataPart.getInputStream(), dataFile.toPath());
}
private void downloadTextPart(String textContent, String filename) throws MessagingException, IOException{
File textFile = new File(destDir, filename);
Files.writeString(textFile.toPath(), textContent);
}
private void downloadMultiPart(Multipart multiPartMessage, String basename) throws MessagingException, IOException {
for(int partIdx = 0; partIdx < multiPartMessage.getCount(); partIdx++){
BodyPart part = multiPartMessage.getBodyPart(partIdx);
download(part, String.format("%s_%d_", basename, partIdx));
}
}
public static void main(String[] args) throws MessagingException, IOException {
Store store = getStore();
Folder folder = store.getFolder("Inbox");
folder.open(Folder.READ_ONLY);
MessageDownloader msgDownloader = new MessageDownloader(new File("/tmp/messages"));
Message lastMessage = folder.getMessage(folder.getMessageCount()-1);
msgDownloader.download(lastMessage, "last_message");
folder.close();
store.close();
}
private static Store getStore() throws MessagingException {
Properties props = new Properties();
props.setProperty("mail.smtp.ssl.enable", "true");
Session session = Session.getInstance(props, null);
Store store = session.getStore("imaps");
store.connect("imap.gmail.com", "account@gmail.com","password");
return store;
}
}

最新更新