Sending Email with Freemarker HTML Template Example

How to compose html emails in Java with Spring and Velocity

In this post I will present how you can format and send automatic emails with Spring and Velocity. Spring offers alone the capability to create simple text emails, which is fine for simple cases, but in typical enterprise application you wouldn’t want to do that for a number of reasons:

  • creating HTML-based email content in Java code is tedious and error prone
  • there is no clear separation between display logic and business logic
  • changing the display structure of the email requires writing Java code, recompiling, redeploying etc

Typically the approach taken to address these issues is to use a template library such as FreeMarker or Velocity to define the display structure of email content. For Podcastpedia I chose Velocity, which is a free open source Java-based templating engine from Apache. In the end my only coding task will be to create the data that is to be rendered in the email template and sending the email.

Читайте также:  Tukey hsd test python

I will base the demonstration on a real scenario from Podcastpedia.org

Scenario

On Podcastpedia.org’s Submit podcast page, we encourage our visitors and podcast producers to submit their podcasts to be included in our podcast directory. Once a podcast is submitted, an automatic email will be generated to notify me (adixchen [AT] proton DOT com ) and the Podcastpedia personnel ( contact [AT] podcastpedia DOT org) about it.

Octocat

Source code for this post is available on Github — podcastpedia.org is an open source project.

Let’s see now how Spring and Velocity play together:

1. Prerequisites

1.1. Spring setup

“The Spring Framework provides a helpful utility library for sending email that shields the user from the specifics of the underlying mailing system and is responsible for low level resource handling on behalf of the client.”[1]

1.1.1. Library depedencies

The following additional jars need to be on the classpath of your application in order to be able to use the Spring Framework’s email library.

I load these dependencies with Maven, so here’s the configuration snippet from pom.xml:

 javax.mail mail 1.4.7 provided  jaf activation 1.0.2 provided 

1.2. Velocity setup

To use Velocity to create your email template(s), you will need to have the Velocity libraries available on your classpath in the first place.

With Maven you have the following dependencies in the pom.xml file:

  org.apache.velocity velocity 1.7  org.apache.velocity velocity-tools 2.0 

2. Email notification service

I defined the EmailNotificationService interface for email notification after a successful podcast submission. It has just one operation, namely to notify the Podcastpedia personnel about the proposed podcast.

The code bellow presents the EmailNotificationServiceImpl, which is the implementation of the interface mentioned above:

package org.podcastpedia.web.suggestpodcast; import java.util.Date; import java.util.HashMap; import java.util.Map; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import org.apache.velocity.app.VelocityEngine; import org.podcastpedia.common.util.config.ConfigService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.mail.javamail.MimeMessagePreparator; import org.springframework.ui.velocity.VelocityEngineUtils; public class EmailNotificationServiceImpl implements EmailNotificationService < @Autowired private ConfigService configService; private JavaMailSender mailSender; private VelocityEngine velocityEngine; public void sendSuggestPodcastNotification(final SuggestedPodcast suggestedPodcast) < MimeMessagePreparator preparator = new MimeMessagePreparator() < @SuppressWarnings(< "rawtypes", "unchecked" >) public void prepare(MimeMessage mimeMessage) throws Exception < MimeMessageHelper message = new MimeMessageHelper(mimeMessage); message.setTo(configService.getValue("EMAIL_TO_SUGGEST_PODCAST")); message.setBcc("example@proton.me"); message.setFrom(new InternetAddress(suggestedPodcast.getEmail()) ); message.setSubject("New suggested podcast"); message.setSentDate(new Date()); Map model = new HashMap(); model.put("newMessage", suggestedPodcast); String text = VelocityEngineUtils.mergeTemplateIntoString( velocityEngine, "velocity/suggestPodcastNotificationMessage.vm", "UTF-8", model); message.setText(text, true); >>; mailSender.send(preparator); > //getters and setters omitted for brevity >

Let’s go a little bit through the code now:

2.1. JavaMailSender and MimeMessagePreparator

The org.springframework.mail package is the root level package for the Spring Framework’s email support. The central interface for sending emails is the MailSender interface, but we are using the org.springframework.mail.javamail.JavaMailSender interface (lines 22, 42), which adds specialized JavaMail features such as MIME message support to the MailSender interface (from which it inherits). JavaMailSender also provides a callback interface for preparation of JavaMail MIME messages, called org.springframework.mail.javamail.MimeMessagePreparator (lines 26-42)

2.2. MimeMessageHelper

Another helpful class when dealing with JavaMail messages is the org.springframework.mail.javamail.MimeMessageHelper class, which shields you from having to use the verbose JavaMail API. As you can see by using the MimeMessageHelper , it becomes pretty easy to create a MimeMessage:

MimeMessageHelper message = new MimeMessageHelper(mimeMessage); message.setTo(configService.getValue("EMAIL_TO_SUGGEST_PODCAST")); message.setBcc("example@proton.me"); message.setFrom(new InternetAddress(suggestedPodcast.getEmail()) ); message.setSubject("New suggested podcast"); message.setSentDate(new Date());

2.3. VelocityEngine

The next thing to note is how the email text is being created:

Map model = new HashMap(); model.put("newPodcast", suggestedPodcast); String text = VelocityEngineUtils.mergeTemplateIntoString( velocityEngine, "velocity/suggestPodcastNotificationMessage.vm", "UTF-8", model); message.setText(text, true);
  • the VelocityEngineUtils.mergeTemplateIntoString method merges the specified template ( suggestPodcastNotificationMessage.vm present in the velocity folder from the classpath) with the given model (model – “newPodcast”), which a map containing model names as keys and model objects as values.
  • you also need to the specify the velocityEngine you work with
  • and, finally, the result is returned as a string

2.3.1. Create velocity template

You can see below the Velocity template that is being used in this example. Note that it is HTML-based, and since it is plain text it can be created using your favorite HTML or text editor.

  

Hi Adrian, you have a new suggested podcast!

From - $ / $

Podcast metadataline

$

With the message

$

2.4. Beans configuration

Let’s see how everything is configured in the application context:

        resource.loader=class class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader     
  • the JavaMailSender has a JNDI reference to a smtp session. A generic example how to configure an email session with a google account can be found in the Jetty9-gmail-account.xml file
  • the VelocityEngineFactoryBean is a factory that configures the VelocityEngine and provides it as a bean reference.
  • the ClasspathResourceLoader is a simple loader that will load templates from the classpath

Octocat

Source code for this post is available on Github — podcastpedia.org is an open source project.

Summary

You’ve learned in this example how to compose html emails in Java with Spring and Velocity. All you need are mail, spring and velocity libraries, compose your email template and use those simple Spring helper classes to add metadata to the email and send it.

Resources

Podcastpedia image

Adrian Matei

Creator of Podcastpedia.org and Codepedia.org, computer science engineer, husband, father, curious and passionate about science, computers, software, education, economics, social equity, philosophy — but these are just outside labels and not that important, deep inside we are all just consciousness, right?

Источник

Spring Mail – Sending Email with Freemarker HTML Template Example

In this tutorial we demonstrate how to send a HTML email using a custom freemarker template using spring framework. In this topic we learn how to create and configure a custom freemarker template using spring.

Project Structure

Let’s start by looking at our project structure.

spring-mail-sending-email-with-freemarker-html-template-example-project-structure

Maven Dependencies

We use Apache Maven to manage our project dependencies. Make sure the following dependencies reside on your class-path.

  4.0.0 com.memorynotfound.mail mail-template-freemaker 1.0.0-SNAPSHOT https://memorynotfound.com Spring MAIL - $ org.springframework.boot spring-boot-starter-parent 1.5.7.RELEASE   org.springframework.boot spring-boot-starter  org.springframework.boot spring-boot-starter-mail  org.freemarker freemarker     org.springframework.boot spring-boot-maven-plugin  maven-compiler-plugin 3.5.1 1.8 1.8     

Email Configuration Properties

We can use two types of configuration files. Both files reside on the classpath located in the src/main/resources folder. The first and my favorite is application.yml file. I like this type because it has a better structure than the other and you’ll have to type less.

# application.yml spring: mail: default-encoding: UTF-8 host: smtp.gmail.com username: [email protected] password: secret port: 587 properties: mail: smtp: auth: true starttls: enable: true protocol: smtp test-connection: false 

The second option you can use is the application.properties file.

# application.properties spring.mail.default-encoding=UTF-8 spring.mail.host=smtp.gmail.com [email protected] spring.mail.password=secret spring.mail.port=587 spring.mail.protocol=smtp spring.mail.test-connection=false spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.enable=true 

Mail Object

We are using this Mail object to pass as an argument for our EmailService to encapsulate the details of an email message and content.

package com.memorynotfound.mail; public class Mail < private String from; private String to; private String subject; private String content; public Mail() < >public Mail(String from, String to, String subject, String content) < this.from = from; this.to = to; this.subject = subject; this.content = content; >public String getFrom() < return from; >public void setFrom(String from) < this.from = from; >public String getTo() < return to; >public void setTo(String to) < this.to = to; >public String getSubject() < return subject; >public void setSubject(String subject) < this.subject = subject; >public String getContent() < return content; >public void setContent(String content) < this.content = content; >@Override public String toString() < return "Mail'; > >

Freemarker Template Java Configuration

We need to tell freemarker where the email templates are located. We do this by creating a FreeMarkerConfigurationFactoryBean and set the location using the setTemplateLoaderPath() method. This tells freemarker to look for a folder on the class-path named templates.

package com.memorynotfound.mail; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean; @Configuration public class FreemarkerConfig < @Bean public FreeMarkerConfigurationFactoryBean getFreeMarkerConfiguration() < FreeMarkerConfigurationFactoryBean bean = new FreeMarkerConfigurationFactoryBean(); bean.setTemplateLoaderPath("/templates/"); return bean; >>

Freemarker HTML Email Template

Now it’s time to write the actual freemarker HTML email template. This file is located in the src/main/resources/templates folder. We create a very basic HTML email template. Notice, we are linking to an email attachment by using the cid: inside the src attribute inside the element. This image will be attached as an attachment in the email service.

        body  

Dear $,

Sending Email using Spring Boot with FreeMarker template .

Thanks

$

$

Populating HTML Email with Freemarker Template

First, we can create a MimeMessage using the JavaMailSender.createMimeMessage() method. Next, we create a MimeMessageHelper and pass in the MimeMessage as an argument. The MimeMessageHelper let’s us add attachments to the MimeMessage .

Then, we lookup the freemarker template using the Configuration.getTemplate() method. Finally, we process the template using the FreeMarkerTemplateUtils.processTemplateIntoString() method and pass in the template and a model. This model are key values which can be used inside the freemarker template.

package com.memorynotfound.mail; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Service; import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import java.io.IOException; import java.nio.charset.StandardCharsets; @Service public class EmailService < @Autowired private JavaMailSender emailSender; @Autowired private Configuration freemarkerConfig; public void sendSimpleMessage(Mail mail) throws MessagingException, IOException, TemplateException < MimeMessage message = emailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(message, MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED, StandardCharsets.UTF_8.name()); helper.addAttachment("logo.png", new ClassPathResource("memorynotfound-logo.png")); Template t = freemarkerConfig.getTemplate("email-template.ftl"); String html = FreeMarkerTemplateUtils.processTemplateIntoString(t, mail.getModel()); helper.setTo(mail.getTo()); helper.setText(html, true); helper.setSubject(mail.getSubject()); helper.setFrom(mail.getFrom()); emailSender.send(message); >>

Spring Mail – Sending Email with Freemarker HTML Template Example

We are using Spring Boot to bootstrap our application. When the application is invoked we simply create a new Mail object and send it using our previously created EmailService

package com.memorynotfound.mail; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import java.util.HashMap; import java.util.Map; @SpringBootApplication public class Application implements ApplicationRunner < private static Logger log = LoggerFactory.getLogger(Application.class); @Autowired private EmailService emailService; public static void main(String[] args) throws Exception < SpringApplication.run(Application.class, args); >@Override public void run(ApplicationArguments applicationArguments) throws Exception < log.info("Sending Email with Freemarker HTML Template Example"); Mail mail = new Mail(); mail.setFrom("[email protected]"); mail.setTo("[email protected]"); mail.setSubject("Sending Email with Freemarker HTML Template Example"); Map model = new HashMap(); model.put("name", "Memorynotfound.com"); model.put("location", "Belgium"); model.put("signature", "https://memorynotfound.com"); mail.setModel(model); emailService.sendSimpleMessage(mail); > > 

Example Received Email

If your configuration is correct, you should receive the following email in your inbox.

spring-mail-sending-email-with-freemarker-html-template-example

References

Источник

Оцените статью