diff --git a/digiwf-coverage/pom.xml b/digiwf-coverage/pom.xml index a4bf9b5109..48434769cd 100644 --- a/digiwf-coverage/pom.xml +++ b/digiwf-coverage/pom.xml @@ -159,6 +159,11 @@ digiwf-dms-integration-service ${project.version} + + de.muenchen.oss.digiwf + digiwf-email-api + ${project.version} + diff --git a/digiwf-libs/digiwf-email/digiwf-email-api/pom.xml b/digiwf-libs/digiwf-email/digiwf-email-api/pom.xml new file mode 100644 index 0000000000..4abdbba3d0 --- /dev/null +++ b/digiwf-libs/digiwf-email/digiwf-email-api/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + de.muenchen.oss.digiwf + digiwf-email + 1.3.0-SNAPSHOT + + + digiwf-email-api + + + + org.springframework.boot + spring-boot-starter-mail + + + org.apache.commons + commons-lang3 + + + + + org.junit.jupiter + junit-jupiter-api + test + + + org.mockito + mockito-core + test + + + org.mockito + mockito-junit-jupiter + test + + + + diff --git a/digiwf-libs/digiwf-email/digiwf-email-api/src/main/java/de/muenchen/oss/digiwf/email/api/DigiwfEmailApi.java b/digiwf-libs/digiwf-email/digiwf-email-api/src/main/java/de/muenchen/oss/digiwf/email/api/DigiwfEmailApi.java new file mode 100644 index 0000000000..2be10864cf --- /dev/null +++ b/digiwf-libs/digiwf-email/digiwf-email-api/src/main/java/de/muenchen/oss/digiwf/email/api/DigiwfEmailApi.java @@ -0,0 +1,19 @@ +package de.muenchen.oss.digiwf.email.api; + +import de.muenchen.oss.digiwf.email.model.FileAttachment; +import jakarta.mail.MessagingException; + +import java.util.List; + +public interface DigiwfEmailApi { + + + void sendMail(String receivers, String subject, String body, String replyTo) throws MessagingException; + + void sendMail(String receivers, String subject, String body, String replyTo, String receiversCc, String receiversBcc) throws MessagingException; + + void sendMailWithAttachments(String receivers, String subject, String body, String replyTo, List attachments) throws MessagingException; + + void sendMailWithAttachments(String receivers, String subject, String body, String replyTo, String receiversCc, String receiversBcc, List attachments) throws MessagingException; + +} diff --git a/digiwf-libs/digiwf-email/digiwf-email-api/src/main/java/de/muenchen/oss/digiwf/email/impl/DigiwfEmailApiImpl.java b/digiwf-libs/digiwf-email/digiwf-email-api/src/main/java/de/muenchen/oss/digiwf/email/impl/DigiwfEmailApiImpl.java new file mode 100644 index 0000000000..fe62069607 --- /dev/null +++ b/digiwf-libs/digiwf-email/digiwf-email-api/src/main/java/de/muenchen/oss/digiwf/email/impl/DigiwfEmailApiImpl.java @@ -0,0 +1,74 @@ +package de.muenchen.oss.digiwf.email.impl; + +import de.muenchen.oss.digiwf.email.api.DigiwfEmailApi; +import de.muenchen.oss.digiwf.email.model.FileAttachment; +import jakarta.mail.Message; +import jakarta.mail.MessagingException; +import jakarta.mail.internet.InternetAddress; +import jakarta.mail.internet.MimeMessage; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import lombok.val; +import org.apache.commons.lang3.StringUtils; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; + +import java.util.List; + +@Slf4j +@RequiredArgsConstructor +public class DigiwfEmailApiImpl implements DigiwfEmailApi { + + private final JavaMailSender mailSender; + private final String fromAddress; + + @Override + public void sendMail(String receivers, String subject, String body, String replyTo) throws MessagingException { + this.sendMailWithAttachments(receivers, subject, body, replyTo, null, null, List.of()); + } + + @Override + public void sendMail(String receivers, String subject, String body, String replyTo, String receiversCc, String receiversBcc) throws MessagingException { + this.sendMailWithAttachments(receivers, subject, body, replyTo, receiversCc, receiversBcc, List.of()); + } + + @Override + public void sendMailWithAttachments(String receivers, String subject, String body, String replyTo, List attachments) throws MessagingException { + this.sendMailWithAttachments(receivers, subject, body, replyTo, null, null, attachments); + } + + @Override + public void sendMailWithAttachments(String receivers, String subject, String body, String replyTo, String receiversCc, String receiversBcc, List attachments) throws MessagingException { + final MimeMessage mimeMessage = this.mailSender.createMimeMessage(); + + mimeMessage.setRecipients(Message.RecipientType.TO, InternetAddress.parse(receivers)); + + if (StringUtils.isNotEmpty(receiversCc)) { + mimeMessage.setRecipients(Message.RecipientType.CC, InternetAddress.parse(receiversCc)); + } + if (StringUtils.isNotEmpty(receiversCc)) { + mimeMessage.setRecipients(Message.RecipientType.BCC, InternetAddress.parse(receiversBcc)); + } + + final var helper = new MimeMessageHelper(mimeMessage, true); + + helper.setSubject(subject); + helper.setText(subject); + helper.setFrom(this.fromAddress); + + if (StringUtils.isNotBlank(replyTo)) { + helper.setReplyTo(replyTo); + } + + // mail attachments + if (attachments != null) { + for (val attachment : attachments) { + helper.addAttachment(attachment.getFileName(), attachment.getFile()); + } + } + + this.mailSender.send(mimeMessage); + log.info("Mail {} sent to {}.", subject, receivers); + } + +} diff --git a/digiwf-libs/digiwf-email/digiwf-email-api/src/main/java/de/muenchen/oss/digiwf/email/model/FileAttachment.java b/digiwf-libs/digiwf-email/digiwf-email-api/src/main/java/de/muenchen/oss/digiwf/email/model/FileAttachment.java new file mode 100644 index 0000000000..f5a319002e --- /dev/null +++ b/digiwf-libs/digiwf-email/digiwf-email-api/src/main/java/de/muenchen/oss/digiwf/email/model/FileAttachment.java @@ -0,0 +1,17 @@ +package de.muenchen.oss.digiwf.email.model; + +import jakarta.mail.util.ByteArrayDataSource; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.RequiredArgsConstructor; + +@Data +@RequiredArgsConstructor +@AllArgsConstructor +public class FileAttachment { + + private String fileName; + + private ByteArrayDataSource file; + +} diff --git a/digiwf-libs/digiwf-email/digiwf-email-api/src/test/java/de/muenchen/oss/digiwf/email/DigiwfEmailApiImplTest.java b/digiwf-libs/digiwf-email/digiwf-email-api/src/test/java/de/muenchen/oss/digiwf/email/DigiwfEmailApiImplTest.java new file mode 100644 index 0000000000..b7373669d7 --- /dev/null +++ b/digiwf-libs/digiwf-email/digiwf-email-api/src/test/java/de/muenchen/oss/digiwf/email/DigiwfEmailApiImplTest.java @@ -0,0 +1,95 @@ +package de.muenchen.oss.digiwf.email; + +import de.muenchen.oss.digiwf.email.api.DigiwfEmailApi; +import de.muenchen.oss.digiwf.email.impl.DigiwfEmailApiImpl; +import de.muenchen.oss.digiwf.email.model.FileAttachment; +import jakarta.mail.MessagingException; +import jakarta.mail.Session; +import jakarta.mail.internet.MimeMessage; +import jakarta.mail.util.ByteArrayDataSource; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.springframework.mail.javamail.JavaMailSender; + +import java.util.List; + +import static org.mockito.Mockito.*; + +class DigiwfEmailApiImplTest { + + + private final JavaMailSender javaMailSender = mock(JavaMailSender.class); + private DigiwfEmailApi digiwfEmailApi; + + // test data + private final String receiver = "mailReceiver1@muenchen.de,mailReceiver2@muenchen.de"; + private final String receiverCC = "receiverCC@muenchen.de"; + private final String receiverBCC = "receiverBCC@muenchen.de"; + private final String subject = "Test Mail"; + private final String body = "This is a test mail"; + private final String replyTo = "digiwf@muenchen.de"; + + + @BeforeEach + void setUp() { + when(this.javaMailSender.createMimeMessage()).thenReturn(new MimeMessage((Session) null)); + this.digiwfEmailApi = new DigiwfEmailApiImpl(this.javaMailSender, "digiwf@muenchen.de"); + } + + @Test + void sendSimpleMail() throws MessagingException { + this.digiwfEmailApi.sendMail(this.receiver, this.subject, this.body, this.replyTo); + + final ArgumentCaptor messageArgumentCaptor = ArgumentCaptor.forClass(MimeMessage.class); + verify(this.javaMailSender).send(messageArgumentCaptor.capture()); + + Assertions.assertEquals(2, messageArgumentCaptor.getValue().getAllRecipients().length); + Assertions.assertEquals(1, messageArgumentCaptor.getValue().getReplyTo().length); + Assertions.assertEquals(this.subject, messageArgumentCaptor.getValue().getSubject()); + } + + @Test + void sendMailWithCCAndBCC() throws MessagingException { + this.digiwfEmailApi.sendMail(this.receiver, this.subject, this.body, this.replyTo, this.receiverCC, this.receiverBCC); + + final ArgumentCaptor messageArgumentCaptor = ArgumentCaptor.forClass(MimeMessage.class); + verify(this.javaMailSender).send(messageArgumentCaptor.capture()); + + Assertions.assertEquals(4, messageArgumentCaptor.getValue().getAllRecipients().length); + Assertions.assertEquals(1, messageArgumentCaptor.getValue().getReplyTo().length); + Assertions.assertEquals(this.subject, messageArgumentCaptor.getValue().getSubject()); + } + + @Test + void sendMailWithAttachments() throws MessagingException { + final List fileAttachments = List.of( + new FileAttachment("Testanhang", new ByteArrayDataSource("FooBar".getBytes(), "text/plain")) + ); + this.digiwfEmailApi.sendMailWithAttachments(this.receiver, this.subject, this.body, this.replyTo, fileAttachments); + + final ArgumentCaptor messageArgumentCaptor = ArgumentCaptor.forClass(MimeMessage.class); + verify(this.javaMailSender).send(messageArgumentCaptor.capture()); + + Assertions.assertEquals(2, messageArgumentCaptor.getValue().getAllRecipients().length); + Assertions.assertEquals(1, messageArgumentCaptor.getValue().getReplyTo().length); + Assertions.assertEquals(this.subject, messageArgumentCaptor.getValue().getSubject()); + } + + @Test + void sendMailWithReceiversCCAndBCCAndAttachments() throws MessagingException { + final List fileAttachments = List.of( + new FileAttachment("Testanhang", new ByteArrayDataSource("FooBar".getBytes(), "text/plain")) + ); + this.digiwfEmailApi.sendMailWithAttachments(this.receiver, this.subject, this.body, this.replyTo, this.receiverCC, this.receiverBCC, fileAttachments); + + final ArgumentCaptor messageArgumentCaptor = ArgumentCaptor.forClass(MimeMessage.class); + verify(this.javaMailSender).send(messageArgumentCaptor.capture()); + + Assertions.assertEquals(4, messageArgumentCaptor.getValue().getAllRecipients().length); + Assertions.assertEquals(1, messageArgumentCaptor.getValue().getReplyTo().length); + Assertions.assertEquals(this.subject, messageArgumentCaptor.getValue().getSubject()); + } + +} diff --git a/digiwf-libs/digiwf-email/digiwf-email-starter/pom.xml b/digiwf-libs/digiwf-email/digiwf-email-starter/pom.xml new file mode 100644 index 0000000000..94eae7e419 --- /dev/null +++ b/digiwf-libs/digiwf-email/digiwf-email-starter/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + de.muenchen.oss.digiwf + digiwf-email + 1.3.0-SNAPSHOT + + + digiwf-email-starter + + + + de.muenchen.oss.digiwf + digiwf-email-api + ${project.version} + + + org.springframework.boot + spring-boot + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + diff --git a/digiwf-libs/digiwf-email/digiwf-email-starter/src/main/java/de/muenchen/oss/digiwf/email/configuration/DigiwfEmailAutoConfiguration.java b/digiwf-libs/digiwf-email/digiwf-email-starter/src/main/java/de/muenchen/oss/digiwf/email/configuration/DigiwfEmailAutoConfiguration.java new file mode 100644 index 0000000000..9e5e443ec0 --- /dev/null +++ b/digiwf-libs/digiwf-email/digiwf-email-starter/src/main/java/de/muenchen/oss/digiwf/email/configuration/DigiwfEmailAutoConfiguration.java @@ -0,0 +1,24 @@ +package de.muenchen.oss.digiwf.email.configuration; + +import de.muenchen.oss.digiwf.email.api.DigiwfEmailApi; +import de.muenchen.oss.digiwf.email.impl.DigiwfEmailApiImpl; +import de.muenchen.oss.digiwf.email.properties.CustomMailProperties; +import lombok.RequiredArgsConstructor; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.mail.javamail.JavaMailSender; + +@RequiredArgsConstructor +@EnableConfigurationProperties(value = CustomMailProperties.class) +public class DigiwfEmailAutoConfiguration { + + private final CustomMailProperties customMailProperties; + + @ConditionalOnMissingBean + @Bean + public DigiwfEmailApi digiwfEmailApi(final JavaMailSender javaMailSender) { + return new DigiwfEmailApiImpl(javaMailSender, this.customMailProperties.getFromAddress()); + } + +} diff --git a/digiwf-libs/digiwf-email/digiwf-email-starter/src/main/java/de/muenchen/oss/digiwf/email/properties/CustomMailProperties.java b/digiwf-libs/digiwf-email/digiwf-email-starter/src/main/java/de/muenchen/oss/digiwf/email/properties/CustomMailProperties.java new file mode 100644 index 0000000000..050d401ee5 --- /dev/null +++ b/digiwf-libs/digiwf-email/digiwf-email-starter/src/main/java/de/muenchen/oss/digiwf/email/properties/CustomMailProperties.java @@ -0,0 +1,15 @@ +package de.muenchen.oss.digiwf.email.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Data +@ConfigurationProperties(prefix = "io.muenchendigital.digiwf.mail") +public class CustomMailProperties { + + /** + * Sender mail address. + */ + private String fromAddress; + +} diff --git a/digiwf-libs/digiwf-email/digiwf-email-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/digiwf-libs/digiwf-email/digiwf-email-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000000..4be2bbc01a --- /dev/null +++ b/digiwf-libs/digiwf-email/digiwf-email-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +de.muenchen.oss.digiwf.email.configuration.DigiwfEmailAutoConfiguration diff --git a/digiwf-libs/digiwf-email/pom.xml b/digiwf-libs/digiwf-email/pom.xml new file mode 100644 index 0000000000..923f8d31c2 --- /dev/null +++ b/digiwf-libs/digiwf-email/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + + de.muenchen.oss.digiwf + digiwf-libs + 1.3.0-SNAPSHOT + + + digiwf-email + pom + + + digiwf-email-api + digiwf-email-starter + + + diff --git a/digiwf-libs/pom.xml b/digiwf-libs/pom.xml index e00468c78d..abd1c0beb4 100644 --- a/digiwf-libs/pom.xml +++ b/digiwf-libs/pom.xml @@ -24,6 +24,7 @@ digiwf-message digiwf-spring-security digiwf-spring-logging-and-tracing + digiwf-email