Skip to content

Commit

Permalink
[SELC-5163] Added sendMail method and configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
flaminiaScarciofolo committed Jul 6, 2024
1 parent 776a43e commit 214add8
Show file tree
Hide file tree
Showing 18 changed files with 515 additions and 3 deletions.
28 changes: 27 additions & 1 deletion apps/institution-send-mail-scheduler/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<quarkus.platform.version>3.11.3</quarkus.platform.version>
<skipITs>true</skipITs>
<surefire-plugin.version>3.1.2</surefire-plugin.version>
<onboarding-sdk.version>0.1.14</onboarding-sdk.version>
<quarkus-openapi-generator.version>2.4.2</quarkus-openapi-generator.version>
</properties>
<dependencyManagement>
Expand Down Expand Up @@ -94,9 +95,34 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-health</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-client-reactive-jackson</artifactId>
<artifactId>quarkus-mailer</artifactId>
</dependency>
<dependency>
<groupId>it.pagopa.selfcare</groupId>
<artifactId>onboarding-sdk-azure-storage</artifactId>
<version>${onboarding-sdk.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>it.pagopa.selfcare</groupId>
<artifactId>onboarding-sdk-common</artifactId>
<version>${onboarding-sdk.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package it.pagopa.selfcare.institution.config;

import io.smallrye.config.ConfigMapping;

@ConfigMapping(prefix = "institution-send-mail.blob-storage")
public interface AzureStorageConfig {

String connectionStringContract();
String containerContract();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package it.pagopa.selfcare.institution.config;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import io.quarkus.runtime.StartupEvent;
import io.vertx.core.impl.logging.Logger;
import io.vertx.core.impl.logging.LoggerFactory;
import io.vertx.core.json.jackson.DatabindCodec;
import it.pagopa.selfcare.azurestorage.AzureBlobClient;
import it.pagopa.selfcare.azurestorage.AzureBlobClientDefault;
import it.pagopa.selfcare.institution.repository.PecNotificationsRepository;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
import jakarta.enterprise.inject.Produces;

@ApplicationScoped
public class InstitutionSendMailConfig {

private static final Logger log = LoggerFactory.getLogger(InstitutionSendMailConfig.class);

void onStart(@Observes StartupEvent ev, PecNotificationsRepository repository) {
log.info(String.format("Database %s is starting...", repository.mongoDatabase().getName()));
}

@Produces
public ObjectMapper objectMapper(){
ObjectMapper mapper = DatabindCodec.mapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);// custom config
mapper.registerModule(new JavaTimeModule()); // custom config
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // custom config
return mapper;
}

@ApplicationScoped
public AzureBlobClient azureBobClientContract(AzureStorageConfig azureStorageConfig){
return new AzureBlobClientDefault(azureStorageConfig.connectionStringContract(), azureStorageConfig.containerContract());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package it.pagopa.selfcare.institution.config;

import io.smallrye.config.ConfigMapping;

@ConfigMapping(prefix = "onboarding-functions.mail-template.path.onboarding")
public interface MailTemplatePathConfig {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package it.pagopa.selfcare.institution.config;

import io.smallrye.config.ConfigMapping;

@ConfigMapping(prefix = "onboarding-functions.mail-template.placeholders.onboarding")
public interface MailTemplatePlaceholdersConfig {


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package it.pagopa.selfcare.institution.entity;

import io.quarkus.mongodb.panache.common.MongoEntity;
import org.bson.codecs.pojo.annotations.BsonId;
import org.bson.types.ObjectId;

@MongoEntity(collection="pecNotification")
public class PecNotification {
@BsonId
private ObjectId id;
private Integer moduleDayOfTheEpoch;
private String productId;
private String institutionId;

public ObjectId getId() {
return id;
}

public void setId(ObjectId id) {
this.id = id;
}

public Integer getModuleDayOfTheEpoch() {
return moduleDayOfTheEpoch;
}

public void setModuleDayOfTheEpoch(Integer moduleDayOfTheEpoch) {
this.moduleDayOfTheEpoch = moduleDayOfTheEpoch;
}

public String getProductId() {
return productId;
}

public void setProductId(String productId) {
this.productId = productId;
}

public String getInstitutionId() {
return institutionId;
}

public void setInstitutionId(String institutionId) {
this.institutionId = institutionId;
}

@Override
public String toString() {
return "PecNotification{" +
"id=" + id +
", moduleDayOfTheEpoch=" + moduleDayOfTheEpoch +
", productId='" + productId + '\'' +
", institutionId='" + institutionId + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package it.pagopa.selfcare.institution.exception;

public class GenericException extends RuntimeException {

private final String code;

public GenericException(String message, String code) {
super(message);
this.code = code;
}

public GenericException(String message) {
super(message);
this.code = "0000";
}

public String getCode() {
return code;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package it.pagopa.selfcare.institution.model;

public class FileMailData {
byte[] data;
String name;
String contentType;

public FileMailData() {
}

public FileMailData(byte[] data, String name, String contentType) {
this.data = data;
this.name = name;
this.contentType = contentType;
}

public byte[] getData() {
return data;
}

public void setData(byte[] data) {
this.data = data;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getContentType() {
return contentType;
}

public void setContentType(String contentType) {
this.contentType = contentType;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package it.pagopa.selfcare.institution.model;


import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class MailTemplate {
private String subject;
private String body;

public String getSubject() {
return new String(Base64.getDecoder().decode(subject), StandardCharsets.UTF_8);
}

public String getBody() {
return new String(Base64.getDecoder().decode(body), StandardCharsets.UTF_8);
}

public void setBody(String body) {
this.body = body;
}

public void setSubject(String subject) {
this.subject = subject;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package it.pagopa.selfcare.institution.repository;

import io.quarkus.mongodb.panache.PanacheMongoRepositoryBase;
import it.pagopa.selfcare.institution.entity.PecNotification;
import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class PecNotificationsRepository implements PanacheMongoRepositoryBase<PecNotification, String> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package it.pagopa.selfcare.institution.service;

import it.pagopa.selfcare.institution.model.FileMailData;

import java.util.List;
import java.util.Map;

public interface MailService {

void sendMailWithFile(List<String> destinationMail, String templateName, Map<String, String> mailParameters, String prefixSubject, FileMailData fileMailData);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package it.pagopa.selfcare.institution.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.quarkus.mailer.Mail;
import io.quarkus.mailer.Mailer;
import io.vertx.core.impl.logging.Logger;
import io.vertx.core.impl.logging.LoggerFactory;
import it.pagopa.selfcare.azurestorage.AzureBlobClient;
import it.pagopa.selfcare.institution.exception.GenericException;
import it.pagopa.selfcare.institution.model.FileMailData;
import it.pagopa.selfcare.institution.model.MailTemplate;
import jakarta.enterprise.context.ApplicationScoped;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.apache.commons.text.StringSubstitutor;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

@ApplicationScoped
public class MailServiceImpl implements MailService{

private static final String ERROR_DURING_SEND_MAIL = "Error during send mail";

private static final Logger log = LoggerFactory.getLogger(MailServiceImpl.class);
private final AzureBlobClient azureBlobClient;
private final ObjectMapper objectMapper;
private final String senderMail;
private final Boolean destinationMailTest;
private final String destinationMailTestAddress;
private final Mailer mailer;

public MailServiceImpl(AzureBlobClient azureBlobClient,
ObjectMapper objectMapper,
@ConfigProperty(name = "institution-send-mail.sender-mail") String senderMail,
@ConfigProperty(name = "institution-send-mail.destination-mail")Boolean destinationMailTest,
@ConfigProperty(name = "institution-send-mail.destination-mail-test-address") String destinationMailTestAddress,
Mailer mailer) {
this.azureBlobClient = azureBlobClient;
this.objectMapper = objectMapper;
this.senderMail = senderMail;
this.destinationMailTest = destinationMailTest;
this.destinationMailTestAddress = destinationMailTestAddress;
this.mailer = mailer;
}

@Override
public void sendMailWithFile(List<String> destinationMail, String templateName, Map<String, String> mailParameters, String prefixSubject, FileMailData fileMailData) {
try {

// Dev mode send mail to test digital address
String destination = destinationMailTest
? destinationMailTestAddress
: destinationMail.get(0);

log.info(String.format("Sending mail to %s, with prefixSubject %s", destination, prefixSubject));
String template = azureBlobClient.getFileAsText(templateName);
MailTemplate mailTemplate = objectMapper.readValue(template, MailTemplate.class);
String html = StringSubstitutor.replace(mailTemplate.getBody(), mailParameters);

final String subject = Optional.ofNullable(prefixSubject).map(value -> String.format("%s: %s", value, mailTemplate.getSubject())).orElse(mailTemplate.getSubject());

Mail mail = Mail
.withHtml(destination, subject, html)
.setFrom(senderMail);

if(Objects.nonNull(fileMailData)) {
mail.addAttachment(fileMailData.getName(), fileMailData.getData(), fileMailData.getContentType());
}

mailer.send(mail);

log.info(String.format("End of sending mail to %s, with subject %s", destination, subject));
} catch (Exception e) {
log.error(String.format("%s: %s", ERROR_DURING_SEND_MAIL, e.getMessage()));
throw new GenericException(ERROR_DURING_SEND_MAIL);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
quarkus.mongodb.database=pecNotification

## MAIL
institution-send-mail.sender-mail = ${MAIL_SENDER_ADDRESS:[email protected]}
## In PROD env must be false for sending real mail
institution-send-mail.destination-mail = ${MAIL_DESTINATION_TEST:true}
## If MAIL_DESTINATION_TEST is true, app send mail to this address
institution-send-mail.destination-mail-test-address = ${MAIL_DESTINATION_TEST_ADDRESS:[email protected]}

## AZURE STORAGE ##
institution-send-mail.blob-storage.container-contract=${STORAGE_CONTAINER_CONTRACT:selc-d-contracts-blob}
institution-send-mail.blob-storage.connection-string-contract = ${BLOB_STORAGE_CONN_STRING_CONTRACT:UseDevelopmentStorage=true;}
Loading

0 comments on commit 214add8

Please sign in to comment.