From a9d54c14565f5606568aee7cb2f2c6911a71170d Mon Sep 17 00:00:00 2001 From: Benjamin Caure Date: Thu, 23 Apr 2020 07:23:11 +0200 Subject: [PATCH] BAEL-3964 HTML emails with Thymeleaf and FreeMarker (#9119) --- spring-mvc-basics-2/README.md | 1 + .../ApplicationConfiguration.java | 30 +----- .../configuration/EmailConfiguration.java | 89 ++++++++++++++++++ .../spring/configuration/WebInitializer.java | 1 + .../spring/controller/MailController.java | 80 ++++++++++++---- .../baeldung/spring/domain/MailObject.java | 29 ++++++ .../baeldung/spring/mail/EmailService.java | 20 +++- .../spring/mail/EmailServiceImpl.java | 84 ++++++++++++++--- .../src/main/resources/mail-logo.png | Bin 0 -> 7391 bytes .../main/resources/mailMessages.properties | 5 + .../resources/mailMessages_fr_FR.properties | 5 + .../src/main/webapp/WEB-INF/views/emails.jsp | 7 +- .../webapp/WEB-INF/views/mail/sendHtml.jsp | 73 ++++++++++++++ .../views/mail/template-freemarker.ftl | 15 +++ .../views/mail/template-thymeleaf.html | 15 +++ .../java/com/baeldung/SpringContextTest.java | 3 +- .../rss/ArticleRssIntegrationTest.java | 4 +- 17 files changed, 396 insertions(+), 65 deletions(-) create mode 100644 spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/EmailConfiguration.java create mode 100644 spring-mvc-basics-2/src/main/resources/mail-logo.png create mode 100644 spring-mvc-basics-2/src/main/resources/mailMessages.properties create mode 100644 spring-mvc-basics-2/src/main/resources/mailMessages_fr_FR.properties create mode 100644 spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/sendHtml.jsp create mode 100644 spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/template-freemarker.ftl create mode 100644 spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/template-thymeleaf.html diff --git a/spring-mvc-basics-2/README.md b/spring-mvc-basics-2/README.md index 9d1402a210..e52459bd6e 100644 --- a/spring-mvc-basics-2/README.md +++ b/spring-mvc-basics-2/README.md @@ -9,6 +9,7 @@ This module contains articles about Spring MVC - [Servlet Redirect vs Forward](https://www.baeldung.com/servlet-redirect-forward) - [Apache Tiles Integration with Spring MVC](https://www.baeldung.com/spring-mvc-apache-tiles) - [Guide to Spring Email](https://www.baeldung.com/spring-email) +- [Using ThymeLeaf and FreeMarker Emails Templates with Spring](https://www.baeldung.com/thymeleaf-freemarker-email) - [Request Method Not Supported (405) in Spring](https://www.baeldung.com/spring-request-method-not-supported-405) - [Spring @RequestParam Annotation](https://www.baeldung.com/spring-request-param) - More articles: [[more -->]](/spring-mvc-basics-3) diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java index 941a984684..e70e801577 100644 --- a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java +++ b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java @@ -2,7 +2,6 @@ package com.baeldung.spring.configuration; import java.util.ArrayList; import java.util.List; -import java.util.Properties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; @@ -10,9 +9,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.feed.RssChannelHttpMessageConverter; -import org.springframework.mail.SimpleMailMessage; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.web.accept.ContentNegotiationManager; import org.springframework.web.multipart.MultipartResolver; import org.springframework.web.multipart.commons.CommonsMultipartResolver; @@ -65,29 +61,5 @@ public class ApplicationConfiguration implements WebMvcConfigurer { converters.add(new RssChannelHttpMessageConverter()); converters.add(new JsonChannelHttpMessageConverter()); } - - @Bean - public SimpleMailMessage templateSimpleMessage() { - SimpleMailMessage message = new SimpleMailMessage(); - message.setText("This is the test email template for your email:\n%s\n"); - return message; - } - - @Bean - public JavaMailSender getJavaMailSender() { - JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); - mailSender.setHost("smtp.gmail.com"); - mailSender.setPort(587); - - mailSender.setUsername("my.gmail@gmail.com"); - mailSender.setPassword("password"); - - Properties props = mailSender.getJavaMailProperties(); - props.put("mail.transport.protocol", "smtp"); - props.put("mail.smtp.auth", "true"); - props.put("mail.smtp.starttls.enable", "true"); - props.put("mail.debug", "true"); - - return mailSender; - } + } diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/EmailConfiguration.java b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/EmailConfiguration.java new file mode 100644 index 0000000000..1bbbc51304 --- /dev/null +++ b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/EmailConfiguration.java @@ -0,0 +1,89 @@ +package com.baeldung.spring.configuration; + +import java.util.Properties; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.ResourceBundleMessageSource; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.JavaMailSenderImpl; +import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; +import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver; +import org.thymeleaf.spring4.SpringTemplateEngine; +import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver; + +@Configuration +@ComponentScan(basePackages = { "com.baeldung.spring.mail" }) +public class EmailConfiguration { + + @Bean + public JavaMailSender getJavaMailSender() { + JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); + + mailSender.setHost("smtp.gmail.com"); + mailSender.setPort(587); + + mailSender.setUsername("my.gmail@gmail.com"); + mailSender.setPassword("password"); + + Properties props = mailSender.getJavaMailProperties(); + props.put("mail.transport.protocol", "smtp"); + props.put("mail.smtp.auth", "true"); + props.put("mail.smtp.starttls.enable", "false"); + props.put("mail.debug", "true"); + + return mailSender; + } + + @Bean + public SimpleMailMessage templateSimpleMessage() { + SimpleMailMessage message = new SimpleMailMessage(); + message.setText("This is the test email template for your email:\n%s\n"); + return message; + } + + @Bean + public SpringTemplateEngine thymeleafTemplateEngine() { + SpringTemplateEngine templateEngine = new SpringTemplateEngine(); + templateEngine.setTemplateResolver(thymeleafTemplateResolver()); + templateEngine.setTemplateEngineMessageSource(emailMessageSource()); + return templateEngine; + } + + @Bean + public SpringResourceTemplateResolver thymeleafTemplateResolver() { + SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver(); + templateResolver.setPrefix("/WEB-INF/views/mail/"); + templateResolver.setSuffix(".html"); + templateResolver.setTemplateMode("HTML"); + templateResolver.setCharacterEncoding("UTF-8"); + return templateResolver; + } + + @Bean + public FreeMarkerConfigurer freemarkerConfig() { + FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer(); + freeMarkerConfigurer.setTemplateLoaderPath("/WEB-INF/views/mail"); + return freeMarkerConfigurer; + } + + @Bean + public FreeMarkerViewResolver freemarkerViewResolver() { + FreeMarkerViewResolver resolver = new FreeMarkerViewResolver(); + resolver.setCache(true); + resolver.setPrefix(""); + resolver.setSuffix(".ftl"); + return resolver; + } + + + @Bean + public ResourceBundleMessageSource emailMessageSource() { + final ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); + messageSource.setBasename("/mailMessages"); + return messageSource; + } + +} diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/WebInitializer.java b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/WebInitializer.java index 74094a11c7..4d43549440 100644 --- a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/WebInitializer.java +++ b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/WebInitializer.java @@ -20,6 +20,7 @@ public class WebInitializer implements WebApplicationInitializer { // ctx.register(GroovyConfiguration.class); // ctx.register(JadeTemplateConfiguration.class); // ctx.register(PushConfiguration.class); + ctx.register(EmailConfiguration.class); // ctx.setServletContext(container); //ctx.register(TilesApplicationConfiguration.class); diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/MailController.java b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/MailController.java index 16d1202eef..b6e19a4c39 100644 --- a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/MailController.java +++ b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/MailController.java @@ -1,10 +1,17 @@ package com.baeldung.spring.controller; -import com.baeldung.spring.mail.EmailServiceImpl; -import com.baeldung.spring.domain.MailObject; +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import javax.mail.MessagingException; +import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.mail.SimpleMailMessage; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.Errors; @@ -12,26 +19,21 @@ import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -import javax.servlet.http.HttpServletRequest; -import javax.validation.Valid; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; +import com.baeldung.spring.domain.MailObject; +import com.baeldung.spring.mail.EmailService; + +import freemarker.template.TemplateException; @Controller @RequestMapping("/mail") public class MailController { @Autowired - public EmailServiceImpl emailService; + public EmailService emailService; @Value("${attachment.invoice}") private String attachmentPath; - @Autowired - public SimpleMailMessage template; - private static final Map> labels; static { @@ -46,7 +48,7 @@ public class MailController { //Email with template props = new HashMap<>(); - props.put("headerText", "Send Email Using Template"); + props.put("headerText", "Send Email Using Text Template"); props.put("messageLabel", "Template Parameter"); props.put("additionalInfo", "The parameter value will be added to the following message template:
" + @@ -60,6 +62,7 @@ public class MailController { props.put("messageLabel", "Message"); props.put("additionalInfo", "To make sure that you send an attachment with this email, change the value for the 'attachment.invoice' in the application.properties file to the path to the attachment."); labels.put("sendAttachment", props); + } @RequestMapping(method = RequestMethod.GET) @@ -85,6 +88,7 @@ public class MailController { return "mail/send"; } + @RequestMapping(value = "/send", method = RequestMethod.POST) public String createMail(Model model, @ModelAttribute("mailObject") @Valid MailObject mailObject, @@ -95,7 +99,7 @@ public class MailController { emailService.sendSimpleMessage(mailObject.getTo(), mailObject.getSubject(), mailObject.getText()); - return "redirect:/home"; + return "emails"; } @RequestMapping(value = "/sendTemplate", method = RequestMethod.POST) @@ -107,10 +111,9 @@ public class MailController { } emailService.sendSimpleMessageUsingTemplate(mailObject.getTo(), mailObject.getSubject(), - template, mailObject.getText()); - return "redirect:/home"; + return "redirect:/mail"; } @RequestMapping(value = "/sendAttachment", method = RequestMethod.POST) @@ -127,6 +130,47 @@ public class MailController { attachmentPath ); - return "redirect:/home"; + return "redirect:/mail"; + } + + + @RequestMapping(value = {"/sendHtml"}, method = RequestMethod.GET) + public String getHtmlMailView(Model model, + HttpServletRequest request) { + + Map templateEngines = new HashMap<>(); + templateEngines.put("Thymeleaf", "Thymeleaf"); + templateEngines.put("Freemarker", "Freemarker"); + model.addAttribute("mailObject", new MailObject()); + model.addAttribute("templateEngines", templateEngines); + return "mail/sendHtml"; + } + + @RequestMapping(value = "/sendHtml", method = RequestMethod.POST) + public String createHtmlMail(Model model, + @ModelAttribute("mailObject") @Valid MailObject mailObject, + Errors errors) throws IOException, MessagingException, TemplateException { + if (errors.hasErrors()) { + return "mail/send"; + } + + Map templateModel = new HashMap<>(); + templateModel.put("recipientName", mailObject.getRecipientName()); + templateModel.put("text", mailObject.getText()); + templateModel.put("senderName", mailObject.getSenderName()); + + if (mailObject.getTemplateEngine().equalsIgnoreCase("thymeleaf")) { + emailService.sendMessageUsingThymeleafTemplate( + mailObject.getTo(), + mailObject.getSubject(), + templateModel); + } else { + emailService.sendMessageUsingFreemarkerTemplate( + mailObject.getTo(), + mailObject.getSubject(), + templateModel); + } + + return "redirect:/mail"; } } diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/MailObject.java b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/MailObject.java index aceaf685fa..d425ca9a26 100644 --- a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/MailObject.java +++ b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/MailObject.java @@ -12,8 +12,11 @@ public class MailObject { @NotNull @Size(min = 1, message = "Please, set an email address to send the message to it") private String to; + private String recipientName; private String subject; private String text; + private String senderName; + private String templateEngine; public String getTo() { return to; @@ -38,4 +41,30 @@ public class MailObject { public void setText(String text) { this.text = text; } + + public String getRecipientName() { + return recipientName; + } + + public void setRecipientName(String recipientName) { + this.recipientName = recipientName; + } + + public String getSenderName() { + return senderName; + } + + public void setSenderName(String senderName) { + this.senderName = senderName; + } + + public String getTemplateEngine() { + return templateEngine; + } + + public void setTemplateEngine(String templateEngine) { + this.templateEngine = templateEngine; + } + + } diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailService.java b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailService.java index 43d7378227..b7d5be09c8 100644 --- a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailService.java +++ b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailService.java @@ -1,6 +1,11 @@ package com.baeldung.spring.mail; -import org.springframework.mail.SimpleMailMessage; +import java.io.IOException; +import java.util.Map; + +import javax.mail.MessagingException; + +import freemarker.template.TemplateException; /** * Created by Olga on 8/22/2016. @@ -11,10 +16,19 @@ public interface EmailService { String text); void sendSimpleMessageUsingTemplate(String to, String subject, - SimpleMailMessage template, - String ...templateArgs); + String ...templateModel); void sendMessageWithAttachment(String to, String subject, String text, String pathToAttachment); + + void sendMessageUsingThymeleafTemplate(String to, + String subject, + Map templateModel) + throws IOException, MessagingException; + + void sendMessageUsingFreemarkerTemplate(String to, + String subject, + Map templateModel) + throws IOException, TemplateException, MessagingException; } diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java index 039b970d8e..0592415ab5 100644 --- a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java +++ b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java @@ -1,26 +1,49 @@ package com.baeldung.spring.mail; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.io.FileSystemResource; -import org.springframework.mail.MailException; -import org.springframework.mail.SimpleMailMessage; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.mail.javamail.MimeMessageHelper; -import org.springframework.stereotype.Component; - import java.io.File; +import java.io.IOException; +import java.util.Map; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.mail.MailException; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Service; +import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; +import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; +import org.thymeleaf.context.Context; +import org.thymeleaf.spring4.SpringTemplateEngine; + +import freemarker.template.Template; +import freemarker.template.TemplateException; + /** * Created by Olga on 7/15/2016. */ -@Component +@Service("EmailService") public class EmailServiceImpl implements EmailService { @Autowired public JavaMailSender emailSender; + + @Autowired + public SimpleMailMessage template; + + @Autowired + private SpringTemplateEngine thymeleafTemplateEngine; + + @Autowired + private FreeMarkerConfigurer freemarkerConfigurer; + + @Value("classpath:/mail-logo.png") + Resource resourceFile; public void sendSimpleMessage(String to, String subject, String text) { try { @@ -38,9 +61,8 @@ public class EmailServiceImpl implements EmailService { @Override public void sendSimpleMessageUsingTemplate(String to, String subject, - SimpleMailMessage template, - String ...templateArgs) { - String text = String.format(template.getText(), templateArgs); + String ...templateModel) { + String text = String.format(template.getText(), templateModel); sendSimpleMessage(to, subject, text); } @@ -66,4 +88,42 @@ public class EmailServiceImpl implements EmailService { e.printStackTrace(); } } + + + @Override + public void sendMessageUsingThymeleafTemplate( + String to, String subject, Map templateModel) + throws MessagingException { + + Context thymeleafContext = new Context(); + thymeleafContext.setVariables(templateModel); + + String htmlBody = thymeleafTemplateEngine.process("template-thymeleaf.html", thymeleafContext); + + sendHtmlMessage(to, subject, htmlBody); + } + + @Override + public void sendMessageUsingFreemarkerTemplate( + String to, String subject, Map templateModel) + throws IOException, TemplateException, MessagingException { + + Template freemarkerTemplate = freemarkerConfigurer.createConfiguration().getTemplate("template-freemarker.ftl"); + String htmlBody = FreeMarkerTemplateUtils.processTemplateIntoString(freemarkerTemplate, templateModel); + + sendHtmlMessage(to, subject, htmlBody); + } + + private void sendHtmlMessage(String to, String subject, String htmlBody) throws MessagingException { + + MimeMessage message = emailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(htmlBody, true); + helper.addInline("attachment.png", resourceFile); + emailSender.send(message); + + } + } diff --git a/spring-mvc-basics-2/src/main/resources/mail-logo.png b/spring-mvc-basics-2/src/main/resources/mail-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..edb83efbe3d4f083363fea616d5c0e2df6e1fe03 GIT binary patch literal 7391 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 TggyZsN(>c6O@%LVmf`;o*#$Af literal 0 HcmV?d00001 diff --git a/spring-mvc-basics-2/src/main/resources/mailMessages.properties b/spring-mvc-basics-2/src/main/resources/mailMessages.properties new file mode 100644 index 0000000000..46f7a80ed3 --- /dev/null +++ b/spring-mvc-basics-2/src/main/resources/mailMessages.properties @@ -0,0 +1,5 @@ +greetings=Hi {0}, +subscriptions=Please find below your current subscriptions to our forum: +regards=Regards, +unsubscribe=Unsubscribe from these emails here +signature={0} at Baeldung \ No newline at end of file diff --git a/spring-mvc-basics-2/src/main/resources/mailMessages_fr_FR.properties b/spring-mvc-basics-2/src/main/resources/mailMessages_fr_FR.properties new file mode 100644 index 0000000000..6f300a9ab7 --- /dev/null +++ b/spring-mvc-basics-2/src/main/resources/mailMessages_fr_FR.properties @@ -0,0 +1,5 @@ +greetings=Bonjour {0}, +subscriptions=Voici vos différentes souscriptions sur notre forum : +regards=Cordialement, +unsubscribe=Se désinscrire de ces emails ici +signature={0} à Baeldung \ No newline at end of file diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/emails.jsp b/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/emails.jsp index 63351bbf3a..dafa71cbb0 100644 --- a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/emails.jsp +++ b/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/emails.jsp @@ -26,7 +26,7 @@ - + @@ -34,6 +34,11 @@ + + + + + diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/sendHtml.jsp b/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/sendHtml.jsp new file mode 100644 index 0000000000..f91a8826d1 --- /dev/null +++ b/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/sendHtml.jsp @@ -0,0 +1,73 @@ +<%-- + User: Benjamin CAURE + Date: 4/14/2020 +--%> +<%@ page pageEncoding="UTF-8" contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> + + + Send HTML Email + + +
+

Send Email Using Text Template

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Enter email address
+ +
+ Enter the recipient name
+ +
+ Enter the subject
+ +
+ +
+ Enter the sender name
+ +
+ Select the template engine
+ +
+ +
+
+
+
+
+ + diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/template-freemarker.ftl b/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/template-freemarker.ftl new file mode 100644 index 0000000000..066fc0302c --- /dev/null +++ b/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/template-freemarker.ftl @@ -0,0 +1,15 @@ + + + + + + +

Hi ${recipientName}

+

${text}

+

Regards,

+

+ ${senderName} at Baeldung
+ +

+ + diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/template-thymeleaf.html b/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/template-thymeleaf.html new file mode 100644 index 0000000000..b255b5dee5 --- /dev/null +++ b/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/template-thymeleaf.html @@ -0,0 +1,15 @@ + + + + + + +

+

+

+

+
+ +

+ + diff --git a/spring-mvc-basics-2/src/test/java/com/baeldung/SpringContextTest.java b/spring-mvc-basics-2/src/test/java/com/baeldung/SpringContextTest.java index ab0b23c4a5..5c276254d3 100644 --- a/spring-mvc-basics-2/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-mvc-basics-2/src/test/java/com/baeldung/SpringContextTest.java @@ -7,10 +7,11 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import com.baeldung.spring.configuration.ApplicationConfiguration; +import com.baeldung.spring.configuration.EmailConfiguration; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes={ApplicationConfiguration.class}) +@ContextConfiguration(classes={ApplicationConfiguration.class, EmailConfiguration.class}) @WebAppConfiguration public class SpringContextTest { diff --git a/spring-mvc-basics-2/src/test/java/com/baeldung/controller/rss/ArticleRssIntegrationTest.java b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/rss/ArticleRssIntegrationTest.java index fe7aeeb570..2ed70489c0 100644 --- a/spring-mvc-basics-2/src/test/java/com/baeldung/controller/rss/ArticleRssIntegrationTest.java +++ b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/rss/ArticleRssIntegrationTest.java @@ -1,6 +1,8 @@ package com.baeldung.controller.rss; import com.baeldung.spring.configuration.ApplicationConfiguration; +import com.baeldung.spring.configuration.EmailConfiguration; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -13,7 +15,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@SpringJUnitWebConfig(ApplicationConfiguration.class) +@SpringJUnitWebConfig(classes={ApplicationConfiguration.class, EmailConfiguration.class}) public class ArticleRssIntegrationTest { public static final String APPLICATION_RSS_XML = "application/rss+xml"; public static final String APPLICATION_RSS_JSON = "application/rss+json";