I've got an assigment to send HTML mail with the JavaMail API. Here is a small part of my code:
MimeMessage message = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message);
try {
helper.setTo(recipients);
helper.setSubject("Simple mail template");
helper.setText("<html><body>Hi There</body><html>",html:true);
} catch (MessagingException e) {
e.printStackTrace();
}
Now I've got an assigment to move the HTML in a separate file, and create a class to read that HTML template and send a mail with it. Any suggestions on how to do that?
I've created a minimal example with Thymeleaf as a template engine. You first wrote that you are using Spring Boot in your project, so I assume you can use it. I also assume you are using either Maven or Gradle as a build tool.
Add the spring-boot-starter-thymeleaf
dependency to your project. Are you using Maven or Gradle?
Your pom.xml
dependencies should include:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Your build.gradle
dependencies should include:
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
Add the required @Bean
s. Those are:
@Bean
public ITemplateResolver templateResolver()
{
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix("templates/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode(TemplateMode.HTML);
return templateResolver;
}
@Bean
public TemplateEngine templateEngine()
{
TemplateEngine templateEngine = new TemplateEngine();
templateEngine.setTemplateResolver(this.templateResolver());
return templateEngine;
}
They can go into any class annotated with @Configuration
(or @SpringBootApplication
).
Now, you can access your TemplateEngine
from any class whose fields are injected by Spring.
@Component
public class SomeClass
{
@Autowired
private TemplateEngine templateEngine;
public String generateMailHtml(String text)
{
Map<String, Object> variables = new HashMap<>();
variables.put("mailtext", text);
final String templateFileName = "mail"; //Name of the template file without extension
String output = this.templateEngine.process(templateFileName, new Context(Locale.getDefault(), variables));
return output;
}
}
The mail.html
should be located in the classpath (resources/
) under templates/
.
And it should look like this:
<html>
<body data-th-text="${mailtext}"></body>
</html>
Your code snippet you posted could now look like this (@Autowired
SomeClass
as someClass
in the class outside of the method):
MimeMessage message = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message);
try {
helper.setTo(recipients);
helper.setSubject("Simple mail template");
helper.setText(someClass.generateMailHtml("Hi There"), true);
} catch (MessagingException e) {
e.printStackTrace();
}
Of course, change the examples according to your needs!
You mentioned you need to fill the template "with a list of some names". This would be achieved like that:
public String generateMailHtml(List<String> names)
{
Map<String, Object> variables = new HashMap<>();
variables.put("names", names);
final String templateFileName = "mail"; //Name of the template file without extension
String output = this.templateEngine.process(templateFileName, new Context(Locale.getDefault(), variables));
return output;
}
mail.html
<html>
<body>
<ul>
<li data-th-each="name : ${names}" data-th-text="${name}"></li>
</ul>
</body>
</html>
Read more about data-th-each
/ th:each
here. Note: You can use data-th-
and th:
interchangably, though data-th-
is more HTML5-friendly.