From 6b1b34291b449cd21c3a4ada0ec0a784da7db057 Mon Sep 17 00:00:00 2001
From: nitin-ebi <79518737+nitin-ebi@users.noreply.github.com>
Date: Tue, 26 Mar 2024 09:18:47 +0000
Subject: [PATCH] EVA-3529 Notify submission update to user through email (#10)
* send mail on status update
---
pom.xml | 4 +
.../ebi/eva/submission/config/AppConfig.java | 18 +++
.../submissionws/SubmissionController.java | 2 +
.../submission/service/SubmissionService.java | 26 ++++-
.../util/EmailNotificationHelper.java | 58 ++++++++++
.../ebi/eva/submission/util/HTMLHelper.java | 66 +++++++++++
.../ebi/eva/submission/util/MailSender.java | 41 +++++++
.../SubmissionWSIntegrationTest.java | 5 +
.../unit/EmailNotificationHelperTest.java | 87 ++++++++++++++
.../eva/submission/unit/HTMLHelperTest.java | 109 ++++++++++++++++++
10 files changed, 412 insertions(+), 4 deletions(-)
create mode 100644 src/main/java/uk/ac/ebi/eva/submission/config/AppConfig.java
create mode 100644 src/main/java/uk/ac/ebi/eva/submission/util/EmailNotificationHelper.java
create mode 100644 src/main/java/uk/ac/ebi/eva/submission/util/HTMLHelper.java
create mode 100644 src/main/java/uk/ac/ebi/eva/submission/util/MailSender.java
create mode 100644 src/test/java/uk/ac/ebi/eva/submission/unit/EmailNotificationHelperTest.java
create mode 100644 src/test/java/uk/ac/ebi/eva/submission/unit/HTMLHelperTest.java
diff --git a/pom.xml b/pom.xml
index b6ea621..06e2616 100644
--- a/pom.xml
+++ b/pom.xml
@@ -60,6 +60,10 @@
org.springframework.boot
spring-boot-starter-security
+
+ org.springframework.boot
+ spring-boot-starter-mail
+
org.springdoc
springdoc-openapi-ui
diff --git a/src/main/java/uk/ac/ebi/eva/submission/config/AppConfig.java b/src/main/java/uk/ac/ebi/eva/submission/config/AppConfig.java
new file mode 100644
index 0000000..74514c4
--- /dev/null
+++ b/src/main/java/uk/ac/ebi/eva/submission/config/AppConfig.java
@@ -0,0 +1,18 @@
+package uk.ac.ebi.eva.submission.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.JavaMailSenderImpl;
+
+@Configuration
+public class AppConfig {
+
+ @Bean
+ public JavaMailSender javaMailService() {
+ JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
+ javaMailSender.setHost("smtp.ebi.ac.uk");
+ javaMailSender.setPort(25);
+ return javaMailSender;
+ }
+}
diff --git a/src/main/java/uk/ac/ebi/eva/submission/controller/submissionws/SubmissionController.java b/src/main/java/uk/ac/ebi/eva/submission/controller/submissionws/SubmissionController.java
index 251ec70..1d45f07 100644
--- a/src/main/java/uk/ac/ebi/eva/submission/controller/submissionws/SubmissionController.java
+++ b/src/main/java/uk/ac/ebi/eva/submission/controller/submissionws/SubmissionController.java
@@ -17,6 +17,7 @@
import uk.ac.ebi.eva.submission.controller.BaseController;
import uk.ac.ebi.eva.submission.entity.Submission;
import uk.ac.ebi.eva.submission.entity.SubmissionAccount;
+import uk.ac.ebi.eva.submission.model.SubmissionStatus;
import uk.ac.ebi.eva.submission.service.LsriTokenService;
import uk.ac.ebi.eva.submission.service.SubmissionService;
import uk.ac.ebi.eva.submission.service.WebinTokenService;
@@ -87,6 +88,7 @@ public ResponseEntity> markSubmissionUploaded(@RequestHeader("Authorization")
}
Submission submission = this.submissionService.markSubmissionUploaded(submissionId);
+ submissionService.sendMailNotificationForStatusUpdate(submissionAccount, submissionId, SubmissionStatus.UPLOADED, true);
return new ResponseEntity<>(stripUserDetails(submission), HttpStatus.OK);
}
diff --git a/src/main/java/uk/ac/ebi/eva/submission/service/SubmissionService.java b/src/main/java/uk/ac/ebi/eva/submission/service/SubmissionService.java
index ab54971..b5fd2db 100644
--- a/src/main/java/uk/ac/ebi/eva/submission/service/SubmissionService.java
+++ b/src/main/java/uk/ac/ebi/eva/submission/service/SubmissionService.java
@@ -2,13 +2,16 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
-import uk.ac.ebi.eva.submission.exception.SubmissionDoesNotExistException;
import uk.ac.ebi.eva.submission.entity.Submission;
import uk.ac.ebi.eva.submission.entity.SubmissionAccount;
+import uk.ac.ebi.eva.submission.exception.SubmissionDoesNotExistException;
import uk.ac.ebi.eva.submission.model.SubmissionStatus;
import uk.ac.ebi.eva.submission.repository.SubmissionAccountRepository;
import uk.ac.ebi.eva.submission.repository.SubmissionDetailsRepository;
import uk.ac.ebi.eva.submission.repository.SubmissionRepository;
+import uk.ac.ebi.eva.submission.util.EmailNotificationHelper;
+import uk.ac.ebi.eva.submission.util.HTMLHelper;
+import uk.ac.ebi.eva.submission.util.MailSender;
import java.time.LocalDateTime;
import java.util.Optional;
@@ -25,17 +28,24 @@ public class SubmissionService {
private final GlobusDirectoryProvisioner globusDirectoryProvisioner;
+ private final MailSender mailSender;
+
@Value("${globus.uploadHttpDomain}")
private String uploadHttpDomain;
+ private EmailNotificationHelper emailHelper;
+
public SubmissionService(SubmissionRepository submissionRepository,
SubmissionAccountRepository submissionAccountRepository,
SubmissionDetailsRepository submissionDetailsRepository,
- GlobusDirectoryProvisioner globusDirectoryProvisioner) {
+ GlobusDirectoryProvisioner globusDirectoryProvisioner,
+ MailSender mailSender, EmailNotificationHelper emailHelper) {
this.submissionRepository = submissionRepository;
this.submissionAccountRepository = submissionAccountRepository;
this.submissionDetailsRepository = submissionDetailsRepository;
this.globusDirectoryProvisioner = globusDirectoryProvisioner;
+ this.mailSender = mailSender;
+ this.emailHelper = emailHelper;
}
public Submission initiateSubmission(SubmissionAccount submissionAccount) {
@@ -45,7 +55,7 @@ public Submission initiateSubmission(SubmissionAccount submissionAccount) {
Optional optSubmissionAccount = submissionAccountRepository.findById(submissionAccount.getId());
// if the user account is not present or if its primary email has changed, save/update the user account
- if (!optSubmissionAccount.isPresent() || optSubmissionAccount.get().getPrimaryEmail() != submissionAccount.getPrimaryEmail()) {
+ if (!optSubmissionAccount.isPresent() || !optSubmissionAccount.get().getPrimaryEmail().equals(submissionAccount.getPrimaryEmail())) {
submissionAccountRepository.save(submissionAccount);
}
@@ -85,9 +95,17 @@ public boolean checkUserHasAccessToSubmission(SubmissionAccount account, String
Optional optSubmission = submissionRepository.findById(submissionId);
if (optSubmission.isPresent()) {
SubmissionAccount submissionAccount = optSubmission.get().getSubmissionAccount();
- return submissionAccount.getId() == account.getId();
+ return submissionAccount.getId().equals(account.getId());
} else {
throw new SubmissionDoesNotExistException("Given submission with id " + submissionId + " does not exist");
}
}
+
+ public void sendMailNotificationForStatusUpdate(SubmissionAccount submissionAccount, String submissionId,
+ SubmissionStatus submissionStatus, boolean success) {
+ String sendTo = submissionAccount.getPrimaryEmail();
+ String subject = emailHelper.getSubjectForSubmissionStatusUpdate(submissionStatus, success);
+ String body = emailHelper.getTextForSubmissionStatusUpdate(submissionAccount, submissionId, submissionStatus, success);
+ mailSender.sendEmail(sendTo, subject, body);
+ }
}
diff --git a/src/main/java/uk/ac/ebi/eva/submission/util/EmailNotificationHelper.java b/src/main/java/uk/ac/ebi/eva/submission/util/EmailNotificationHelper.java
new file mode 100644
index 0000000..76146d7
--- /dev/null
+++ b/src/main/java/uk/ac/ebi/eva/submission/util/EmailNotificationHelper.java
@@ -0,0 +1,58 @@
+package uk.ac.ebi.eva.submission.util;
+
+import org.springframework.stereotype.Component;
+import uk.ac.ebi.eva.submission.entity.SubmissionAccount;
+import uk.ac.ebi.eva.submission.model.SubmissionStatus;
+
+@Component
+public class EmailNotificationHelper {
+ private static final String EVA_HELPDESK_EMAIL = "eva-helpdesk@ebi.ac.uk";
+
+ public String getSubjectForSubmissionStatusUpdate(SubmissionStatus submissionStatus, boolean success) {
+ String result = (success == true) ? "SUCCESS" : "FAILED";
+ return String.format("EVA Submission Update: %s %s", submissionStatus, result);
+ }
+
+ public String getTextForSubmissionStatusUpdate(SubmissionAccount submissionAccount, String submissionId,
+ SubmissionStatus submissionStatus, boolean success) {
+ String result;
+ String resultColor;
+ if (success) {
+ result = "SUCCESS";
+ resultColor = "green";
+ } else {
+ result = "FAILED";
+ resultColor = "red";
+ }
+
+ String notificationText = new HTMLHelper()
+ .addText("Dear " + submissionAccount.getFirstName() + ",")
+ .addGap(1)
+ .addText("Here is the update for your submission: ")
+ .addGap(1)
+ .addText("submission ID: " + submissionId)
+ .addLineBreak()
+ .addText("Submission Status: " + submissionStatus)
+ .addLineBreak()
+ .addText("Result: ")
+ .addBoldTextWithColor(result, resultColor)
+ .addGap(2)
+ .build();
+
+ notificationText += getNotificationFooter();
+
+ return notificationText;
+ }
+
+ public String getNotificationFooter() {
+ return new HTMLHelper()
+ .addTextWithSize("Please don't reply to this email.", 10)
+ .addLineBreak()
+ .addTextWithSize("For any issues/support please contact us at ", 10)
+ .addEmailLinkWithSize(EVA_HELPDESK_EMAIL, EVA_HELPDESK_EMAIL, 10)
+ .addLineBreak()
+ .addTextWithSize("European Variation Archive: EMBL-EBI", 10)
+ .build();
+
+ }
+}
diff --git a/src/main/java/uk/ac/ebi/eva/submission/util/HTMLHelper.java b/src/main/java/uk/ac/ebi/eva/submission/util/HTMLHelper.java
new file mode 100644
index 0000000..78997bf
--- /dev/null
+++ b/src/main/java/uk/ac/ebi/eva/submission/util/HTMLHelper.java
@@ -0,0 +1,66 @@
+package uk.ac.ebi.eva.submission.util;
+
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+public class HTMLHelper {
+ private final StringBuilder htmlBuilder;
+
+ public HTMLHelper() {
+ htmlBuilder = new StringBuilder();
+ }
+
+ public HTMLHelper addLineBreak() {
+ htmlBuilder.append("
");
+ return this;
+ }
+
+ public HTMLHelper addGap(int count) {
+ htmlBuilder.append(IntStream.range(0, count+1).boxed().map(i -> "
").collect(Collectors.joining("")));
+ return this;
+ }
+
+ public HTMLHelper addText(String text) {
+ htmlBuilder.append(text);
+ return this;
+ }
+
+ public HTMLHelper addTextWithSize(String text, int size) {
+ htmlBuilder.append("" + text + "");
+ return this;
+ }
+
+ public HTMLHelper addTextWithColor(String text, String color) {
+ htmlBuilder.append("" + text + "");
+ return this;
+ }
+
+ public HTMLHelper addBoldText(String text) {
+ htmlBuilder.append("" + text + "");
+ return this;
+ }
+
+ public HTMLHelper addLink(String url, String text) {
+ htmlBuilder.append("" + text + "");
+ return this;
+ }
+
+ public HTMLHelper addEmailLink(String email, String text) {
+ htmlBuilder.append("" + text + "");
+ return this;
+ }
+
+ public HTMLHelper addEmailLinkWithSize(String email, String text, int size) {
+ htmlBuilder.append(" " + text + " ");
+ return this;
+ }
+
+ public HTMLHelper addBoldTextWithColor(String text, String color) {
+ htmlBuilder.append("" + text + "");
+ return this;
+ }
+
+ public String build() {
+ return htmlBuilder.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/uk/ac/ebi/eva/submission/util/MailSender.java b/src/main/java/uk/ac/ebi/eva/submission/util/MailSender.java
new file mode 100644
index 0000000..1715ad6
--- /dev/null
+++ b/src/main/java/uk/ac/ebi/eva/submission/util/MailSender.java
@@ -0,0 +1,41 @@
+package uk.ac.ebi.eva.submission.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.MimeMessageHelper;
+import org.springframework.stereotype.Component;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+@Component
+public class MailSender {
+ private final Logger logger = LoggerFactory.getLogger(MailSender.class);
+ private final JavaMailSender javaMailSender;
+ private final String DEFAULT_SENDER = "eva_submissions@ebi.ac.uk";
+
+ @Autowired
+ MailSender(JavaMailSender javaMailSender) {
+ this.javaMailSender = javaMailSender;
+ }
+
+ public void sendEmail(String to, String subject, String body) {
+ sendEmail(DEFAULT_SENDER, to, subject, body);
+ }
+
+ public void sendEmail(String from, String to, String subject, String body) {
+ MimeMessage message = javaMailSender.createMimeMessage();
+ MimeMessageHelper helper = new MimeMessageHelper(message);
+ try {
+ helper.setFrom(from);
+ helper.setTo(to);
+ helper.setSubject(subject);
+ helper.setText(body, true);
+ javaMailSender.send(message);
+ } catch (MessagingException e) {
+ logger.error("Error sending mail: " + e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/uk/ac/ebi/eva/submission/integration/SubmissionWSIntegrationTest.java b/src/test/java/uk/ac/ebi/eva/submission/integration/SubmissionWSIntegrationTest.java
index 9bdf97d..51516ed 100644
--- a/src/test/java/uk/ac/ebi/eva/submission/integration/SubmissionWSIntegrationTest.java
+++ b/src/test/java/uk/ac/ebi/eva/submission/integration/SubmissionWSIntegrationTest.java
@@ -26,6 +26,7 @@
import uk.ac.ebi.eva.submission.service.LoginMethod;
import uk.ac.ebi.eva.submission.service.LsriTokenService;
import uk.ac.ebi.eva.submission.service.WebinTokenService;
+import uk.ac.ebi.eva.submission.util.MailSender;
import java.time.LocalDateTime;
import java.util.ArrayList;
@@ -76,6 +77,9 @@ public class SubmissionWSIntegrationTest {
@MockBean
private GlobusDirectoryProvisioner globusDirectoryProvisioner;
+ @MockBean
+ private MailSender mailSender;
+
@Container
static PostgreSQLContainer> postgreSQLContainer = new PostgreSQLContainer<>("postgres:9.6")
.withInitScript("init.sql");
@@ -230,6 +234,7 @@ public void testMarkSubmissionUploaded() throws Exception {
String userToken = "webinUserToken";
SubmissionAccount submissionAccount = getWebinUserAccount();
when(webinTokenService.getWebinUserAccountFromToken(anyString())).thenReturn(submissionAccount);
+ doNothing().when(mailSender).sendEmail(anyString(), anyString(), anyString());
String submissionId = createNewSubmissionEntry(submissionAccount);
diff --git a/src/test/java/uk/ac/ebi/eva/submission/unit/EmailNotificationHelperTest.java b/src/test/java/uk/ac/ebi/eva/submission/unit/EmailNotificationHelperTest.java
new file mode 100644
index 0000000..647e97d
--- /dev/null
+++ b/src/test/java/uk/ac/ebi/eva/submission/unit/EmailNotificationHelperTest.java
@@ -0,0 +1,87 @@
+package uk.ac.ebi.eva.submission.unit;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import uk.ac.ebi.eva.submission.entity.SubmissionAccount;
+import uk.ac.ebi.eva.submission.model.SubmissionStatus;
+import uk.ac.ebi.eva.submission.service.LoginMethod;
+import uk.ac.ebi.eva.submission.util.EmailNotificationHelper;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class EmailNotificationHelperTest {
+ private EmailNotificationHelper emailNotificationHelper;
+
+ @BeforeEach
+ public void setup() {
+ emailNotificationHelper = new EmailNotificationHelper();
+ }
+
+ @Test
+ public void testGetSubjectForSubmissionStatusUpdate() {
+ String expectedSubject = "EVA Submission Update: UPLOADED SUCCESS";
+ String actualSubject = emailNotificationHelper.getSubjectForSubmissionStatusUpdate(SubmissionStatus.UPLOADED, true);
+
+ assertEquals(expectedSubject, actualSubject);
+ }
+
+ @Test
+ public void testGetTextForSubmissionStatusUpdateSuccess() {
+ SubmissionAccount submissionAccount = new SubmissionAccount("johndoe@example.com",
+ LoginMethod.WEBIN.toString(), "John", "Doe", "john@example.com");
+ String expectedText = "Dear John," +
+ "
" +
+ "Here is the update for your submission: " +
+ "
" +
+ "submission ID: 12345
" +
+ "Submission Status: UPLOADED
" +
+ "Result: SUCCESS" +
+ "
" +
+ "Please don't reply to this email.
" +
+ "For any issues/support please contact us at " +
+ " eva-helpdesk@ebi.ac.uk " +
+ "
European Variation Archive: EMBL-EBI";
+
+ String actualText = emailNotificationHelper.getTextForSubmissionStatusUpdate(submissionAccount,
+ "12345", SubmissionStatus.UPLOADED, true);
+
+ assertEquals(expectedText, actualText);
+ }
+
+ @Test
+ public void testGetTextForSubmissionStatusUpdateFailure() {
+ SubmissionAccount submissionAccount = new SubmissionAccount("johndoe@example.com",
+ LoginMethod.WEBIN.toString(), "John", "Doe", "john@example.com");
+ String expectedText = "Dear John," +
+ "
" +
+ "Here is the update for your submission: " +
+ "
" +
+ "submission ID: 12345
" +
+ "Submission Status: UPLOADED
" +
+ "Result: FAILED" +
+ "
" +
+ "Please don't reply to this email.
" +
+ "For any issues/support please contact us at " +
+ " eva-helpdesk@ebi.ac.uk " +
+ "
European Variation Archive: EMBL-EBI";
+
+ String actualText = emailNotificationHelper.getTextForSubmissionStatusUpdate(submissionAccount,
+ "12345", SubmissionStatus.UPLOADED, false);
+
+ assertEquals(expectedText, actualText);
+ }
+
+ @Test
+ public void testGetNotificationFooter(){
+ String expectedFooter = "Please don't reply to this email.
" +
+ "For any issues/support please contact us at " +
+ " eva-helpdesk@ebi.ac.uk " +
+ "
European Variation Archive: EMBL-EBI";
+
+ String actualFooter = emailNotificationHelper.getNotificationFooter();
+
+ assertEquals(expectedFooter, actualFooter);
+ }
+
+}
+
diff --git a/src/test/java/uk/ac/ebi/eva/submission/unit/HTMLHelperTest.java b/src/test/java/uk/ac/ebi/eva/submission/unit/HTMLHelperTest.java
new file mode 100644
index 0000000..5f89dc4
--- /dev/null
+++ b/src/test/java/uk/ac/ebi/eva/submission/unit/HTMLHelperTest.java
@@ -0,0 +1,109 @@
+package uk.ac.ebi.eva.submission.unit;
+
+import org.junit.jupiter.api.Test;
+import uk.ac.ebi.eva.submission.util.HTMLHelper;
+
+import static org.junit.Assert.assertEquals;
+
+public class HTMLHelperTest {
+
+ @Test
+ public void testAddLineBreak() {
+ String expectedHTML = "
";
+ String actualHTML = new HTMLHelper().addLineBreak().build();
+ assertEquals(expectedHTML, actualHTML);
+ }
+
+ @Test
+ public void testAddGap() {
+ // adding a gap of 3 lines means you need to add 4
tags,
+ // one for taking the cursor to the new line and the rest for the actual gap
+ String expectedHTML = "
";
+ String actualHTML = new HTMLHelper().addGap(3).build();
+ assertEquals(expectedHTML, actualHTML);
+ }
+
+ @Test
+ public void testAddText() {
+ String expectedHTML = "sample text";
+ String actualHTML = new HTMLHelper().addText("sample text").build();
+ assertEquals(expectedHTML, actualHTML);
+ }
+
+ @Test
+ public void testAddTextWithSize() {
+ String expectedHTML = "sample text";
+ String actualHTML = new HTMLHelper().addTextWithSize("sample text", 5).build();
+ assertEquals(expectedHTML, actualHTML);
+ }
+
+ @Test
+ public void testAddTextWithColour() {
+ String expectedHTML = "sample text";
+ String actualHTML = new HTMLHelper().addTextWithColor("sample text", "red").build();
+ assertEquals(expectedHTML, actualHTML);
+ }
+
+ @Test
+ public void testAddBoldText() {
+ String expectedHTML = "sample text";
+ String actualHTML = new HTMLHelper().addBoldText("sample text").build();
+ assertEquals(expectedHTML, actualHTML);
+ }
+
+ @Test
+ public void testAddLink() {
+ String expectedHTML = "abc";
+ String actualHTML = new HTMLHelper().addLink("abc@example.com", "abc").build();
+ assertEquals(expectedHTML, actualHTML);
+ }
+
+ @Test
+ public void testAddEmailLink() {
+ String expectedHTML = "abc@example.com";
+ String actualHTML = new HTMLHelper().addEmailLink("abc@example.com", "abc@example.com").build();
+ assertEquals(expectedHTML, actualHTML);
+ }
+
+ @Test
+ public void testAddEmailLinkWithSize() {
+ String expectedHTML = " abc@example.com ";
+ String actualHTML = new HTMLHelper().addEmailLinkWithSize("abc@example.com", "abc@example.com", 5).build();
+ assertEquals(expectedHTML, actualHTML);
+ }
+
+ @Test
+ public void addBoldTextWithColour() {
+ String expectedHTML = "sample text";
+ String actualHTML = new HTMLHelper().addBoldTextWithColor("sample text", "red").build();
+ assertEquals(expectedHTML, actualHTML);
+ }
+
+ @Test
+ public void testMultiLineHTML() {
+ String expectedHTML = "Dear John," +
+ "
" +
+ "Here is the update for your submission: " +
+ "
" +
+ "submission id: 12345
" +
+ "Submission Status: UPLOADED
" +
+ "Result: FAILED" +
+ "
";
+ String actualHTMl = new HTMLHelper()
+ .addText("Dear " + "John" + ",")
+ .addGap(1)
+ .addText("Here is the update for your submission: ")
+ .addGap(1)
+ .addText("submission id: " + 12345)
+ .addLineBreak()
+ .addText("Submission Status: " + "UPLOADED")
+ .addLineBreak()
+ .addText("Result: ")
+ .addBoldTextWithColor("FAILED", "red")
+ .addGap(2)
+ .build();
+
+ assertEquals(expectedHTML, actualHTMl);
+ }
+
+}