diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/EmailConfiguration.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/EmailConfiguration.java new file mode 100644 index 000000000..0c6e76aa9 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/EmailConfiguration.java @@ -0,0 +1,91 @@ +package edu.internet2.tier.shibboleth.admin.ui.configuration; + +import edu.internet2.tier.shibboleth.admin.ui.service.EmailService; +import edu.internet2.tier.shibboleth.admin.ui.service.EmailServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.ResourceBundleMessageSource; +import org.springframework.mail.javamail.JavaMailSender; +import org.thymeleaf.TemplateEngine; +import org.thymeleaf.spring5.SpringTemplateEngine; +import org.thymeleaf.templatemode.TemplateMode; +import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver; +import org.thymeleaf.templateresolver.ITemplateResolver; + +import java.util.Collections; + +/** + * @author Bill Smith (wsmith@unicon.net) + */ +@Configuration +public class EmailConfiguration { + + private static final String EMAIL_TEMPLATE_ENCODING = "UTF-8"; + + @Value("${shibui.text.email.template.path.prefix:/mail/text/}") + private String textEmailTemplatePathPrefix; + + @Value("${shibui.html.email.template.path.prefix:/mail/html/}") + private String htmlEmailTemplatePathPrefix; + + @Autowired + private ApplicationContext applicationContext; + + @Autowired + private JavaMailSender javaMailSender; + + @Bean + public ResourceBundleMessageSource emailMessageSource() { + final ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); + messageSource.setBasename("mail/mailMessages"); + return messageSource; + } + + @Bean + public TemplateEngine textEmailTemplateEngine() { + final SpringTemplateEngine templateEngine = new SpringTemplateEngine(); + templateEngine.addTemplateResolver(textTemplateResolver()); + templateEngine.setTemplateEngineMessageSource(emailMessageSource()); + return templateEngine; + } + + @Bean + public TemplateEngine htmlEmailTemplateEngine() { + final SpringTemplateEngine templateEngine = new SpringTemplateEngine(); + templateEngine.addTemplateResolver(htmlTemplateResolver()); + templateEngine.setTemplateEngineMessageSource(emailMessageSource()); + return templateEngine; + } + + private ITemplateResolver textTemplateResolver() { + final ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver(); + templateResolver.setOrder(1); + templateResolver.setResolvablePatterns(Collections.singleton("*")); + templateResolver.setPrefix(textEmailTemplatePathPrefix); + templateResolver.setSuffix(".txt"); + templateResolver.setTemplateMode(TemplateMode.TEXT); + templateResolver.setCharacterEncoding(EMAIL_TEMPLATE_ENCODING); + templateResolver.setCacheable(false); + return templateResolver; + } + + private ITemplateResolver htmlTemplateResolver() { + final ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver(); + templateResolver.setOrder(1); + templateResolver.setResolvablePatterns(Collections.singleton("*")); + templateResolver.setPrefix(htmlEmailTemplatePathPrefix); + templateResolver.setSuffix(".html"); + templateResolver.setTemplateMode(TemplateMode.HTML); + templateResolver.setCharacterEncoding(EMAIL_TEMPLATE_ENCODING); + templateResolver.setCacheable(false); + return templateResolver; + } + + @Bean + public EmailService emailService() { + return new EmailServiceImpl(javaMailSender, emailMessageSource(), textEmailTemplateEngine(), htmlEmailTemplateEngine()); + } +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EmailService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EmailService.java new file mode 100644 index 000000000..2b76360ae --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EmailService.java @@ -0,0 +1,11 @@ +package edu.internet2.tier.shibboleth.admin.ui.service; + +import javax.mail.MessagingException; +import java.util.Locale; + +/** + * @author Bill Smith (wsmith@unicon.net) + */ +public interface EmailService { + void sendMail(String emailTemplate, String fromAddress, String recipient, String subject, Locale locale) throws MessagingException; +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EmailServiceImpl.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EmailServiceImpl.java new file mode 100644 index 000000000..9bdc1fc15 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EmailServiceImpl.java @@ -0,0 +1,53 @@ +package edu.internet2.tier.shibboleth.admin.ui.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.support.ResourceBundleMessageSource; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.thymeleaf.TemplateEngine; +import org.thymeleaf.context.Context; + +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; +import java.util.Locale; + +/** + * @author Bill Smith (wsmith@unicon.net) + */ +public class EmailServiceImpl implements EmailService { + private static final Logger logger = LoggerFactory.getLogger(EmailServiceImpl.class); + + private JavaMailSender emailSender; + private ResourceBundleMessageSource emailMessageSource; + private TemplateEngine textEmailTemplateEngine; + private TemplateEngine htmlEmailTemplateEngine; + + public EmailServiceImpl(JavaMailSender emailSender, + ResourceBundleMessageSource emailMessageSource, + TemplateEngine textEmailTemplateEngine, + TemplateEngine htmlEmailTemplateEngine) { + this.emailSender = emailSender; + this.emailMessageSource = emailMessageSource; + this.textEmailTemplateEngine = textEmailTemplateEngine; + this.htmlEmailTemplateEngine = htmlEmailTemplateEngine; + } + + public void sendMail(String emailTemplate, String fromAddress, String recipient, String subject, Locale locale) throws MessagingException { + Context context = new Context(locale); + // TODO: set things to be replaced in the email template here + + MimeMessage mimeMessage = this.emailSender.createMimeMessage(); + MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true,"UTF-8"); + message.setSubject(subject); + message.setFrom(fromAddress); + message.setTo(recipient); + + String textContent = textEmailTemplateEngine.process(emailTemplate, context); + String htmlContent = htmlEmailTemplateEngine.process(emailTemplate, context); + message.setText(textContent, htmlContent); + + // TODO: Uncomment when we're ready to actually send emails + // emailSender.send(mimeMessage); + } +} diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 81a0d09dd..113cc8e92 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -65,3 +65,11 @@ shibui.nameid-filter-ui-schema-location=classpath:nameid-filter.schema.json # Set the following property to periodically write out metadata providers configuration. There is no default value; the following is just an example # shibui.metadataProviders.target=file:/opt/shibboleth-idp/conf/shibui-metadata-providers.xml # shibui.metadataProviders.taskRunRate=30000 + +# Email configuration +spring.mail.host=localhost +spring.mail.port=25 +spring.mail.username=username +spring.mail.password=password +spring.mail.properties.mail.smtp.auth=true +spring.mail.properties.mail.smtp.starttls.enable=true \ No newline at end of file diff --git a/backend/src/main/resources/mail/html/test.html b/backend/src/main/resources/mail/html/test.html new file mode 100644 index 000000000..db4472ad1 --- /dev/null +++ b/backend/src/main/resources/mail/html/test.html @@ -0,0 +1,4 @@ + + This is a test! + This is a test email template. Can't you tell? + \ No newline at end of file diff --git a/backend/src/main/resources/mail/text/test.txt b/backend/src/main/resources/mail/text/test.txt new file mode 100644 index 000000000..55781c52c --- /dev/null +++ b/backend/src/main/resources/mail/text/test.txt @@ -0,0 +1 @@ +This is a test email template. Can't you tell? \ No newline at end of file