Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/init mail integration #68

Merged
merged 28 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
4442787
:sparkles: email-integration init mail lib
simonhir Aug 6, 2024
027a6c4
:sparkles: email-integration init core
simonhir Aug 6, 2024
874abe3
:art: email-integration-core format
simonhir Aug 6, 2024
b373571
:sparkles: email-integration init starter
simonhir Aug 6, 2024
89ec08e
:sparkles: email-integration add to pom
simonhir Aug 7, 2024
d1601ea
:recycle: email integrate s3 refactoring
simonhir Aug 13, 2024
e6408d1
:recycle: email rm digiwf relations
simonhir Aug 13, 2024
1609118
:memo: email init README
simonhir Aug 13, 2024
b7dc3ca
:fire: email core rm digiwf fileContext
simonhir Aug 13, 2024
217a25f
:sparkles: email integration init rest example
simonhir Aug 14, 2024
7f637d2
:sparkles: email integration init java example
simonhir Aug 14, 2024
46d9aaa
:recycle: email integration use list for paths instead of splitting
simonhir Aug 14, 2024
6809ae6
:recycle: email integration use list for paths instead of splitting
simonhir Aug 14, 2024
9038a34
:recycle: email integration rm Path naming
simonhir Aug 14, 2024
0953620
:memo: mail update README.md add properties examples
simonhir Aug 14, 2024
e5e3f3e
:bug: email core re add test file
simonhir Aug 14, 2024
54e47a3
Merge branch 'main' into feature/init-mail-integration
simonhir Aug 14, 2024
8affaa9
Merge branch 'refs/heads/main' into feature/init-mail-integration
simonhir Aug 16, 2024
80f2499
:recycle: integrations replace custom properties aliases with env vars
simonhir Aug 16, 2024
e978b87
Merge branch 'refs/heads/main' into feature/init-mail-integration
simonhir Sep 2, 2024
571dde2
:art: mail replace fqn with import
simonhir Sep 2, 2024
8a69c38
:art: mail rm digiwf from class name
simonhir Sep 2, 2024
edad1d3
:fire: mail rm default digiwf template footer
simonhir Sep 2, 2024
41b9358
:art: mail rm star imports
simonhir Sep 2, 2024
3dd327d
:recycle: mail make model classes record or not modifiable
simonhir Sep 2, 2024
9deb1f4
:recycle: mail make model classes record or not modifiable
simonhir Sep 2, 2024
0914811
:recycle: mail format spotless
simonhir Sep 2, 2024
761938b
:recycle: mail fix autowire syntax
simonhir Sep 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions refarch-integrations/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Collection of different integration which can be used as is in RefArch projects.

- [s3-integration](./refarch-s3-integration/README.md): For CRUD operations on a s3 storage. Also used for file handling
in other integrations.
- [email-integration](./refarch-email-integration/README.md): For sending text and html emails with attachments. Uses
s3-integration for file handling.

## Naming conventions

Expand Down
1 change: 1 addition & 0 deletions refarch-integrations/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

<modules>
<module>refarch-s3-integration</module>
<module>refarch-email-integration</module>
</modules>

<properties>
Expand Down
34 changes: 34 additions & 0 deletions refarch-integrations/refarch-email-integration/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# RefArch email integration

Integration for sending text and html emails with attachments. Uses [s3-integration](../refarch-s3-integration) for file
handling.

## Usage

```xml

<dependencies>
<dependency>
<groupId>de.muenchen.refarch</groupId>
<artifactId>refarch-email-integration-starter</artifactId>
<version>...</version>
</dependency>
</dependencies>
```

and a [s3-integration starter](../refarch-s3-integration/README.md#usage).

## Configuration

### refarch-email-integration-starter

| Property | Description | Example |
|-----------------------------------------|---------------------------------------------------|------------------------|
| `spring.mail.host` | Host of smtp server used for sending mails. | `mail.example.com` |
| `spring.mail.port` | Host of smtp server used for sending mails. | `1025` |
| `spring.mail.username` | Username of smtp server. | |
| `spring.mail.password` | Password of smtp server. | |
| `refarch.mail.from-address` | Default from address used when sending mails. | `test@example.com` |
| `refarch.mail.default-reply-to-address` | Default reply to address used when sending mails. | `no_reply@example.com` |

In addition, properties of selected [s3-integration starter](../refarch-s3-integration/README.md#usage).
30 changes: 30 additions & 0 deletions refarch-integrations/refarch-email-integration/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>de.muenchen.refarch</groupId>
<artifactId>refarch-integrations</artifactId>
<version>1.1.0-SNAPSHOT</version>
</parent>

<name>refarch-email-integration</name>
<artifactId>refarch-email-integration</artifactId>
<version>1.1.0-SNAPSHOT</version>
<packaging>pom</packaging>

<properties>
<jbig2-imageio.version>3.0.4</jbig2-imageio.version>
<jai-imageio-jpeg2000.version>1.4.0</jai-imageio-jpeg2000.version>
</properties>

<modules>
<module>refarch-email</module>
<module>refarch-email-integration-core</module>
<module>refarch-email-integration-starter</module>
<module>refarch-email-integration-rest-example</module>
<module>refarch-email-integration-java-example</module>
</modules>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>refarch-email-integration</artifactId>
<groupId>de.muenchen.refarch</groupId>
<version>1.1.0-SNAPSHOT</version>
</parent>

<artifactId>refarch-email-integration-core</artifactId>

<dependencies>
<dependency>
<groupId>de.muenchen.refarch</groupId>
<artifactId>refarch-s3-integration-client-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>de.muenchen.refarch</groupId>
<artifactId>refarch-email-starter</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>jbig2-imageio</artifactId>
<version>${jbig2-imageio.version}</version>
</dependency>
<dependency>
<groupId>com.github.jai-imageio</groupId>
<artifactId>jai-imageio-jpeg2000</artifactId>
<version>${jai-imageio-jpeg2000.version}</version>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package de.muenchen.refarch.email.integration.adapter.out.mail;

import de.muenchen.refarch.email.api.EmailApi;
import de.muenchen.refarch.email.integration.application.port.out.MailOutPort;
import de.muenchen.refarch.email.model.Mail;
import freemarker.template.TemplateException;
import jakarta.mail.MessagingException;
import java.io.IOException;
import java.util.Map;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
public class MailAdapter implements MailOutPort {

private final EmailApi emailApi;

@Override
public void sendMail(Mail mail, String logoPath) throws MessagingException {
this.emailApi.sendMail(mail, logoPath);
}

@Override
public String getBodyFromTemplate(String templateName, Map<String, Object> content) throws TemplateException, IOException {
return this.emailApi.getBodyFromTemplate(templateName, content);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package de.muenchen.refarch.email.integration.adapter.out.s3;

import de.muenchen.refarch.email.integration.application.port.out.LoadMailAttachmentOutPort;
import de.muenchen.refarch.email.integration.domain.exception.LoadAttachmentError;
import de.muenchen.refarch.email.model.FileAttachment;
import de.muenchen.refarch.integration.s3.client.exception.DocumentStorageClientErrorException;
import de.muenchen.refarch.integration.s3.client.exception.DocumentStorageException;
import de.muenchen.refarch.integration.s3.client.exception.DocumentStorageServerErrorException;
import de.muenchen.refarch.integration.s3.client.repository.DocumentStorageFileRepository;
import de.muenchen.refarch.integration.s3.client.repository.DocumentStorageFolderRepository;
import de.muenchen.refarch.integration.s3.client.service.FileValidationService;
import jakarta.mail.util.ByteArrayDataSource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;

@Slf4j
@RequiredArgsConstructor
public class S3Adapter implements LoadMailAttachmentOutPort {

private final DocumentStorageFileRepository documentStorageFileRepository;
private final DocumentStorageFolderRepository documentStorageFolderRepository;
private final FileValidationService fileValidationService;

@Override
public List<FileAttachment> loadAttachments(final List<String> filePaths) {
final List<FileAttachment> attachments = new ArrayList<>();
filePaths.forEach(path -> {
if (path.endsWith("/")) {
attachments.addAll(getFilesFromFolder(path));
} else {
attachments.add(getFile(path));
}
});
return attachments;
}

private List<FileAttachment> getFilesFromFolder(final String folderPath) {
try {
final List<FileAttachment> contents = new ArrayList<>();
final Set<String> filepath;
filepath = documentStorageFolderRepository.getAllFilesInFolderRecursively(folderPath);
if (Objects.isNull(filepath))
throw new LoadAttachmentError("An folder could not be loaded from url: " + folderPath);
filepath.forEach(file -> contents.add(getFile(file)));
return contents;
} catch (final DocumentStorageException | DocumentStorageServerErrorException | DocumentStorageClientErrorException e) {
throw new LoadAttachmentError("An folder could not be loaded from path: " + folderPath);
}
}

private FileAttachment getFile(final String filePath) {
try {
final byte[] bytes;
bytes = this.documentStorageFileRepository.getFile(filePath, 3);
final String mimeType = fileValidationService.detectFileType(bytes);
final String filename = FilenameUtils.getName(filePath);
final ByteArrayDataSource file = new ByteArrayDataSource(bytes, mimeType);

// check if mimeType exists
if (!fileValidationService.isSupported(mimeType))
throw new LoadAttachmentError("The type of this file is not supported: " + filePath);

return new FileAttachment(filename, file);
} catch (final DocumentStorageException | DocumentStorageServerErrorException | DocumentStorageClientErrorException e) {
throw new LoadAttachmentError("An file could not be loaded from path: " + filePath);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package de.muenchen.refarch.email.integration.application.port.in;

import de.muenchen.refarch.email.integration.domain.model.TemplateMail;
import de.muenchen.refarch.email.integration.domain.model.TextMail;
import jakarta.validation.Valid;

public interface SendMailInPort {

void sendMailWithText(@Valid final TextMail mail);

void sendMailWithTemplate(@Valid final TemplateMail mail);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package de.muenchen.refarch.email.integration.application.port.out;

import de.muenchen.refarch.email.model.FileAttachment;
import java.util.List;

public interface LoadMailAttachmentOutPort {
List<FileAttachment> loadAttachments(final List<String> filePaths);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package de.muenchen.refarch.email.integration.application.port.out;

import de.muenchen.refarch.email.model.Mail;
import freemarker.template.TemplateException;
import jakarta.mail.MessagingException;
import java.io.IOException;
import java.util.Map;

public interface MailOutPort {

void sendMail(Mail mail, String logoPath) throws MessagingException;

String getBodyFromTemplate(String templateName, Map<String, Object> content) throws TemplateException, IOException;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package de.muenchen.refarch.email.integration.application.usecase;

import de.muenchen.refarch.email.integration.application.port.in.SendMailInPort;
import de.muenchen.refarch.email.integration.application.port.out.LoadMailAttachmentOutPort;
import de.muenchen.refarch.email.integration.application.port.out.MailOutPort;
import de.muenchen.refarch.email.integration.domain.exception.TemplateError;
import de.muenchen.refarch.email.integration.domain.model.BasicMail;
import de.muenchen.refarch.email.integration.domain.model.TemplateMail;
import de.muenchen.refarch.email.integration.domain.model.TextMail;
import de.muenchen.refarch.email.model.FileAttachment;
import freemarker.template.TemplateException;
import jakarta.mail.MessagingException;
import jakarta.validation.Valid;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.mail.MailSendException;
import org.springframework.validation.annotation.Validated;

@Slf4j
@RequiredArgsConstructor
@Validated
public class SendMailUseCase implements SendMailInPort {

private final LoadMailAttachmentOutPort loadAttachmentOutPort;
private final MailOutPort mailOutPort;

/**
* Send a mail.
*
* @param mail mail that is sent
*/
@Override
public void sendMailWithText(@Valid final TextMail mail) {
de.muenchen.refarch.email.model.Mail mailModel = createMail(mail);
mailModel.setBody(mail.getBody());

this.sendMail(mailModel, null);
}

@Override
public void sendMailWithTemplate(@Valid final TemplateMail mail) throws TemplateError {
// get body from template
try {
Map<String, Object> content = new HashMap<>(mail.getContent());
content.put("footer", "DigiWF 2.0<br>IT-Referat der Stadt München");
String body = this.mailOutPort.getBodyFromTemplate(mail.getTemplate(), content);

de.muenchen.refarch.email.model.Mail mailModel = createMail(mail);
mailModel.setBody(body);
mailModel.setHtmlBody(true);

this.sendMail(mailModel, "templates/email-logo.png");

} catch (IOException ioException) {
throw new TemplateError("The template " + mail.getTemplate() + " could not be loaded");
} catch (TemplateException templateException) {
throw new TemplateError(templateException.getMessage());
}
}

private de.muenchen.refarch.email.model.Mail createMail(BasicMail mail) {
simonhir marked this conversation as resolved.
Show resolved Hide resolved
// load Attachments
List<FileAttachment> attachments = loadAttachmentOutPort.loadAttachments(mail.getFilePaths());

// send mail
return de.muenchen.refarch.email.model.Mail.builder()
.receivers(mail.getReceivers())
.subject(mail.getSubject())
.replyTo(mail.getReplyTo())
.receiversCc(mail.getReceiversCc())
.receiversBcc(mail.getReceiversBcc())
.attachments(attachments)
.build();
}

private void sendMail(de.muenchen.refarch.email.model.Mail mailModel, String logoPath) throws MailSendException {
simonhir marked this conversation as resolved.
Show resolved Hide resolved
try {
this.mailOutPort.sendMail(mailModel, logoPath);
} catch (final MessagingException ex) {
log.error("Sending mail failed with exception: {}", ex.getMessage());
throw new MailSendException(ex.getMessage());
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package de.muenchen.refarch.email.integration.domain.exception;

public class LoadAttachmentError extends Error {
public LoadAttachmentError(final String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package de.muenchen.refarch.email.integration.domain.exception;

public class TemplateError extends Error {
public TemplateError(final String message) {
super(message);
}
}
Loading