How to create an in-memory PDF report and send as an email attachment using iText and Java

02Nov10

In this blog entry, I will show with a few lines of code how to create an in-memory PDF report and send it as an email attachment. Why is this exercise or illustration important? It is important to me because I’m involved in a lot of report generation projects where the reporting logic and display center around PDFs, and due to server constraints (i.e. space), it is not desirable to store these PDF reports as files; the goal is to generate PDF reports on the fly and send them off to the client. Furthermore, I found a lot of search results from the major search engines that discussed the same issue, but no clear example was given in Java. Two such discussions are below.

On the other hand, a full example in C# was also discovered here http://stackoverflow.com/questions/1196059/itextsharp-sending-in-memory-pdf-in-an-email-attachment.

What you will need to get the code to compile and execute are the following two jar files.

The code to create an in-memory PDF report and send it as an email attachment is below. To get this code to run properly, you’ll have to replace some of the variable values (i.e. email server host, email server port, sender address, recipient address, etc…), and these variables are noted with comments. As you can see from the code, I constructed the objects in a bottom-up approach—from MimeBodyPart, to MimeMultiPart, to MimeMessage. There are two MimeBodyPart objects, one for the text of the email and one for the PDF attachment of the email. The text MimeBodyPart is simple to understand; instantiate an instance and set its text. The PDF MimeBodyPart is a bit more involved. First, we have to instantiate a ByteArrayOutputStream object which will hold the PDF file in binary form. We then pass this ByteArrayOutputStream to the writePdf(OutputStream) method, where we use the iText API to construct a PDF report (in this case, the report is just a simple hello). Once the data is written to the ByteArrayOutputStream, we get its byte array (byte[]) and use it it instantiate a ByteArrayDataSource. We then set the DataHandler and file name of the PDF MimeBodyPart. A MimeMultiPart is instantiated and the two MimeBodyPart objects are added. Lastly, a MimeMessage is created and sent off.

/**
 * Copyright 2010 Jee Vang 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 *  http://www.apache.org/licenses/LICENSE-2.0 
 *  
 *  Unless required by applicable law or agreed to in writing, software 
 *  distributed under the License is distributed on an "AS IS" BASIS, 
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 *  See the License for the specific language governing permissions and 
 *  limitations under the License. 
 */
package demo;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.util.ByteArrayDataSource;

import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;

/**
 * Email with PDF example.
 * <br><br>
 * Email sending code adapted from http://www.java-tips.org/other-api-tips/javamail/how-to-send-an-email-with-a-file-attachment.html.
 * @author Jee Vang
 *
 */
public class EmailWithPdf {
	
	/**
	 * Sends an email with a PDF attachment.
	 */
	public void email() {
		String smtpHost = "yourhost.com"; //replace this with a valid host
		int smtpPort = 587; //replace this with a valid port
				
		String sender = "sender@yourhost.com"; //replace this with a valid sender email address
		String recipient = "recipient@anotherhost.com"; //replace this with a valid recipient email address
		String content = "dummy content"; //this will be the text of the email
		String subject = "dummy subject"; //this will be the subject of the email
		
		Properties properties = new Properties();
		properties.put("mail.smtp.host", smtpHost);
		properties.put("mail.smtp.port", smtpPort);		
		Session session = Session.getDefaultInstance(properties, null);
		
		ByteArrayOutputStream outputStream = null;
		
		try {			
			//construct the text body part
			MimeBodyPart textBodyPart = new MimeBodyPart();
			textBodyPart.setText(content);
			
			//now write the PDF content to the output stream
			outputStream = new ByteArrayOutputStream();
			writePdf(outputStream);
			byte[] bytes = outputStream.toByteArray();
			
			//construct the pdf body part
			DataSource dataSource = new ByteArrayDataSource(bytes, "application/pdf");
			MimeBodyPart pdfBodyPart = new MimeBodyPart();
			pdfBodyPart.setDataHandler(new DataHandler(dataSource));
			pdfBodyPart.setFileName("test.pdf");
						
			//construct the mime multi part
			MimeMultipart mimeMultipart = new MimeMultipart();
			mimeMultipart.addBodyPart(textBodyPart);
			mimeMultipart.addBodyPart(pdfBodyPart);
			
			//create the sender/recipient addresses
			InternetAddress iaSender = new InternetAddress(sender);
			InternetAddress iaRecipient = new InternetAddress(recipient);
			
			//construct the mime message
			MimeMessage mimeMessage = new MimeMessage(session);
			mimeMessage.setSender(iaSender);
			mimeMessage.setSubject(subject);
			mimeMessage.setRecipient(Message.RecipientType.TO, iaRecipient);
			mimeMessage.setContent(mimeMultipart);
			
			//send off the email
			Transport.send(mimeMessage);
			
			System.out.println("sent from " + sender + 
					", to " + recipient + 
					"; server = " + smtpHost + ", port = " + smtpPort);			
		} catch(Exception ex) {
			ex.printStackTrace();
		} finally {
			//clean off
			if(null != outputStream) {
				try { outputStream.close(); outputStream = null; }
				catch(Exception ex) { }
			}
		}
	}
	
	/**
	 * Writes the content of a PDF file (using iText API)
	 * to the {@link OutputStream}.
	 * @param outputStream {@link OutputStream}.
	 * @throws Exception
	 */
	public void writePdf(OutputStream outputStream) throws Exception {
		Document document = new Document();
		PdfWriter.getInstance(document, outputStream);
		
		document.open();
		
		document.addTitle("Test PDF");
		document.addSubject("Testing email PDF");
		document.addKeywords("iText, email");
		document.addAuthor("Jee Vang");
		document.addCreator("Jee Vang");
		
		Paragraph paragraph = new Paragraph();
		paragraph.add(new Chunk("hello!"));
		document.add(paragraph);
		
		document.close();
	}
	
	/**
	 * Main method.
	 * @param args No args required.
	 */
	public static void main(String[] args) {
		EmailWithPdf demo = new EmailWithPdf();
		demo.email();
	}
}

I usually write my blog entries centered around technical issues that I struggled with and couldn’t find a decent answer on the Internet, but after researching and tinkering, found my own way to an acceptable solution. The spirit of this blog entry aligns with the aforementioned sentiment. I hope this blog entry helps you out. Cheers! Sib ntsib dua nawb mog!

About these ads


No Responses Yet to “How to create an in-memory PDF report and send as an email attachment using iText and Java”

  1. Leave a Comment

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.

%d bloggers like this: