content = Map.of("data", "test");
+ Configuration configuration = new Configuration(Configuration.VERSION_2_3_30);
+ configuration.setClassForTemplateLoading(this.getClass(), "/templates/");
+ when(this.freeMarkerConfigurer.getConfiguration()).thenReturn(configuration);
+
+ final String result = this.emailApi.getBodyFromTemplate(templateName, content);
+
+ assertThat(result.contains("test")).isTrue();
+ }
+
+ @Test
+ void testGetEmailBodyFromTemplate() {
+ when(this.resourceLoader.getResource(anyString())).thenReturn(this.getResourceForText("This is a test mail", true));
+
+ final String templatePath = "bausteine/mail/email-logo.png";
+ final String result = this.emailApi.getEmailBodyFromTemplate(templatePath, Map.of());
+
+ assertThat(result).isEqualTo("This is a test mail");
+ }
+
+ @Test
+ void testGetEmailBodyFromTemplateWithContent() {
+ when(this.resourceLoader.getResource(anyString())).thenReturn(this.getResourceForText("This is a test mail with content", true));
+
+ final String templatePath = "bausteine/mail/email-logo.png";
+ final String result = this.emailApi.getEmailBodyFromTemplate(templatePath, Map.of("content", "some content"));
+
+ assertThat(result).isEqualTo("This is a test mail with some content");
+ }
+
+ @Test
+ void testGetEmailBodyFromTemplateWithContentAndNewLines() {
+ when(this.resourceLoader.getResource(anyString())).thenReturn(this.getResourceForText("This is a test mail with content", true));
+
+ final String templatePath = "bausteine/mail/email-logo.png";
+ final String result = this.emailApi.getEmailBodyFromTemplate(templatePath, Map.of("content", "some content \n with new line"));
+
+ assertThat(result).isEqualTo("This is a test mail with some content
with new line");
+ }
+
+ @Test
+ void testGetEmailBodyFromTemplateWithContentFailsIfTemplateDoesNotExist() {
+ when(this.resourceLoader.getResource(anyString())).thenReturn(this.getResourceForText("foo bar", false));
+
+ final String templatePath = "some/temlate/that/does/not/exist";
+ assertThatThrownBy(() -> {
+ this.emailApi.getEmailBodyFromTemplate(templatePath, Map.of("content", "some content"));
+ })
+ .isInstanceOf(RuntimeException.class)
+ .hasMessageContaining("Email Template not found: " + templatePath);
+ }
+
+ private Resource getResourceForText(final String text, final boolean resourceExists) {
+ return new Resource() {
+ @Override
+ public boolean exists() {
+ return resourceExists;
+ }
+
+ @Override
+ public URL getURL() throws IOException {
+ return null;
+ }
+
+ @Override
+ public URI getURI() throws IOException {
+ return null;
+ }
+
+ @Override
+ public File getFile() throws IOException {
+ return null;
+ }
+
+ @Override
+ public long contentLength() throws IOException {
+ return 0;
+ }
+
+ @Override
+ public long lastModified() throws IOException {
+ return 0;
+ }
+
+ @Override
+ public Resource createRelative(String relativePath) throws IOException {
+ return null;
+ }
+
+ @Override
+ public String getFilename() {
+ return "test.txt";
+ }
+
+ @Override
+ public String getDescription() {
+ return null;
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return new ByteArrayInputStream(text.getBytes());
+ }
+ };
+ }
+
+}
diff --git a/refarch-integrations/refarch-email-integration/refarch-email/refarch-email-api/src/test/resources/templates/test-template.ftl b/refarch-integrations/refarch-email-integration/refarch-email/refarch-email-api/src/test/resources/templates/test-template.ftl
new file mode 100644
index 00000000..1e47f8a2
--- /dev/null
+++ b/refarch-integrations/refarch-email-integration/refarch-email/refarch-email-api/src/test/resources/templates/test-template.ftl
@@ -0,0 +1,9 @@
+
+
+
+ Titel
+
+
+ Zweck dieser E-Mail ist ein ${data}
+
+
diff --git a/refarch-integrations/refarch-email-integration/refarch-email/refarch-email-starter/pom.xml b/refarch-integrations/refarch-email-integration/refarch-email/refarch-email-starter/pom.xml
new file mode 100644
index 00000000..9c2eb0bf
--- /dev/null
+++ b/refarch-integrations/refarch-email-integration/refarch-email/refarch-email-starter/pom.xml
@@ -0,0 +1,31 @@
+
+
+ 4.0.0
+
+ de.muenchen.refarch
+ refarch-email
+ 1.1.0-SNAPSHOT
+
+
+ refarch-email-starter
+
+
+
+ de.muenchen.refarch
+ refarch-email-api
+ ${project.version}
+
+
+ org.springframework.boot
+ spring-boot
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+
+
diff --git a/refarch-integrations/refarch-email-integration/refarch-email/refarch-email-starter/src/main/java/de/muenchen/refarch/email/configuration/EmailAutoConfiguration.java b/refarch-integrations/refarch-email-integration/refarch-email/refarch-email-starter/src/main/java/de/muenchen/refarch/email/configuration/EmailAutoConfiguration.java
new file mode 100644
index 00000000..976b08cd
--- /dev/null
+++ b/refarch-integrations/refarch-email-integration/refarch-email/refarch-email-starter/src/main/java/de/muenchen/refarch/email/configuration/EmailAutoConfiguration.java
@@ -0,0 +1,63 @@
+package de.muenchen.refarch.email.configuration;
+
+import de.muenchen.refarch.email.api.EmailApi;
+import de.muenchen.refarch.email.impl.EmailApiImpl;
+import de.muenchen.refarch.email.properties.CustomMailProperties;
+import jakarta.mail.MessagingException;
+import java.util.Properties;
+import lombok.RequiredArgsConstructor;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.mail.MailProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.JavaMailSenderImpl;
+import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
+
+@RequiredArgsConstructor
+@EnableConfigurationProperties({ MailProperties.class, CustomMailProperties.class })
+public class EmailAutoConfiguration {
+
+ private final MailProperties mailProperties;
+ private final CustomMailProperties customMailProperties;
+
+ /**
+ * Configures the {@link JavaMailSender}
+ *
+ * @return configured JavaMailSender
+ */
+ @Bean
+ @ConditionalOnMissingBean
+ public JavaMailSender getJavaMailSender() throws MessagingException {
+ final JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
+ mailSender.setHost(this.mailProperties.getHost());
+ mailSender.setPort(this.mailProperties.getPort());
+ mailSender.setProtocol(this.mailProperties.getProtocol());
+ mailSender.setUsername(this.mailProperties.getUsername());
+ mailSender.setPassword(this.mailProperties.getPassword());
+
+ final Properties props = mailSender.getJavaMailProperties();
+ props.putAll(this.mailProperties.getProperties());
+ mailSender.setJavaMailProperties(props);
+ mailSender.testConnection();
+ return mailSender;
+ }
+
+ @ConditionalOnMissingBean
+ @Bean
+ public EmailApi emailApi(final ResourceLoader resourceLoader, final JavaMailSender javaMailSender,
+ final FreeMarkerConfigurer freeMarkerConfigurer) {
+ return new EmailApiImpl(javaMailSender, resourceLoader, freeMarkerConfigurer, this.customMailProperties.getFromAddress(),
+ this.customMailProperties.getDefaultReplyToAddress());
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public FreeMarkerConfigurer freemarkerConfig() {
+ FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
+ freeMarkerConfigurer.setTemplateLoaderPath("classpath:templates/");
+ return freeMarkerConfigurer;
+ }
+
+}
diff --git a/refarch-integrations/refarch-email-integration/refarch-email/refarch-email-starter/src/main/java/de/muenchen/refarch/email/properties/CustomMailProperties.java b/refarch-integrations/refarch-email-integration/refarch-email/refarch-email-starter/src/main/java/de/muenchen/refarch/email/properties/CustomMailProperties.java
new file mode 100644
index 00000000..af903421
--- /dev/null
+++ b/refarch-integrations/refarch-email-integration/refarch-email/refarch-email-starter/src/main/java/de/muenchen/refarch/email/properties/CustomMailProperties.java
@@ -0,0 +1,20 @@
+package de.muenchen.refarch.email.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@Data
+@ConfigurationProperties(prefix = "refarch.mail")
+public class CustomMailProperties {
+
+ /**
+ * Sender mail address.
+ */
+ private String fromAddress;
+
+ /**
+ * Default Reply-to mail address, e.g. no-reply@domain
+ */
+ private String defaultReplyToAddress;
+
+}
diff --git a/refarch-integrations/refarch-email-integration/refarch-email/refarch-email-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/refarch-integrations/refarch-email-integration/refarch-email/refarch-email-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 00000000..e67a5bac
--- /dev/null
+++ b/refarch-integrations/refarch-email-integration/refarch-email/refarch-email-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+de.muenchen.refarch.email.configuration.EmailAutoConfiguration