JavaBlog.fr / Java.lu DEVELOPMENT,Java Java : Mail : EML : MSG : Example of mail generation (MSGParser, Apache POI-HSMF)

Java : Mail : EML : MSG : Example of mail generation (MSGParser, Apache POI-HSMF)

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 ArticleMailEmlMsg1;
  • 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:
ArticleMailEmlMsg2


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:
ArticleMailEmlMsg3

ArticleMailEmlMsg4

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:
ArticleMailEmlMsg3

ArticleMailEmlMsg4

/**
 * 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:
ArticleMailEmlMsg5


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

The generated files are:
ArticleMailEmlMsg6

ArticleMailEmlMsg7

ArticleMailEmlMsg8

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

8 thoughts on “Java : Mail : EML : MSG : Example of mail generation (MSGParser, Apache POI-HSMF)”

  1. 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().

    1. HI,

      The source code is available in the post:
      Download: test_mail_msg_eml.zip

      
      	public Msg2txtTest(String fileName) throws IOException {
      		fileNameStem = fileName;
      		if(fileNameStem.endsWith(".msg") || fileNameStem.endsWith(".MSG")) {
      			fileNameStem = fileNameStem.substring(0, fileNameStem.length() - 4);
      		}
      		msg = new MAPIMessage(fileName);
      	}
      	
      	/**
      	 * Processes the message.
      	 * 
      	 * @throws IOException if an exception occurs while writing the message out
      	 */
      	public void processMessage() throws IOException {
      		String txtFileName = fileNameStem + ".txt";
      		String attDirName = fileNameStem + "-att";
      		PrintWriter txtOut = null;
      		try {
      			txtOut = new PrintWriter(txtFileName);
      			try {
      				String displayFrom = msg.getDisplayFrom();
      				txtOut.println("From: "+displayFrom);
      			} catch (ChunkNotFoundException e) {
      				// ignore
      		
      
        1. 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.

  2. 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

Leave a Reply

Your email address will not be published.

Time limit is exhausted. Please reload CAPTCHA.

Related Post

Backup your projectsBackup your projects

Hello again, Here, I expose a simple solution to backup your developments in the remote directory \\YOUR_SERVER_or_EXTERNALDISK\backupWorkspaces\. To do this: – Create file “backup.dat” in your Eclipse workspace ie “R:\java\dev\eclipse_workspaces\default-3.3”: –