Using thymeleaf template for sending Mail with Spring
Solution 1
I got it working finally ... I changed the following line
final Context ctx = new Context(locale);
with
final WebContext ctx = new WebContext(request,request.getContext(),locale);
Now I am able to send any template or attachment anything works great ..!!
Solution 2
You are getting this issue because, it seems, you don't have a mail folder inside WEB-INF/classes folder.
According to the configuration mentioned below, it is expecting a mail folder inside WEB-INF/classes folder.
<bean id="emailTemplateResolver" class="org.thymeleaf.templateresolver.ClassLoaderTemplateResolver">
<property name="prefix" value="mail/" />
<property name="templateMode" value="HTML5" />
<property name="characterEncoding" value="UTF-8" />
<property name="order" value="1" />
<!-- Template cache is true by default. Set to false if you want -->
<!-- templates to be automatically updated when modified. -->
<property name="cacheable" value="true" />
</bean>
So, create a folder with name "mail" inside your "resouces" folder and keep the mail templates inside "mail" folder. Make sure that you got this "mail" folder inside WEB-INF/classes folder while deploying. This should solve your problem
IMO, we shouldn't use WebContext as it requires a "request" object and strong coupling the mail with request is not a good idea.
Comments
-
Ruby almost 2 years
I'm trying to use Thymeleaf template for Spring application to send mail, I am taking the reference from here https://github.com/thymeleaf/thymeleafexamples-springmail/
I am not getting any error but still it doesn't work ..I am using the same code as given in github still no luck ...Can anybody suggest how to do that??
Following is the method which is used to send mail ...
public void sendSimpleMail( final String recipientName, final String recipientEmail, final Locale locale) throws MessagingException { final Context ctx = new Context(locale); ctx.setVariable("name", recipientName); ctx.setVariable("subscriptionDate", new Date()); ctx.setVariable("hobbies", Arrays.asList("Cinema", "Sports", "Music")); final MimeMessage mimeMessage = this.mailSender.createMimeMessage(); final MimeMessageHelper message = new MimeMessageHelper(mimeMessage, "UTF-8"); message.setSubject("Example HTML email (simple)"); message.setFrom("[email protected]"); message.setTo(recipientEmail); // Create the HTML body using Thymeleaf final String htmlContent = this.templateEngine.process("email-simple.html", ctx); message.setText(htmlContent /* isHtml */); // Send email System.out.println("........"); this.mailSender.send(mimeMessage); }
If I remove the line which is creating the html body using thymeleaf and send a ordinary mail it works but not with template ..
This is the line which causing problem ... just redirect to error page
final String htmlContent = this.templateEngine.process("email-simple.html", ctx);
Following is the error I am getting ..
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] at org.thymeleaf.resourceresolver.ServletContextResourceResolver.getResourceAsStream(ServletContextResourceResolver.java:74) at org.thymeleaf.TemplateParser.parseDocument(TemplateParser.java:254) at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:812) at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:769) at com.ivb.coep.other.EmailService.sendSimpleMail(EmailService.java:72) at com.ivb.coep.controller.MainController.sendTextMail(MainController.java:83) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789) at javax.servlet.http.HttpServlet.service(HttpServlet.java:647) at javax.servlet.http.HttpServlet.service(HttpServlet.java:728) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source)
-
vphilipnyc over 9 yearsI know this is an old answer, but one reason not to go this route is that you'll be dependent on the request as @real gadha mentioned. This might be ok for a test application, but if you later use Spring's ApplicationEvent structure to listen for events and fire emails while carrying out other logic, you may not have access to the request.
-
Krish about 5 yearshow are you getting the request object here ?