diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 57555c3f..23b14cf0 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -288,5 +288,7 @@ public class GepafinConstant { public static final String INVALID_AMENDMENT_FOR_COMMENT = "invalid.amendment.for.comment"; public static final String DD_MM_YYYY_HH_MM = "DD_MM_YYYY_HH_MM"; + public static final String ENCRYPT_INIT_VECTOR = "IG8*(*@&)*#biVVD"; + public static final String ENCRYPT_KEY = "U2VjdXJlRW5jcnlwdEtleQ=="; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index f8334632..71d08f08 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -131,6 +131,8 @@ public class ApplicationDao { @Autowired private HubService hubService; + @Autowired + private EmailNotificationDao emailNotificationDao; public ApplicationResponseBean createApplication(HttpServletRequest request, ApplicationRequestBean applicationRequestBean, Long formId, Long applicationId) { FormEntity formEntity = formService.validateForm(formId); @@ -728,9 +730,8 @@ public class ApplicationDao { if (userEntity.getBeneficiary() != null) { email = userEntity.getBeneficiary().getEmail(); } - mailUtil.sendByMailGun(subject, body, List.of(email), null); - mailUtil.sendByMailGun(subject, body, List.of(applicationEntity.getCompany().getEmail()), null); - + emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(email)); + emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(applicationEntity.getCompany().getEmail())); } private void sendMailTodefaultSystemAndGepafin(UserEntity userEntity, ApplicationEntity applicationEntity) { @@ -759,12 +760,16 @@ public class ApplicationDao { String body = Utils.replacePlaceholders(systemEmailTemplateResponse.getHtmlContent(), bodyPlaceholders); - mailUtil.sendByMailGun(subject, body, List.of(defaultSystemReceiverEmail), null); - mailUtil.sendByMailGun(subject, body, List.of(gepafinEmail), null); - mailUtil.sendByMailGun(subject, body, List.of(rinaldoEmail), null); +// mailUtil.sendByMailGun(subject, body, List.of(defaultSystemReceiverEmail), null); +// mailUtil.sendByMailGun(subject, body, List.of(gepafinEmail), null); +// mailUtil.sendByMailGun(subject, body, List.of(rinaldoEmail), null); if(validator.isProductionProfileActivated()) { - mailUtil.sendByMailGun(subject, body, List.of(carloEmail), null); +// mailUtil.sendByMailGun(subject, body, List.of(carloEmail), null); + emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(carloEmail)); } + emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(gepafinEmail)); + emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(defaultSystemReceiverEmail)); + emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(rinaldoEmail)); } public ApplicationSignedDocumentResponse uploadSignedDocument(HttpServletRequest request, Long applicationId, diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java index 729f2e17..cd1654bb 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java @@ -896,7 +896,7 @@ public class ApplicationEvaluationDao { entity = applicationEvaluationRepository.save(existingEntity); assignedApplicationsRepository.save(assignedApplicationsEntity); - ApplicationAmendmentRequestEntity amendmentRequest = applicationAmendmentRequestRepository.findByApplicationEvaluationIdAndIsDeletedFalse(existingEntity.getId()); + ApplicationAmendmentRequestEntity amendmentRequest = applicationAmendmentRequestRepository.findByApplicationEvaluationIdAndIsDeletedFalse(entity.getId()); if (Boolean.TRUE.equals(statusType.equals((ApplicationStatusTypeEnum.APPROVED.getValue())))) { emailNotificationDao.sendAdmissibilityNotificationEmailForApprovedApplication(amendmentRequest); } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/EmailNotificationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/EmailNotificationDao.java index 75b5dbf6..f75e5796 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/EmailNotificationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/EmailNotificationDao.java @@ -1,22 +1,33 @@ package net.gepafin.tendermanagement.dao; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.ApplicationAmendmentRequestEntity; import net.gepafin.tendermanagement.entities.ApplicationEntity; import net.gepafin.tendermanagement.entities.HubEntity; import net.gepafin.tendermanagement.entities.SystemEmailTemplatesEntity; import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.model.request.EmailConfig; import net.gepafin.tendermanagement.model.response.SystemEmailTemplateResponse; +import net.gepafin.tendermanagement.repositories.CallRepository; +import net.gepafin.tendermanagement.repositories.HubRepository; import net.gepafin.tendermanagement.service.ApplicationService; import net.gepafin.tendermanagement.service.HubService; import net.gepafin.tendermanagement.service.SystemEmailTemplatesService; import net.gepafin.tendermanagement.service.UserService; +import net.gepafin.tendermanagement.service.impl.EmailService; +import net.gepafin.tendermanagement.service.impl.EmailServiceFactory; import net.gepafin.tendermanagement.util.DateTimeUtil; import net.gepafin.tendermanagement.util.MailUtil; import net.gepafin.tendermanagement.util.Utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -24,6 +35,8 @@ import java.util.Map; @Component public class EmailNotificationDao { + private static final Logger log = LoggerFactory.getLogger(EmailNotificationDao.class); + @Autowired private MailUtil mailUtil; @@ -39,126 +52,140 @@ public class EmailNotificationDao { @Autowired private HubService hubService; - public void sendMailToNotifyBeneficiaryRegardingNewAmendment(ApplicationAmendmentRequestEntity applicationAmendmentRequest) { + @Autowired + EmailServiceFactory emailServiceFactory; - ApplicationEntity applicationEntity = applicationService.validateApplication(applicationAmendmentRequest.getApplicationId()); - HubEntity hub = hubService.valdateHub(applicationEntity.getHubId()); - SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService.retrieveTemplateByTypeAndCall( - SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum.DOCUMENTATION_INTEGRATION_REQUEST, hub, null); + @Autowired + HubRepository hubRepository; - // Create the map for subject placeholders + + private void sendEmail(ApplicationAmendmentRequestEntity amendmentRequest, SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum templateType, + Map bodyPlaceholders, List additionalRecipients) { + + ApplicationEntity applicationEntity = applicationService.validateApplication(amendmentRequest.getApplicationId()); + HubEntity hubEntity = hubService.valdateHub(applicationEntity.getHubId()); + String service = determineService(applicationEntity.getHubId()); + String legalMail = service.equals("Gepafin S.p.a.") ? "bandi.gepafin@legalmail.it" : "bandi.sviluppumbria@legalmail.it"; + + SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService.retrieveTemplateByTypeAndCall(templateType, hubEntity, null); Map subjectPlaceholders = new HashMap<>(); subjectPlaceholders.put("{{call_name}}", applicationEntity.getCall().getName()); subjectPlaceholders.put("{{company_name}}", applicationEntity.getCompany().getCompanyName()); - - // Create the map for body placeholders - Map bodyPlaceholders = new HashMap<>(); - bodyPlaceholders.put("{{call_name}}", applicationEntity.getCall().getName()); - bodyPlaceholders.put("{{protocol_number}}", applicationEntity.getProtocol().getProtocolNumber().toString()); - bodyPlaceholders.put("{{protocol_date}}", DateTimeUtil.formatLocalDateTime(applicationAmendmentRequest.getProtocol().getCreatedDate(), GepafinConstant.DD_MM_YYYY)); - bodyPlaceholders.put("{{protocol_time}}", DateTimeUtil.parseLocalTimeToString(applicationAmendmentRequest.getProtocol().getTime(), GepafinConstant.HH_MM_SS)); - bodyPlaceholders.put("{{form_dataInput}}", ""); - - // Replace placeholders in the subject and body + bodyPlaceholders.put("{{legal_mail}}", legalMail); String subject = Utils.replacePlaceholders(systemEmailTemplateResponse.getSubject(), subjectPlaceholders); String body = Utils.replacePlaceholders(systemEmailTemplateResponse.getHtmlContent(), bodyPlaceholders); + UserEntity userEntity = userService.validateUser(applicationEntity.getUserId()); - mailUtil.sendByMailGun(subject, body, List.of(userEntity.getBeneficiary().getEmail()), null); + List recipientEmails = new ArrayList<>(); + if (applicationEntity.getCompany().getEmail() != null) { + recipientEmails.add(applicationEntity.getCompany().getEmail()); + } + if (userEntity.getBeneficiary().getEmail() != null) { + recipientEmails.add(userEntity.getBeneficiary().getEmail()); + } + if (additionalRecipients != null) { + recipientEmails.addAll(additionalRecipients); + } + sendMail(applicationEntity.getHubId(), subject, body, recipientEmails); + } + + private String determineService(Long hubId) { + + HubEntity hub = hubRepository.findById(hubId).orElseThrow(() -> new IllegalArgumentException("Invalid Hub ID: " + hubId)); + return hub.getEmailServiceType().equalsIgnoreCase("MAILGUN_SERVICE") ? "Gepafin S.p.a." : "Sviluppumbria"; + } + + public void sendMailToNotifyBeneficiaryRegardingNewAmendment(ApplicationAmendmentRequestEntity applicationAmendmentRequest) { + + ApplicationEntity applicationEntity = applicationService.validateApplication(applicationAmendmentRequest.getApplicationId()); + Map bodyPlaceholders = new HashMap<>(); + bodyPlaceholders.put("{{call_name}}", applicationEntity.getCall().getName()); + bodyPlaceholders.put("{{protocol_number}}", applicationAmendmentRequest.getProtocol().getProtocolNumber().toString()); + bodyPlaceholders.put("{{protocol_date}}", DateTimeUtil.formatLocalDateTime(applicationAmendmentRequest.getProtocol().getCreatedDate(), GepafinConstant.DD_MM_YYYY)); + bodyPlaceholders.put("{{protocol_time}}", DateTimeUtil.parseLocalTimeToString(applicationAmendmentRequest.getProtocol().getTime(), GepafinConstant.HH_MM_SS)); + String formFieldsJson = applicationAmendmentRequest.getFormFields(); + ObjectMapper objectMapper = new ObjectMapper(); + + try { + List> formFields = objectMapper.readValue(formFieldsJson, new TypeReference>>() { + }); + //• + StringBuilder bulletPoints = new StringBuilder(); + for (Map field : formFields) { + String label = (String) field.get("label"); + boolean selected = (boolean) field.get("selected"); + if (!selected) { + bulletPoints.append("• ").append(label).append("\n"); + } + } + bodyPlaceholders.put("{{form_dataInput}}", bulletPoints.toString()); + } catch (Exception e) { + log.error("Failed to parse form fields JSON: ", e); + } + bodyPlaceholders.put("{{note}}", applicationAmendmentRequest.getNote()); + sendEmail(applicationAmendmentRequest, SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum.DOCUMENTATION_INTEGRATION_REQUEST, bodyPlaceholders, null); } public void sendApplicationFailureNotificationEmail(ApplicationAmendmentRequestEntity amendmentRequest) { ApplicationEntity applicationEntity = applicationService.validateApplication(amendmentRequest.getApplicationId()); - HubEntity hub = hubService.valdateHub(applicationEntity.getHubId()); - SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService.retrieveTemplateByTypeAndCall( - SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum.INADMISSIBILITY_NOTIFICATION_DUE_TO_FAILURE, hub, null); - - // Create the map for subject placeholders - Map subjectPlaceholders = new HashMap<>(); - subjectPlaceholders.put("{{call_name}}", applicationEntity.getCall().getName()); - subjectPlaceholders.put("{{company_name}}", applicationEntity.getCompany().getCompanyName()); - - // Create the map for body placeholders Map bodyPlaceholders = new HashMap<>(); bodyPlaceholders.put("{{call_name}}", applicationEntity.getCall().getName()); bodyPlaceholders.put("{{date_time_emailSend}}", DateTimeUtil.formatLocalDateTime(amendmentRequest.getCreatedDate(), GepafinConstant.DD_MM_YYYY_HH_MM)); - // Replace placeholders in the subject and body - String subject = Utils.replacePlaceholders(systemEmailTemplateResponse.getSubject(), subjectPlaceholders); - String body = Utils.replacePlaceholders(systemEmailTemplateResponse.getHtmlContent(), bodyPlaceholders); - UserEntity userEntity = userService.validateUser(applicationEntity.getUserId()); - if (userEntity.getBeneficiary().getEmail() != null) { - mailUtil.sendByMailGun(subject, body, List.of(userEntity.getBeneficiary().getEmail()), null); - } + sendEmail(amendmentRequest, SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum.INADMISSIBILITY_NOTIFICATION_DUE_TO_FAILURE, bodyPlaceholders, null); } public void sendAdmissibilityNotificationEmailForApprovedApplication(ApplicationAmendmentRequestEntity amendmentRequest) { ApplicationEntity applicationEntity = applicationService.validateApplication(amendmentRequest.getApplicationId()); - HubEntity hub = hubService.valdateHub(applicationEntity.getHubId()); - SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService.retrieveTemplateByTypeAndCall( - SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum.ADMISSIBILITY_NOTIFICATION, hub, null); - - // Create the map for subject placeholders - Map subjectPlaceholders = new HashMap<>(); - subjectPlaceholders.put("{{call_name}}", applicationEntity.getCall().getName()); - subjectPlaceholders.put("{{company_name}}", applicationEntity.getCompany().getCompanyName()); - - // Create the map for body placeholders Map bodyPlaceholders = new HashMap<>(); bodyPlaceholders.put("{{call_name}}", applicationEntity.getCall().getName()); - bodyPlaceholders.put("{{protocol_number}}", applicationEntity.getProtocol().getProtocolNumber().toString()); - bodyPlaceholders.put("{{protocol_date}}", DateTimeUtil.formatCreatedDate(applicationEntity.getProtocol().getCreatedDate())); - bodyPlaceholders.put("{{protocol_time}}", DateTimeUtil.parseLocalTimeToString(applicationEntity.getProtocol().getTime(), GepafinConstant.HH_MM_SS)); + bodyPlaceholders.put("{{protocol_number}}", amendmentRequest.getProtocol().getProtocolNumber().toString()); + bodyPlaceholders.put("{{protocol_date}}", DateTimeUtil.formatCreatedDate(amendmentRequest.getProtocol().getCreatedDate())); + bodyPlaceholders.put("{{protocol_time}}", DateTimeUtil.parseLocalTimeToString(amendmentRequest.getProtocol().getTime(), GepafinConstant.HH_MM_SS)); - // Replace placeholders in the subject and body - String subject = Utils.replacePlaceholders(systemEmailTemplateResponse.getSubject(), subjectPlaceholders); - String body = Utils.replacePlaceholders(systemEmailTemplateResponse.getHtmlContent(), bodyPlaceholders); - - UserEntity userEntity = userService.validateUser(applicationEntity.getUserId()); - String userEmail; - String companyEmail; - if (userEntity.getBeneficiary().getEmail() != null && applicationEntity.getCompany().getEmail() != null) { - userEmail = userEntity.getBeneficiary().getEmail(); - companyEmail = applicationEntity.getCompany().getEmail(); - mailUtil.sendByMailGun(subject, body, List.of(userEmail), null); - mailUtil.sendByMailGun(subject, body, List.of(companyEmail), null); - } + sendEmail(amendmentRequest, SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum.ADMISSIBILITY_NOTIFICATION, bodyPlaceholders, null); } public void sendInadmissibilityEmailForRejectedApplication(ApplicationAmendmentRequestEntity amendmentRequest) { ApplicationEntity applicationEntity = applicationService.validateApplication(amendmentRequest.getApplicationId()); - HubEntity hub = hubService.valdateHub(applicationEntity.getHubId()); - SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService.retrieveTemplateByTypeAndCall( - SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum.INADMISSIBILITY_TEMPLATE, hub, null); - - // Create the map for subject placeholders - Map subjectPlaceholders = new HashMap<>(); - subjectPlaceholders.put("{{call_name}}", applicationEntity.getCall().getName()); - subjectPlaceholders.put("{{company_name}}", applicationEntity.getCompany().getCompanyName()); - - // Create the map for body placeholders Map bodyPlaceholders = new HashMap<>(); bodyPlaceholders.put("{{call_name}}", applicationEntity.getCall().getName()); - bodyPlaceholders.put("{{protocol_number}}", applicationEntity.getProtocol().getProtocolNumber().toString()); - bodyPlaceholders.put("{{protocol_date}}", DateTimeUtil.formatCreatedDate(applicationEntity.getProtocol().getCreatedDate())); - bodyPlaceholders.put("{{protocol_time}}", DateTimeUtil.parseLocalTimeToString(applicationEntity.getProtocol().getTime(), GepafinConstant.HH_MM_SS)); - bodyPlaceholders.put("{{form_text}}", ""); + bodyPlaceholders.put("{{protocol_number}}", amendmentRequest.getProtocol().getProtocolNumber().toString()); + bodyPlaceholders.put("{{protocol_date}}", DateTimeUtil.formatCreatedDate(amendmentRequest.getProtocol().getCreatedDate())); + bodyPlaceholders.put("{{protocol_time}}", DateTimeUtil.parseLocalTimeToString(amendmentRequest.getProtocol().getTime(), GepafinConstant.HH_MM_SS)); + bodyPlaceholders.put("{{form_text}}", amendmentRequest.getNote()); - // Replace placeholders in the subject and body - String subject = Utils.replacePlaceholders(systemEmailTemplateResponse.getSubject(), subjectPlaceholders); - String body = Utils.replacePlaceholders(systemEmailTemplateResponse.getHtmlContent(), bodyPlaceholders); - - UserEntity userEntity = userService.validateUser(applicationEntity.getUserId()); - String userEmail; - String companyEmail; - if (userEntity.getBeneficiary().getEmail() != null && applicationEntity.getCompany().getEmail() != null) { - userEmail = userEntity.getBeneficiary().getEmail(); - companyEmail = applicationEntity.getCompany().getEmail(); - mailUtil.sendByMailGun(subject, body, List.of(userEmail), null); - mailUtil.sendByMailGun(subject, body, List.of(companyEmail), null); - } + sendEmail(amendmentRequest, SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum.INADMISSIBILITY_TEMPLATE, bodyPlaceholders, null); } -} + public void sendMail(Long hubId, String subject, String body, List recipientEmails) { + + EmailConfig emailConfig = retrieveEmailConfig(hubId); + EmailService emailService = emailServiceFactory.getEmailService(emailConfig.getEmailServiceType()); + emailService.sendEmail(subject, body, recipientEmails, emailConfig); + } + + public EmailConfig retrieveEmailConfig(Long hubId) { + + HubEntity hubEntity = hubRepository.findById(hubId).orElseThrow(() -> new IllegalArgumentException("Invalid Hub ID: " + hubId)); + String emailServiceType = hubEntity.getEmailServiceType(); + String encryptedConfigJson = hubEntity.getEmailServiceConfig(); + String decryptedConfigJson = Utils.decryptCredential(encryptedConfigJson); + EmailConfig emailConfig = parseEmailConfig(decryptedConfigJson); + emailConfig.setEmailServiceType(emailServiceType); + return emailConfig; + } + + private EmailConfig parseEmailConfig(String configJson) { + + ObjectMapper objectMapper = new ObjectMapper(); + try { + return objectMapper.readValue(configJson, EmailConfig.class); + } catch (JsonProcessingException e) { + throw new IllegalArgumentException("Failed to parse email configuration JSON", e); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/entities/HubEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/HubEntity.java index 9de3f31d..2e219acf 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/HubEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/HubEntity.java @@ -49,4 +49,9 @@ public class HubEntity extends BaseEntity{ @Column(name = "EMAIL_SIGNATURE") private String emailSignature; + @Column(name = "EMAIL_SERVICE_TYPE") + private String emailServiceType; + + @Column(name = "EMAIL_SERVICE_CONFIG") + private String emailServiceConfig; } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/SystemEmailTemplatesEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/SystemEmailTemplatesEntity.java index 29e33277..6d8ff6de 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/SystemEmailTemplatesEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/SystemEmailTemplatesEntity.java @@ -43,7 +43,7 @@ public class SystemEmailTemplatesEntity extends BaseEntity { DOCUMENTATION_INTEGRATION_REQUEST("DOCUMENTATION_INTEGRATION_REQUEST"), INADMISSIBILITY_NOTIFICATION_DUE_TO_FAILURE("INADMISSIBILITY_NOTIFICATION_DUE_TO_FAILURE"), ADMISSIBILITY_NOTIFICATION("ADMISSIBILITY_NOTIFICATION"), - INADMISSIBILITY_TEMPLATE("INADMISSIBILITY_NOTIFICATION_2"); + INADMISSIBILITY_TEMPLATE("INADMISSIBILITY_NOTIFICATION"); private String value; diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/EmailConfig.java b/src/main/java/net/gepafin/tendermanagement/model/request/EmailConfig.java new file mode 100644 index 00000000..5a94b325 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/EmailConfig.java @@ -0,0 +1,18 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class EmailConfig { + private String emailServiceType; + private String authToken; + private String apiKey; + private String username; + private String password; + private String sender; + private String domain; + private String mailgunApiUrl; + private String pecApiUrl; +} + + diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/PecEmailRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/PecEmailRequest.java new file mode 100644 index 00000000..a066dce0 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/PecEmailRequest.java @@ -0,0 +1,15 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +import java.util.List; + +@Data +public class PecEmailRequest { + private String sender; + private List recipient; + private String subject; + private String body; + private String username; + private String password; +} diff --git a/src/main/java/net/gepafin/tendermanagement/scheduler/NotificationScheduler.java b/src/main/java/net/gepafin/tendermanagement/scheduler/NotificationScheduler.java index f83af795..5fcb3bc2 100644 --- a/src/main/java/net/gepafin/tendermanagement/scheduler/NotificationScheduler.java +++ b/src/main/java/net/gepafin/tendermanagement/scheduler/NotificationScheduler.java @@ -29,7 +29,7 @@ public class NotificationScheduler { @Autowired EmailNotificationDao emailNotificationDao; - @Scheduled(cron = "0 0/1 * * * ?") +// @Scheduled(cron = "0 0/1 * * * ?") void sendNotificationForRejectedApplicationToBeneficiary() { List applicationsList = applicationRepository.findByIsDeletedFalse(); diff --git a/src/main/java/net/gepafin/tendermanagement/service/feignClient/MailgunFeignClient.java b/src/main/java/net/gepafin/tendermanagement/service/feignClient/MailgunFeignClient.java new file mode 100644 index 00000000..eb9c50d1 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/feignClient/MailgunFeignClient.java @@ -0,0 +1,24 @@ +package net.gepafin.tendermanagement.service.feignClient; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.List; + +@FeignClient(name = "mailgunClient", url = "${mailGun_base_url}") +public interface MailgunFeignClient { + @PostMapping("/v3/{domain}/messages") + ResponseEntity sendEmail( + @PathVariable("domain") String domain, + @RequestParam("from") String from, + @RequestParam("to") List to, + @RequestParam("subject") String subject, + @RequestParam("html") String htmlBody, + @RequestHeader("Authorization") String authorizationHeader); +} + + diff --git a/src/main/java/net/gepafin/tendermanagement/service/feignClient/PecFeignClient.java b/src/main/java/net/gepafin/tendermanagement/service/feignClient/PecFeignClient.java new file mode 100644 index 00000000..d251e644 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/feignClient/PecFeignClient.java @@ -0,0 +1,17 @@ +package net.gepafin.tendermanagement.service.feignClient; + +import feign.Headers; +import net.gepafin.tendermanagement.model.request.PecEmailRequest; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; + +@FeignClient(name = "pecClient", url = "${api.pecUrl}") +public interface PecFeignClient { + @PostMapping("/send") + ResponseEntity sendEmail(@RequestHeader("Authorization") String token, + @RequestBody PecEmailRequest emailRequest); +} + diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/EmailService.java b/src/main/java/net/gepafin/tendermanagement/service/impl/EmailService.java new file mode 100644 index 00000000..6b7b91cc --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/EmailService.java @@ -0,0 +1,11 @@ +package net.gepafin.tendermanagement.service.impl; + +import net.gepafin.tendermanagement.model.request.EmailConfig; + +import java.util.List; + +public interface EmailService { + void sendEmail(String subject, String body, List recipientEmails, EmailConfig emailConfig); +} + + diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/EmailServiceFactory.java b/src/main/java/net/gepafin/tendermanagement/service/impl/EmailServiceFactory.java new file mode 100644 index 00000000..6ab6b270 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/EmailServiceFactory.java @@ -0,0 +1,24 @@ +package net.gepafin.tendermanagement.service.impl; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class EmailServiceFactory { + + @Autowired + private PecEmailService pecEmailService; + + @Autowired + private MailgunEmailService mailgunEmailService; + + public EmailService getEmailService(String serviceType) { + if ("MAILGUN_SERVICE".equals(serviceType)) { + return mailgunEmailService; + } else if ("PEC_SERVICE".equals(serviceType)) { + return pecEmailService; + } else { + throw new IllegalArgumentException("Invalid email service type: " + serviceType); + } + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/MailgunEmailService.java b/src/main/java/net/gepafin/tendermanagement/service/impl/MailgunEmailService.java new file mode 100644 index 00000000..9dd965e7 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/MailgunEmailService.java @@ -0,0 +1,33 @@ +package net.gepafin.tendermanagement.service.impl; + +import net.gepafin.tendermanagement.model.request.EmailConfig; +import net.gepafin.tendermanagement.service.feignClient.MailgunFeignClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import java.util.Base64; +import java.util.List; + +@Service +public class MailgunEmailService implements EmailService { + + @Autowired + private MailgunFeignClient mailgunFeignClient; + + @Override + public void sendEmail(String subject, String body, List recipientEmails, EmailConfig emailConfig) { + String domain = emailConfig.getDomain(); + String from = emailConfig.getSender(); + String apiKey = emailConfig.getApiKey(); + String authHeader = "Basic " + Base64.getEncoder().encodeToString(("api:" + apiKey).getBytes()); + + // Send email via Mailgun API + ResponseEntity response = mailgunFeignClient.sendEmail(domain, from, recipientEmails, subject, body, authHeader); + if (!response.getStatusCode().is2xxSuccessful()) { + throw new RuntimeException("Failed to send email via Mailgun: " + response.getStatusCode()); + } + } +} + + diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/PecEmailService.java b/src/main/java/net/gepafin/tendermanagement/service/impl/PecEmailService.java new file mode 100644 index 00000000..f2cdc613 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/PecEmailService.java @@ -0,0 +1,42 @@ +package net.gepafin.tendermanagement.service.impl; + +import lombok.extern.slf4j.Slf4j; +import net.gepafin.tendermanagement.model.request.EmailConfig; +import net.gepafin.tendermanagement.model.request.PecEmailRequest; +import net.gepafin.tendermanagement.service.feignClient.PecFeignClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Slf4j +@Service +public class PecEmailService implements EmailService { + private final PecFeignClient pecFeignClient; + + public PecEmailService(PecFeignClient pecFeignClient) { + + this.pecFeignClient = pecFeignClient; + } + + @Override + public void sendEmail(String subject, String body, List recipientEmails, EmailConfig emailConfig) { + PecEmailRequest emailRequest = new PecEmailRequest(); + emailRequest.setSender(emailConfig.getSender()); + emailRequest.setRecipient(recipientEmails); + emailRequest.setSubject(subject); + emailRequest.setBody(body); + emailRequest.setUsername(emailConfig.getUsername()); + emailRequest.setPassword(emailConfig.getPassword()); + + String authToken = emailConfig.getAuthToken(); + ResponseEntity response = pecFeignClient.sendEmail("Bearer " + authToken, emailRequest); + log.info("Mail response status: {}, headers: {}, body: {}", response.getStatusCode(), response.getHeaders(), response.getBody()); + if (!response.getStatusCode().is2xxSuccessful()) { + throw new RuntimeException("Failed to send email via PEC: " + response.getStatusCode()); + } + } +} + + diff --git a/src/main/java/net/gepafin/tendermanagement/util/Utils.java b/src/main/java/net/gepafin/tendermanagement/util/Utils.java index 3bd7041e..26f049ef 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Utils.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Utils.java @@ -20,6 +20,7 @@ import java.util.stream.Collectors; import com.itextpdf.styledxmlparser.jsoup.Jsoup; import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.constants.GepafinConstant; import org.apache.commons.collections4.MapUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,6 +41,10 @@ import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientNotFoundExcep import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientUnauthorizedException; import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientValidationException; +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + import static org.apache.commons.lang3.StringUtils.isEmpty; @@ -467,4 +472,47 @@ public class Utils { return sanitizedInput.matches(wholeNumberPattern); } + + public static String encryptCredential(String value) { + try { + if(Boolean.FALSE.equals(isEmpty(value))) { + + IvParameterSpec iv = new IvParameterSpec(GepafinConstant.ENCRYPT_INIT_VECTOR.getBytes("UTF-8")); + SecretKeySpec skeySpec = new SecretKeySpec(Base64.getDecoder().decode(GepafinConstant.ENCRYPT_KEY), "AES"); + + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); + cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); + + byte[] encrypted = cipher.doFinal(value.getBytes()); + + return Base64.getEncoder().encodeToString(encrypted); + } + + } catch (Exception ex) { + log.error("Exception occured while encrypt credential :- {0}", ex); + } + return null; + } + + public static String decryptCredential(String encrypted) { + try { + if(Boolean.FALSE.equals(isEmpty(encrypted))) { + + IvParameterSpec iv = new IvParameterSpec(GepafinConstant.ENCRYPT_INIT_VECTOR.getBytes("UTF-8")); + SecretKeySpec skeySpec = new SecretKeySpec(Base64.getDecoder().decode(GepafinConstant.ENCRYPT_KEY), "AES"); + + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); + + cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); + + byte[] original = cipher.doFinal(Base64.getDecoder().decode(encrypted)); + + return new String(original); + } + } catch (Exception ex) { + // log.error("Exception occured while decrypt credential :- {0}", ex); + return encrypted; + } + return null; + } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 6ead5502..d6198fd7 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -58,6 +58,7 @@ mailGun_domainName=paghiamoci.ai mailGun_base_url=https://api.eu.mailgun.net/ # SendinBlue API key apiKey=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 +api.pecUrl=https://ws.pecmassiva.com #senderEmail=mailer@bflows.net application.amendment.expiration.days=30 diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index 551833a0..4156ccf4 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -1627,11 +1627,6 @@ constraintName="fk_communication_application_amendment_request"/> - - - - @@ -1689,5 +1684,16 @@ + + + + + + + + + + diff --git a/src/main/resources/db/dump/insert_system_email_template_for_notification_mail_27_10_2024.sql b/src/main/resources/db/dump/insert_system_email_template_for_notification_mail_31_10_2024.sql similarity index 88% rename from src/main/resources/db/dump/insert_system_email_template_for_notification_mail_27_10_2024.sql rename to src/main/resources/db/dump/insert_system_email_template_for_notification_mail_31_10_2024.sql index 360bdd30..d42b1b40 100644 --- a/src/main/resources/db/dump/insert_system_email_template_for_notification_mail_27_10_2024.sql +++ b/src/main/resources/db/dump/insert_system_email_template_for_notification_mail_31_10_2024.sql @@ -20,14 +20,15 @@ VALUES
  • {{form_dataInput}}
+

{{note}}

Vi invitiamo a fornire quanto sopra richiesto integrando la documentazione sia caricandola all’interno dello sportello - online https://bandi.gepafin.it/ che inviandola a mezzo PEC all’indirizzo - bandi.gepafin@legalmail.it entro e non oltre 10 giorni dal ricevimento della presente comunicazione, + online {{platform_link}} che inviandola a mezzo PEC all’indirizzo + {{legal_mail}} entro e non oltre 10 giorni dal ricevimento della presente comunicazione, precisando che, in caso di mancata ricezione nei termini indicati, saremo costretti a non prendere in considerazione la Vostra richiesta di finanziamento.

Vi informiamo che per la ricezione della PEC farà fede la ricevuta di avvenuta consegna che attesterà il buon esito dell’invio. La documentazione trasmessa e le informazioni fornite saranno processate dall''istruttore assegnatario della pratica.

Distinti Saluti,

-

Gepafin S.p.a.

+

{{email_signature}}

', @@ -38,6 +39,7 @@ VALUES '2024-10-26 20:00:00', '2024-10-26 20:00:00' ); + INSERT INTO gepafin_schema.system_email_template ( id, template_name, "type", html_content, subject, "json", "system", @@ -57,9 +59,9 @@ VALUES dal Gestore sarebbero dovuti pervenire entro 10 giorni dal ricevimento di detta comunicazione. Trascorso il termine senza la ricezione dei documenti richiesti, il Gestore non ha potuto prendere in considerazione la richiesta di finanziamento.

È possibile presentare ricorso tramite modello disponibile nello sportello online - https://bandi.gepafin.it/ entro 10 giorni dalla ricezione di questa comunicazione.

+ {{platform_link}} entro 10 giorni dalla ricezione di questa comunicazione.

Distinti Saluti,

-

Gepafin S.p.a.

+

{{email_signature}}

', @@ -70,6 +72,7 @@ VALUES '2024-10-26 20:00:00', '2024-10-26 20:00:00' ); + INSERT INTO gepafin_schema.system_email_template ( id, template_name, "type", html_content, subject, "json", "system", @@ -89,7 +92,7 @@ VALUES è stata completata con esito positivo.

Seguirà una comunicazione relativa alla valutazione tecnica ed economico-finanziaria ai fini della valutazione finale.

Distinti Saluti,

-

Gepafin S.p.a.

+

{{email_signature}}

', @@ -100,6 +103,7 @@ VALUES '2024-10-26 20:00:00', '2024-10-26 20:00:00' ); + INSERT INTO gepafin_schema.system_email_template ( id, template_name, "type", html_content, subject, "json", "system", @@ -119,9 +123,9 @@ VALUES l''istruttoria di ammissibilità è stata completata con esito negativo.

Motivazioni: {{form_text}}

È possibile presentare ricorso tramite modello disponibile nello sportello online - https://bandi.gepafin.it/ entro 10 giorni dalla ricezione di questa comunicazione.

+ {{platform_link}} entro 10 giorni dalla ricezione di questa comunicazione.

Distinti Saluti,

-

Gepafin S.p.a.

+

{{email_signature}}

', @@ -131,4 +135,4 @@ VALUES false, '2024-10-26 20:00:00', '2024-10-26 20:00:00' -); +); \ No newline at end of file