When JavaMail Meets Groovy Templates
In this quick article, we are going to see how to use the JavaMail API to send via an outgoing SMTP server,
Join the DZone community and get the full member experience.
Join For FreeIn this quick article, we are going to see how to use the JavaMail API to send via an outgoing SMTP server, an HTML email generated with the Apache Groovy Templates module in a Java SE application. We will first design a simple and reusable mail API on top of it, before replacing it with the convenient Apache Commons Email API to not reinvent the wheel.
Using JavaMail API
JavaMail is a Java API, which provides protocol-independent and platform-independent frameworks for sending and receiving mail via SMTP, POP3, and IMAP. It is built into the Java EE platform, but also provides an optional package for use in Java SE. There are two packages that are used in JavaMail API: javax.mail and javax.mail.internet. These packages contain many classes for JavaMail API.
Some of the mail classes that are provided are as follows:
- javax.mail.Session class
- javax.mail.Message class
- javax.mail.internet.MimeMessage class
- javax.mail.Address class
- javax.mail.internet.InternetAddress class
- javax.mail.Authenticator class
- javax.mail.PasswordAuthentication class
- javax.mail.Transport class
- javax.mail.Store class
- javax.mail.Folder class etc.
Maven Dependency
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
Mail.java
package app;
public class Mail {
private String from;
private String to;
private String subject;
private String message;
public Mail() {
}
public Mail(String from,String to,String subject,String message) {
this.from = from;
this.to = to;
this.subject = subject;
this.message = message;
}
public void setFrom(String from) {
this.from = from;
}
public String getFrom() {
return from;
}
public void setTo(String to) {
this.to = to;
}
public String getTo() {
return to;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
MailConfig.java
package app;
import java.util.Properties;
public class MailConfig {
private final String user;
private final String password;
private final Properties properties;
public MailConfig(String user,String password,String host) {
this.user = user;
this.password = password;
properties = new Properties();
properties.put("mail.smtp.auth", "true");
properties.put("mail.smtp.starttls.enable", "true");
properties.put("mail.smtp.host", host);
properties.put("mail.smtp.port", "25");
}
public MailConfig(String user,String password,String host,String port) {
this(user,password,host);
properties.put("mail.smtp.port", port);
}
public String getUser() {
return user;
}
public String getPassword() {
return password;
}
public Properties getProperties() {
return properties;
}
}
MailSender.java
package app;
import javax.mail.PasswordAuthentication;
import java.util.Date;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class MailSender {
private final MailConfig config;
public MailSender(MailConfig config) {
this.config = config;
}
public void send(Mail mail) {
try {
Session session = Session.getInstance(config.getProperties(),
new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(config.getUser(), config.getPassword());
}
});
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(mail.getFrom()));
message.setRecipients(Message.RecipientType.TO,InternetAddress.parse(mail.getTo()));
message.setSubject(mail.getSubject());
message.setContent(mail.getMessage(),"text/html");
message.setSentDate(new Date());
Transport.send(message);
} catch (MessagingException e) {
e.printStackTrace();
}
}
public MailConfig getConfig() {
return config;
}
}
To send the mail, we will use the SMTP server of the Zoho mail service which is, by the way, the most complete and cheap business email service out there with a gorgeous and robust webmail application built with the Apache Struts web framework.
App.java
package app;
public class App {
public static void main(String[] args) {
MailConfig config = new MailConfig("noreply@dzone.com","899djdjdgd95vnfn32","smtp.zoho.com","587");
MailSender sender = new MailSender(config);
Mail mail = new Mail();
mail.setFrom("noreply@dzone.com");
mail.setTo("john.doe@lightbend.com");
mail.setSubject("html message");
mail.setMessage("<p style='font-size:16px;color:red'>Hello John Doe</p>");
sender.send(mail);
}
}
Using Apache Commons Email API
Apache Commons Email aims to provide an API for sending emails. It is built on top of the JavaMail API, which it aims to simplify.
Some of the mail classes that are provided are as follows:
- SimpleEmail — This class is used to send basic text based emails.
- MultiPartEmail — This class is used to send multipart messages. This allows a text message with attachments either inline or attached.
- HtmlEmail — This class is used to send HTML formatted emails. It has all of the capabilities as MultiPartEmail allowing attachments to be easily added. It also supports embedded images.
- ImageHtmlEmail — This class is used to send HTML formatted emails with inline images. It has all of the capabilities as HtmlEmail but transforms all image references to inline images.
- EmailAttachment — This is a simple container class to allow for easy handling of attachments. It is for use with instances of MultiPartEmail and HtmlEmail.
Maven Dependency
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-email</artifactId>
<version>1.5</version>
</dependency>
App.java
package app;
import org.apache.commons.mail.DefaultAuthenticator;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.HtmlEmail;
public class App {
public static void main(String[] args) throws EmailException {
HtmlEmail mail = new HtmlEmail();
mail.setHostName("smtp.zoho.com");
mail.setSmtpPort(587);
mail.setAuthenticator(new DefaultAuthenticator("noreply@dzone.com", "899djdjdgd95vnfn32"));
mail.setSSLOnConnect(true);
mail.setFrom("noreply@dzone.com", "Dzone");
mail.addTo("john.doe@lightbend.com", "John Doe");
mail.setSubject("html message");
mail.setHtmlMsg("<p style='font-size:16px;color:red'>Hello John Doe</p>");
mail.send();
}
}
Using Apache Groovy Templates Module
The template framework in Groovy consists of a TemplateEngine abstract base class that engines must implement and a Template interface that the resulting templates they generate must implement.
Included with Groovy are several template engines:
- SimpleTemplateEngine — for basic templates
- StreamingTemplateEngine — functionally equivalent to SimpleTemplateEngine, but can handle strings larger than 64k
- GStringTemplateEngine — stores the template as writeable closures (useful for streaming scenarios)
- XmlTemplateEngine — works well when the template and output are valid XML
- MarkupTemplateEngine — a very complete, optimized, template engine
The MarkupTemplateEngine is a template engine primarily aimed at generating XML-like markup (XML, XHTML, HTML5, …), but that can be used to generate any text-based content. Unlike traditional template engines, this one relies on a DSL that uses the builder syntax.
Maven Dependency
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-templates</artifactId>
<version>2.5.4</version>
</dependency>
template.groovy
p(style : "font-size:16px;color:red") {
yield "Hello $name"
}
App.java
package app;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.mail.DefaultAuthenticator;
import org.apache.commons.mail.HtmlEmail;
import groovy.text.markup.MarkupTemplateEngine;
public class App {
public static void main(String[] args) throws Exception {
HtmlEmail mail = new HtmlEmail();
mail.setHostName("smtp.zoho.com");
mail.setSmtpPort(587);
mail.setAuthenticator(new DefaultAuthenticator("noreply@dzone.com", "899djdjdgd95vnfn32"));
mail.setSSLOnConnect(true);
mail.setFrom("noreply@dzone.com", "Dzone");
mail.addTo("john.doe@lightbend.com", "John Doe");
mail.setSubject("html message");
Map<String,Object> map = new HashMap<String,Object>();
map.put("name", "John Doe");
mail.setHtmlMsg(parseTemplate("template.groovy",map));
mail.send();
}
public static String parseTemplate(String file,Map<String,Object> map) throws Exception {
return new MarkupTemplateEngine().createTemplate(readFile(file)).make(map).toString();
}
public static String readFile(String file) throws Exception {
BufferedReader reader = new BufferedReader(new FileReader(new File(file)),1024);
String content = "";
StringBuffer buffer = new StringBuffer();
while((content = reader.readLine()) != null) buffer.append(content);
reader.close();
return buffer.toString();
}
}
Output
Hello John Doe
Feel free to customize this solution as you wish and to even port it to a Java EE environment with the Apache Tomcat web server, and since establishing a connection to a SMTP server is time-consuming, just remind yourself to send the mail in a thread so your users won't have to wait for too long to get the message which will tell them to check their inbox.
final HtmlEmail mail = new HtmlEmail();
new Thread(new Runnable() {
public void run() {
mail.send();
}
}).start();
If you have to use the HTML entities in the subject of the mail, just don't forget to unescape them. You can face this situation when dealing with the French characters and for the unescaping, you can just use the Apache Commons Lang API.
import org.apache.commons.lang3.StringEscapeUtils;
final HtmlEmail mail = new HtmlEmail();
mail.setSubject(StringEscapeUtils.unescapeHtml4("création site web"));
Opinions expressed by DZone contributors are their own.
Comments