Using thymeleaf template for sending Mail with Spring

10,354

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.

Share:
10,354
Ruby
Author by

Ruby

Software Engineer, Love Java Coding

Updated on June 09, 2022

Comments

  • Ruby
    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
    vphilipnyc over 9 years
    I 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
    Krish about 5 years
    how are you getting the request object here ?