Hello,
I would expose you a simple need: generate a mail file on server side and return it to client side in order to open the client’s email software like Outlook. So, we must on server side:
- generate a prefilled mail file with an attachment like PDF file,
- send this mail file to the client browser,
At first, it seems simple: we have already create and send an email with the javax.mail java package and it is possible to print an link in a HTML page with mailto tag. However, the generation of mail file is not similar to the above points which don’t response our requirements (attachement file and opening of client mail software).
Investigations
Since opening in October 2007, the spécifications of “msg” format by Microsoft, various libraries have appeared on the market:
- the opensource library of Apache POI-HSMF which is the POI Project’s pure Java implementation of the Outlook MSG format,
- the opensource Library MSGparser which is a small open source Java library that parses Outlook .msg files and provides their content using Java objects. MSGparser uses the Apache POI – POIFS Library,
… however, these opensource libraries allow the parsing of “msg” files but don’t allow the creation ou the updating of “msg” files.
Of course, there are paying libraries allowing the creation or the updating of “msg” files:
- JMSG IndependentSoft.com which is Microsoft Outlook .msg file API for Java. The API allows you to easy create/read/parse/convert Outlook .msg files and more. The API does not require Microsoft Outlook to be installed on the machine or any other third party application or library in order to work.
- Aspose.Email for Java which is a Java component for reading and writing Microsoft Outlook MSG files without using Outlook. It can create and update MSG files, and retrieve properties such as subject, body, recipients, attachments, sender information, MAPI properties. It can be used with Web or desktop applications.
There is also the possibility to use the web services exposed by the SMTP server (like Exchange ) in order to create “msg” file, nevertheless, the implementation of this solution is cumbersome because it is necessary to create a technical account in SMTP server, make secure the exposed services, develope the calls of WS on server side.
Finally, a simple solution appeared us : use open “eml” format instead of “msg” format.
What is EML?
EML is a file extension for an e-mail message saved to a file in the MIME RFC 822 standard format by Microsoft Outlook Express as well as some other email programs. So, EML format is very simple and very standard, these files contain plain ASCII text for the headers and the main message body as well as hyperlinks and attachments.
More, the creation of “eml” files is possible without external libraries via standard java packages (java mail, java activation). However, the “eml” files can’t be created in DRAFT mode, so in our case, the server side will return to client a mail file in ready only mode, which could be forwarded by the user on client side.
Examples
We need a JAVA project named “test_mail_msg_eml” with:
- lib: contains the libraries poi-3.10-FINAL.jar, poi-scratchpad-3.10-FINAL.jar, msgparser-1.12.jar, junit-4.1.jar, log4j-1.2.15.jar and mail-1.3.2.jar. Add these libraries to the classpath of current project like in ;
- src: contains the source codes of our tests;
- etc: contains the data file used in the test cases;
This project will contain several classes:
- MsgParserTest: which parses “msg” files via the opensource library MSGParser;
- Msg2txtTest: which parses “msg” files via the opensource library Apache POI-HSMF;
- EMLGenerateTest: which generates “eml” files with the standard java packages;
…the structure of our project will be:
MsgParserTest
This class parses 2 files “Test_parsing_mail_without_attach.msg” and “Test_parsing_mail_with_attach.msg” in the folder “etc\msgparser” and prints the results in the console:
public class MsgParserTest extends TestCase { private static final Logger LOG = Logger.getLogger(MsgParserTest.class); public void testParsing() { try { MsgParser msgp = new MsgParser(); Message msg = null; // Message without attach { String fileName = "C:\\MyFiles\\Development\\Java\\dev\\test_mail_msg_eml\\etc\\msgparser\\Test_parsing_mail_without_attach.msg"; LOG.info(fileName); File testFile = new File(fileName); msg = msgp.parseMsg(testFile); System.out.println("---------------------------------------"); System.out.println("Parsed message:\n"+msg.toString()); } // Message with attach { String fileName = "C:\\MyFiles\\Development\\Java\\dev\\test_mail_msg_eml\\etc\\msgparser\\Test_parsing_mail_with_attach.msg"; LOG.info(fileName); File testFile = new File(fileName); msg = msgp.parseMsg(testFile); System.out.println("---------------------------------------"); System.out.println("Parsed message:\n"+msg.toString()); } } catch(Exception e) { e.printStackTrace(); fail(e.getMessage()); } }
The outputs will be:
--------------------------------------- Parsed message: From: null To: huseyin.ozveren@java.lu Subject: Test parsing mail without attach 0 attachments. --------------------------------------- Parsed message: From: null To: huseyin.ozveren@java.lu Subject: Test parsing mail with attach 1 attachments.
Msg2txtTest
This class parses the above 2 same files “Test_parsing_mail_without_attach.msg” and “Test_parsing_mail_with_attach.msg” in the folder “etc\msgparser”, saves the result into text files and the attachments files into a folder:
/** * Reads one or several Outlook MSG files and for each of them creates * a text file from available chunks and a directory that contains * attachments. * * @author Apache * */ public class Msg2txtTest{ //.... //.... //.... //.... //.... /** * Processes the Outlook MSG files. */ public static void main(String[] args) { // Message without attach { String fileName = "C:\\MyFiles\\Development\\Java\\dev\\test_mail_msg_eml\\etc\\msg2text\\Test_parsing_mail_without_attach.msg"; LOG.info(fileName); try { Msg2txtTest processor = new Msg2txtTest(fileName); processor.processMessage(); } catch (IOException e) { System.err.println("Could not process "+fileName+": "+e); } } // Message with attach { String fileName = "C:\\MyFiles\\Development\\Java\\dev\\test_mail_msg_eml\\etc\\msg2text\\Test_parsing_mail_with_attach.msg"; LOG.info(fileName); try { Msg2txtTest processor = new Msg2txtTest(fileName); processor.processMessage(); } catch (IOException e) { System.err.println("Could not process "+fileName+": "+e); } } } }
The outputs are:
log4j:WARN No appenders could be found for logger (com.ho.test.mail.apache.poi.outlook.Msg2txtTest). log4j:WARN Please initialize the log4j system properly. Generation of txt file:C:\MyFiles\Development\Java\dev\test_mail_msg_eml\etc\msg2text\Test_parsing_mail_without_attach.txt Generation of attachments files into the directory:C:\MyFiles\Development\Java\dev\test_mail_msg_eml\etc\msg2text\Test_parsing_mail_without_attach-att Generation of txt file:C:\MyFiles\Development\Java\dev\test_mail_msg_eml\etc\msg2text\Test_parsing_mail_with_attach.txt Generation of attachments files into the directory:C:\MyFiles\Development\Java\dev\test_mail_msg_eml\etc\msg2text\Test_parsing_mail_with_attach-att
…the txt files
Test_parsing_mail_without_attach.txt:
To: huseyin.ozveren@java.lu CC: BCC: Subject: Test parsing mail without attach Test parsing mail without attach 1 2 3 4 .. Test parsing mail without attach
Test_parsing_mail_with_attach.txt:
To: huseyin.ozveren@java.lu CC: BCC: Subject: Test parsing mail with attach Test parsing mail with attach 1 2 3 4 .. Test parsing mail with attach
…and extracted attachements files in the folder Test_parsing_mail_with_attach-att:
EMLGenerateTest
This class generates 2 files “testGeneratedEML.eml” and “testGeneratedEML2.eml” in the folder “etc\eml”:
/** * Test of EML file generation * @author huseyin * */ public class EMLGenerateTest extends TestCase { //.... //.... //.... //.... //.... public void testGenerating() { // EML test generation { String from = "contact@javablog.fr"; String to = "huon@java.lu"; String subject = "my subject"; String body = "this the body of the message \n\n\nMail generated by JAVA"; // List<File> attachments = new ArrayList<File>(); attachments.add(new File("C:\\MyFiles\\Development\\Java\\dev\\test_mail_msg_eml\\etc\\eml\\attachPDF.pdf")); // String outputEmlPath = "C:\\MyFiles\\Development\\Java\\dev\\test_mail_msg_eml\\etc\\eml\\testGeneratedEML.eml"; // createMessage(from, to, subject, body, attachments, outputEmlPath); // System.out.println("----------------------------------"); System.out.println("Eml file generated message:" + outputEmlPath); } // EML test generation { String from = null; String to = null; String subject = "my subject"; String body = "this the body of the message \n\n\nMail generated by JAVA"; // List<File> attachments = new ArrayList<File>(); attachments.add(new File("C:\\MyFiles\\Development\\Java\\dev\\test_mail_msg_eml\\etc\\eml\\attachPDF.pdf")); // String outputEmlPath = "C:\\MyFiles\\Development\\Java\\dev\\test_mail_msg_eml\\etc\\eml\\testGeneratedEML2.eml"; // createMessage(from, to, subject, body, attachments, outputEmlPath); // System.out.println("----------------------------------"); System.out.println("Eml file generated message:" + outputEmlPath); } } }
The outputs will be:
---------------------------------- Eml file generated message:C:\MyFiles\Development\Java\dev\test_mail_msg_eml\etc\eml\testGeneratedEML.eml ---------------------------------- Eml file generated message:C:\MyFiles\Development\Java\dev\test_mail_msg_eml\etc\eml\testGeneratedEML2.eml
More, following an example of servlet/remote service (Spring WEB service) which sends to client a binary content like pdf or eml file.
Here, we use the class “org.apache.commons.io.FileUtils” from “commons-io-2.3.jar” in order to avoid reading the full content of file
and serving many parallel requests will quickly consume memory.
@Override public void handleRequest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ // Write the stream to the client browser ServletOutputStream op = resp.getOutputStream(); String fileName = "test.eml"; String fullFileNamePath = "../../folder1/folder2/myEmlFile.eml"; resp.setContentType("application/vnd.ms-outlook"); resp.setCharacterEncoding("UTF-8"); resp.setHeader("Content-disposition", "attachment;filename="+fileName); File fileIn = new File(fullFileNamePath); // In order to avoid reading the full content of file and serving many parallel requests will quickly consume memory. //op.write(FileUtils.readFileToByteArray(fileIn)); // FileUtils has methods for this. FileUtils.copyFile(fileIn, op); }
That’s all!!!
Download: test_mail_msg_eml.zip
Best regards,
Huseyin OZVEREN
Thanks, but here processMessage() method of Msg2txtTest class is not defined.
Also there is no constructor with parameter is defined which is used in this class.
please provide the coding for the constructor and the processMessage().
HI,
The source code is available in the post:
Download: test_mail_msg_eml.zip
Thanks.. but when I run this one, it gives an “empty” txt file(not pdf file)…
Hi,
I am sorry, but this classe Msg2txtTest generates 2 files and 1 folder with the attached pdf file.
inputs:
– Test_parsing_mail_with_attach.msg
– Test_parsing_mail_without_attach.msg
ouputs:
– Test_parsing_mail_with_attach-att/attachPDF.pdf
– Test_parsing_mail_with_attach.txt
– Test_parsing_mail_without_attach.txt
http://www.javablog.fr/wp-content/uploads/2014/04/ArticleMailEmlMsg5.png
Best regards,
Ok.. Actually I want the mail body to be saved as a PDF. How Can it be done?
The goal of this article is not the presentation of the PDF files’ generation … 🙂
The class Msg2txtTest parses the MSG files, saves their body into text files and extracts their attachments files into a folder.
Once the body of MSG files extracted you could save/transform it to PDF document by using XSL-FO with FOP, PDFBOX (java) …etc.
Hi,
When I run I am getting the invalid header signature…I can confirm the libraries I am using are same as the one you have it here….
log4j:WARN No appenders could be found for logger (msgparser.msgparsertest).
log4j:WARN Please initialize the log4j system properly.
Could not process C:\temp\Java Mail\Tadeb91b5f00acbcb0a610.MSG: java.io.IOException: Invalid header signature; read 0x6465766965636552, expected 0xE11AB1A1E011CFD0 – Your file appears not to be a valid OLE2 document
Could not process C:\temp\Java Mail\Tac44a9b9900a6b6b155bc.MSG: java.io.IOException: Invalid header signature; read 0x6465766965636552, expected 0xE11AB1A1E011CFD0 – Your file appears not to be a valid OLE2 document
Please advise
Thanks
Hi,
See the post http://stackoverflow.com/questions/27956535/apache-poi-file-getting-corrupted-and-unable-to-write-to-existing-workbook
Kind regards,