TurboManage

David Chandler's Journal of Java Web and Mobile Development

  • David M. Chandler


    Web app developer since 1994 and former Developer Advocate with Google now residing in Colorado. Besides tech, I enjoy landscape photography and share my work at ColoradoPhoto.gallery.

  • Subscribe

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 241 other followers

  • Sleepless Nights…

    July 2011
    S M T W T F S
    « Jun   Aug »
     12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31  
  • Blog Stats

    • 861,536 hits

Sending HTML emails with App Engine and Velocity in a Maven project

Posted by David Chandler on July 6, 2011

I’ve been using the App Engine Mail API for a while now to send emails in plain text format, but recently decided to beef it up to allow HTML formatting. In addition, I wanted a template-based approach so I could more easily modify the email contents. To achieve both purposes, I chose Apache Velocity, an easy-to-use, general purpose framework that lets you easily create anything textual from a template (text, email, XML, even Java code once on a previous project).

The main subtlety to observe when using Velocity with App Engine is that by default, Velocity uses the filesystem resource loader to load templates. This works fine in the App Engine development server and should also work in production as long as you put your templates in the WAR. Since my project is using Maven, however, the standard way to do this is to put templates in src/main/resources and let Maven automatically copy them to WEB-INF/classes during the build. In order for Velocity to see them on the classpath, you need Velocity’s ClasspathResourceLoader, so I created a helper class that lazily initializes the Velocity engine with the required resource loader:

/**
 * Singleton that initializes Velocity engine instance with the classpath resource loader
 * 
 * @author David Chandler
 */
public class VelocityHelper {
  private static VelocityEngine velocityEngine;

  static VelocityEngine getVelocityEngine() {
    if (velocityEngine == null)
      init();
    return velocityEngine;
  }

  private static void init() {
    velocityEngine = new VelocityEngine();
    Properties velocityProperties = new Properties();
    velocityProperties.put("resource.loader", "class");
    velocityProperties.put("class.resource.loader.description", "Velocity Classpath Resource Loader");
    velocityProperties.put("class.resource.loader.class",
        "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
    velocityEngine.init(velocityProperties);
  }
}

To use the template, first populate the VelocityContext with variables to be replaced, then merge the template:

VelocityContext context = new VelocityContext();
context.put("date", today);
context.put("username", "johndoe");
VelocityEngine ve = VelocityHelper.getVelocityEngine();
// Finds template in WEB-INF/classes
template = ve.getTemplate("emailTemplate.vm");
StringWriter writer = new StringWriter();
template.merge(context, writer);

Since we’re sending an HTML email, the template is just an HTML file named emailTemplate.vm (by convention–.vm stands for Velocity macro). The template merge substitutes variables like ${date} with their values from the VelocityContext populated above. You can also loop over Collections with #foreach ($item in $list) … #end.

Now let’s send the email. There are a couple things to observe here.

First, webmail readers like Gmail write the HEAD and BODY tags to the page, so the browser will likely ignore these tags in your HTML template. This means you can’t link a stylesheet in the HEAD section of your HTML and expect it to work across email clients. The most compatible approach is to use inline styles, that is, the style=”” attribute on various HTML tags right in your template.

Second, in order to send HTML email, you must set the MIME type correctly. Here is the code that takes the template output, sets the MIME type, and sends the email:

import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.ServletException;

...

Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);
try
{
	Message msg = new MimeMessage(session);
	msg.setFrom(from);
	msg.addRecipient(Message.RecipientType.TO, to);
	msg.setSubject(msgSubject);
	if (msgBody.startsWith("<!DOCTYPE html"))
		msg.setContent(msgBody, "text/html");
	else
		msg.setText(msgBody);
	Transport.send(msg);
}
catch (AddressException e)
{
	throw new ServletException(e);
}
catch (MessagingException e)
{
	throw new ServletException(e);
}

That’s it in a nutshell. Spam away…

/dmc

Advertisements

9 Responses to “Sending HTML emails with App Engine and Velocity in a Maven project”

  1. Balaram said

    i liked it. But what is the format of .vm file. What does it contain.

  2. Balaram said

    For this example, can you give me the content of emailTemplate.vm file.

  3. Saulloo said

    Awesome! I never used Velocity, but the solution worked and was very straight-forward to implement! Thanks!

    Following this blog!!!

  4. Achim Roehm said

    Thx a lot for your post Mr. Chandler. With your help I could solve my “ResourceNotFoundException”-problem.

    Kind regards, Achim Roehm

  5. Which method is used to encode the emailTemplate.vm file ?

Leave a Reply

Fill in your details below or click an icon to log in:

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

 
%d bloggers like this: