Reputation: 187
first of all, I have read al questions about thymeleaf email rendering, I mean, the original tutorial:
http://www.thymeleaf.org/doc/articles/springmail.html
And other solved stackoverflow questions about this, The thing is I cant reach to a proper solution, and it starts to be annoying... so, please, can you please help me with this?
The problem, as many people, I want to send rich HTML emails, and here is my Thymeleaf configuration:
@Configuration
public class ThymeleafConfig {
@Bean
public ClassLoaderTemplateResolver emailTemplateResolver(){
ClassLoaderTemplateResolver emailResolver = new ClassLoaderTemplateResolver();
emailResolver.setPrefix("/WEB-INF/mailTemplates/");
emailResolver.setSuffix(".html");
emailResolver.setTemplateMode("HTML5");
emailResolver.setOrder(1);
return emailResolver;
}
@Bean
public ServletContextTemplateResolver webTemplateResolver() {
ServletContextTemplateResolver webResolver = new ServletContextTemplateResolver();
webResolver.setPrefix("/WEB-INF/templates/");
webResolver.setSuffix(".html");
webResolver.setTemplateMode("HTML5");
webResolver.setOrder(2);
return webResolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.addTemplateResolver(emailTemplateResolver());
engine.addTemplateResolver(webTemplateResolver());
engine.addDialect(new SpringSecurityDialect());
return engine;
}
@Bean
public ThymeleafViewResolver thymeleafViewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
resolver.setOrder(1);
return resolver;
}
}
in the emailResolver.setPrefix("/WEB-INF/mailTemplates/"); line I tried to put the original example config instead, like emailResolver.setPrefix("/mail/"); and reorganising files in the eclipse project. Now its going like this
The method who sends the emails goes like this:
public void sendRegistrationEmail(String contextPath, Locale locale, User user) throws MessagingException{
String token = UUID.randomUUID().toString();
userService.createVerificationToken(user, token);
String recipientAddress = user.getEmail();
String subject = "Register";
String confirmationUrl = contextPath + "/regitrationConfirm.html?token=" + token;
String imageResourceName= "/images/myLogo.jpg";
final Context ctx = new Context(locale);
ctx.setVariable("name", user.getShownUsername());
ctx.setVariable("subscriptionDate", new Date());
ctx.setVariable("logo", imageResourceName);
ctx.setVariable("name", user.getShownUsername());
ctx.setVariable("loginName", user.getUsername());
ctx.setVariable("email", user.getEmail());
ctx.setVariable("link", confirmationUrl);
final String htmlContent = templateEngine.process("registrationTemplate", ctx);
final MimeMessage mimeMessage = this.mailSender.createMimeMessage();
final MimeMessageHelper message = new MimeMessageHelper(mimeMessage);
message.setFrom("<" + env.getProperty("email.username") + ">");
message.setTo("<" + recipientAddress + ">");
message.setSubject(subject);
message.setText(htmlContent,true);
mailSender.send(mimeMessage);
}
And, of course, the error in which Tomcat says that the Servlet context cant render this template.
I have debbugged inside the thymelead code, and when it has to render the template, I have checked how it tryes to render the mail with the ClassLoaderTemplateResolver:
and its simply write in the log this message:
logger.trace("[THYMELEAF][{}] Template \"{}\" could not be resolved as resource \"{}\" with resource resolver \"{}\"", new Object[] {TemplateEngine.threadIndex(), templateName, resourceName, resourceResolver.getName()});
with this params:
resourceName = /WEB-INF/mailTemplates/registrationTemplate.html
templateName = registrationTemplate
resourceResolver.getName() = org.thymeleaf.resourceresolver.ClassLoaderResourceResolver
I am pretty sure that the error is a little thing in some configuration or anything like that, buy I don't now where to search it...
The exception runs when it dont render the template with the ClassLoader, and then its try to use the second renter template, the Servlet one, and it crashes with this well-known error:
Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateProcessingException: Resource resolution by ServletContext with org.thymeleaf.resourceresolver.ServletContextResourceResolver can only be performed when context implements org.thymeleaf.context.IWebContext [current context: org.thymeleaf.context.Context]] con causa raíz
org.thymeleaf.exceptions.TemplateProcessingException: Resource resolution by ServletContext with org.thymeleaf.resourceresolver.ServletContextResourceResolver can only be performed when context implements org.thymeleaf.context.IWebContext [current context: org.thymeleaf.context.Context]
Any ideas?
I have read this approach: Using multiple template resolvers with Spring 3.2 and Thymeleaf 2.1.3 for emails
But it will be nice to get it work with the configuration like the Thymeleaf example, avoiding to send the request, etc
Thanks in advance!
EDIT:
To add more info, here is the email template:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title th:remove="all">Registration Template</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="#{email.registration.greeting(${name})}">
Hello, Username!
</p>
<p>
Registering on <span th:text="${#dates.format(subscriptionDate)}">Date</span>.
</p>
<p>Your data:</p>
<ul th:remove="all-but-first">
<li th:text="#{email.registration.loginname(${loginName})}">Login: username</li>
<li th:text="#{email.registration.shownusername(${shownUserName})}">show name: UserName</li>
<li th:text="#{email.registration.email(${email})}">email: [email protected]</li>
</ul>
<p>
Register link:
</p>
<p th:text="${link}"></p>
<p>
Thanks!
</p>
<p>
<img src="sample.png" th:src="'cid:' + ${logo}" />
</p>
</body>
</html>
Upvotes: 2
Views: 1825
Reputation: 5440
i'm nearly sure the issue comes from this configuration :
ClassLoaderTemplateResolver emailResolver = new ClassLoaderTemplateResolver();
emailResolver.setPrefix("/WEB-INF/mailTemplates/");
/WEB-INF/mailTemplates is not on the classpath when you are in a war. Instead, put your mailTemplates folder in src/resources. It will then be put in /WEB-INF/classes/ in the war, and you should be able to access them with this configuration :
ClassLoaderTemplateResolver emailResolver = new ClassLoaderTemplateResolver();
emailResolver.setPrefix("/mailTemplates/");
EDIT: the other solution is to use a ServletContextTemplateResolver for the email templates too :
ServletContextTemplateResolver emailResolver = new ServletContextTemplateResolver();
emailResolver.setPrefix("/WEB-INF/mailTemplates/");
Upvotes: 3