JAMES-1717 We should avoid a read to Cassandra if the mail is automatically sent
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/a05bcee7 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/a05bcee7 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/a05bcee7 Branch: refs/heads/master Commit: a05bcee71442c6a3c3a7e9153b29024ef9e6c07c Parents: 9eec8d9 Author: Benoit Tellier <btell...@linagora.com> Authored: Wed May 25 11:45:35 2016 +0700 Committer: Benoit Tellier <btell...@linagora.com> Committed: Fri May 27 18:03:29 2016 +0700 ---------------------------------------------------------------------- .../james/jmap/mailet/VacationMailet.java | 44 +++--- .../james/jmap/mailet/VacationMailetTest.java | 133 +++---------------- 2 files changed, 37 insertions(+), 140 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/a05bcee7/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/VacationMailet.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/VacationMailet.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/VacationMailet.java index 374336b..02258e4 100644 --- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/VacationMailet.java +++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/VacationMailet.java @@ -59,11 +59,13 @@ public class VacationMailet extends GenericMailet { @Override public void service(Mail mail) { try { - ZonedDateTime processingDate = zonedDateTimeProvider.get(); - mail.getRecipients() - .stream() - .map(mailAddress -> manageVacation(mailAddress, mail, processingDate)) - .forEach(CompletableFuture::join); + if (! automaticallySentMailDetector.isAutomaticallySent(mail)) { + ZonedDateTime processingDate = zonedDateTimeProvider.get(); + mail.getRecipients() + .stream() + .map(mailAddress -> manageVacation(mailAddress, mail, processingDate)) + .forEach(CompletableFuture::join); + } } catch (Throwable e) { LOGGER.warn("Can not process vacation for one or more recipients in {}", mail.getRecipients(), e); } @@ -72,34 +74,20 @@ public class VacationMailet extends GenericMailet { public CompletableFuture<Void> manageVacation(MailAddress recipient, Mail processedMail, ZonedDateTime processingDate) { AccountId accountId = AccountId.fromString(recipient.toString()); CompletableFuture<Vacation> vacationFuture = vacationRepository.retrieveVacation(accountId); - return vacationFuture.thenAccept(vacation -> { - if (shouldSendNotification(vacation, processedMail, recipient, processingDate)) { + CompletableFuture<Boolean> hasAlreadyBeenSent = notificationRegistry.isRegistered( + AccountId.fromString(recipient.toString()), + RecipientId.fromMailAddress(processedMail.getSender())); + + return vacationFuture.thenAcceptBoth(hasAlreadyBeenSent, (vacation, alreadySent) -> { + if (shouldSendNotification(vacation, processingDate, alreadySent)) { sendNotification(recipient, processedMail, vacation); } }); } - private boolean shouldSendNotification(Vacation vacation, Mail processedMail, MailAddress recipient, ZonedDateTime processingDate) { - try { - return vacation.isActiveAtDate(processingDate) - && ! automaticallySentMailDetector.isAutomaticallySent(processedMail) - && hasNotSentNotificationsYet(processedMail, recipient); - } catch (MessagingException e) { - LOGGER.warn("Failed detect automatic response in a mail from {} to {}", processedMail.getSender(), recipient, e); - return false; - } - } - - private boolean hasNotSentNotificationsYet(Mail processedMail, MailAddress recipient) { - CompletableFuture<Boolean> hasAlreadyBeenSent = notificationRegistry.isRegistered( - AccountId.fromString(recipient.toString()), - RecipientId.fromMailAddress(processedMail.getSender())); - try { - return !hasAlreadyBeenSent.join(); - } catch (Throwable t) { - LOGGER.warn("Error while checking registration state of vacation notification for user {} and sender {}", recipient, processedMail.getSender(), t); - return true; - } + private boolean shouldSendNotification(Vacation vacation, ZonedDateTime processingDate, boolean alreadySent) { + return vacation.isActiveAtDate(processingDate) + && ! alreadySent; } private void sendNotification(MailAddress recipient, Mail processedMail, Vacation vacation) { http://git-wip-us.apache.org/repos/asf/james-project/blob/a05bcee7/server/protocols/jmap/src/test/java/org/apache/james/jmap/mailet/VacationMailetTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/mailet/VacationMailetTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/mailet/VacationMailetTest.java index 1de142a..f3047e4 100644 --- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/mailet/VacationMailetTest.java +++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/mailet/VacationMailetTest.java @@ -54,9 +54,15 @@ public class VacationMailetTest { public static final ZonedDateTime DATE_TIME_2016 = ZonedDateTime.parse("2016-10-09T08:07:06+07:00[Asia/Vientiane]"); public static final ZonedDateTime DATE_TIME_2017 = ZonedDateTime.parse("2017-10-09T08:07:06+07:00[Asia/Vientiane]"); public static final ZonedDateTime DATE_TIME_2018 = ZonedDateTime.parse("2018-10-09T08:07:06+07:00[Asia/Vientiane]"); - public static final String USERNAME = "be...@apache.org"; public static final AccountId ACCOUNT_ID = AccountId.fromString(USERNAME); + public static final Vacation VACATION = Vacation.builder() + .enabled(true) + .fromDate(Optional.of(DATE_TIME_2016)) + .toDate(Optional.of(DATE_TIME_2018)) + .textBody("Explaining my vacation") + .build(); + private VacationMailet testee; private VacationRepository vacationRepository; private ZonedDateTimeProvider zonedDateTimeProvider; @@ -66,12 +72,18 @@ public class VacationMailetTest { private AutomaticallySentMailDetector automaticallySentMailDetector; private NotificationRegistry notificationRegistry; private RecipientId recipientId; + private FakeMail mail; @Before public void setUp() throws Exception { originalSender = new MailAddress("dist...@apache.org"); originalRecipient = new MailAddress(USERNAME); recipientId = RecipientId.fromMailAddress(originalSender); + mail = FakeMail.builder() + .fileName("spamMail.eml") + .recipient(originalRecipient) + .sender(originalSender) + .build(); vacationRepository = mock(VacationRepository.class); zonedDateTimeProvider = mock(ZonedDateTimeProvider.class); @@ -84,11 +96,6 @@ public class VacationMailetTest { @Test public void unactivatedVacationShouldNotSendNotification() throws Exception { - FakeMail mail = FakeMail.builder() - .fileName("spamMail.eml") - .recipient(originalRecipient) - .sender(new MailAddress("owner-l...@any.com")) - .build(); when(zonedDateTimeProvider.get()).thenReturn(DATE_TIME_2017); when(vacationRepository.retrieveVacation(AccountId.fromString(USERNAME))) .thenReturn(CompletableFuture.completedFuture(VacationRepository.DEFAULT_VACATION)); @@ -101,19 +108,8 @@ public class VacationMailetTest { @Test public void activateVacationShouldSendNotification() throws Exception { - FakeMail mail = FakeMail.builder() - .fileName("spamMail.eml") - .recipient(originalRecipient) - .sender(originalSender) - .build(); when(vacationRepository.retrieveVacation(AccountId.fromString(USERNAME))) - .thenReturn(CompletableFuture.completedFuture( - Vacation.builder() - .enabled(true) - .fromDate(Optional.of(DATE_TIME_2016)) - .toDate(Optional.of(DATE_TIME_2018)) - .textBody("Explaining my vacation") - .build())); + .thenReturn(CompletableFuture.completedFuture(VACATION)); when(zonedDateTimeProvider.get()).thenReturn(DATE_TIME_2017); when(automaticallySentMailDetector.isAutomaticallySent(mail)).thenReturn(false); when(notificationRegistry.isRegistered(ACCOUNT_ID, recipientId)) @@ -129,19 +125,8 @@ public class VacationMailetTest { @Test public void activateVacationShouldNotSendNotificationIfAlreadySent() throws Exception { - FakeMail mail = FakeMail.builder() - .fileName("spamMail.eml") - .recipient(originalRecipient) - .sender(originalSender) - .build(); when(vacationRepository.retrieveVacation(AccountId.fromString(USERNAME))) - .thenReturn(CompletableFuture.completedFuture( - Vacation.builder() - .enabled(true) - .fromDate(Optional.of(DATE_TIME_2016)) - .toDate(Optional.of(DATE_TIME_2018)) - .textBody("Explaining my vacation") - .build())); + .thenReturn(CompletableFuture.completedFuture(VACATION)); when(zonedDateTimeProvider.get()).thenReturn(DATE_TIME_2017); when(notificationRegistry.isRegistered(ACCOUNT_ID, recipientId)) .thenReturn(CompletableFuture.completedFuture(true)); @@ -153,19 +138,8 @@ public class VacationMailetTest { @Test public void activateVacationShouldSendNotificationIfErrorUpdatingNotificationRepository() throws Exception { - FakeMail mail = FakeMail.builder() - .fileName("spamMail.eml") - .recipient(originalRecipient) - .sender(originalSender) - .build(); when(vacationRepository.retrieveVacation(AccountId.fromString(USERNAME))) - .thenReturn(CompletableFuture.completedFuture( - Vacation.builder() - .enabled(true) - .fromDate(Optional.of(DATE_TIME_2016)) - .toDate(Optional.of(DATE_TIME_2018)) - .textBody("Explaining my vacation") - .build())); + .thenReturn(CompletableFuture.completedFuture(VACATION)); when(zonedDateTimeProvider.get()).thenReturn(DATE_TIME_2017); RecipientId recipientId = RecipientId.fromMailAddress(originalSender); when(notificationRegistry.isRegistered(ACCOUNT_ID, recipientId)) @@ -180,19 +154,8 @@ public class VacationMailetTest { @Test public void activateVacationShouldSendNotificationIfErrorRetrievingNotificationRepository() throws Exception { - FakeMail mail = FakeMail.builder() - .fileName("spamMail.eml") - .recipient(originalRecipient) - .sender(originalSender) - .build(); when(vacationRepository.retrieveVacation(AccountId.fromString(USERNAME))) - .thenReturn(CompletableFuture.completedFuture( - Vacation.builder() - .enabled(true) - .fromDate(Optional.of(DATE_TIME_2016)) - .toDate(Optional.of(DATE_TIME_2018)) - .textBody("Explaining my vacation") - .build())); + .thenReturn(CompletableFuture.completedFuture(VACATION)); when(zonedDateTimeProvider.get()).thenReturn(DATE_TIME_2017); RecipientId recipientId = RecipientId.fromMailAddress(originalSender); when(notificationRegistry.isRegistered(ACCOUNT_ID, recipientId)) @@ -205,23 +168,8 @@ public class VacationMailetTest { @Test public void activateVacationShouldNotSendNotificationToMailingList() throws Exception { - FakeMail mail = FakeMail.builder() - .fileName("spamMail.eml") - .recipient(originalRecipient) - .sender(new MailAddress("owner-l...@any.com")) - .build(); - when(vacationRepository.retrieveVacation(AccountId.fromString(USERNAME))) - .thenReturn(CompletableFuture.completedFuture( - Vacation.builder() - .enabled(true) - .fromDate(Optional.of(DATE_TIME_2016)) - .toDate(Optional.of(DATE_TIME_2018)) - .textBody("Explaining my vacation") - .build())); when(zonedDateTimeProvider.get()).thenReturn(DATE_TIME_2017); when(automaticallySentMailDetector.isAutomaticallySent(mail)).thenReturn(true); - when(notificationRegistry.isRegistered(ACCOUNT_ID, RecipientId.fromMailAddress(originalSender))) - .thenReturn(CompletableFuture.completedFuture(false)); testee.service(mail); @@ -240,21 +188,9 @@ public class VacationMailetTest { .sender(originalSender) .build(); when(vacationRepository.retrieveVacation(AccountId.fromString(USERNAME))) - .thenReturn(CompletableFuture.completedFuture( - Vacation.builder() - .enabled(true) - .fromDate(Optional.of(DATE_TIME_2016)) - .toDate(Optional.of(DATE_TIME_2018)) - .textBody("Explaining my vacation") - .build())); + .thenReturn(CompletableFuture.completedFuture(VACATION)); when(vacationRepository.retrieveVacation(secondAccountId)) - .thenReturn(CompletableFuture.completedFuture( - Vacation.builder() - .enabled(true) - .fromDate(Optional.of(DATE_TIME_2016)) - .toDate(Optional.of(DATE_TIME_2018)) - .textBody("Explaining my vacation") - .build())); + .thenReturn(CompletableFuture.completedFuture(VACATION)); when(zonedDateTimeProvider.get()).thenReturn(DATE_TIME_2017); when(automaticallySentMailDetector.isAutomaticallySent(mail)).thenReturn(false); when(notificationRegistry.isRegistered(ACCOUNT_ID, RecipientId.fromMailAddress(originalSender))) @@ -271,11 +207,6 @@ public class VacationMailetTest { @Test public void serviceShouldNotSendNotificationUponErrorsRetrievingVacationObject() throws Exception { - FakeMail mail = FakeMail.builder() - .fileName("spamMail.eml") - .recipient(originalRecipient) - .sender(new MailAddress("owner-l...@any.com")) - .build(); when(vacationRepository.retrieveVacation(AccountId.fromString(USERNAME))) .thenReturn(CompletableFuture.supplyAsync(() -> { throw new RuntimeException(); @@ -290,19 +221,8 @@ public class VacationMailetTest { @Test public void serviceShouldNotSendNotificationUponErrorsDetectingAutomaticallySentMails() throws Exception { - FakeMail mail = FakeMail.builder() - .fileName("spamMail.eml") - .recipient(originalRecipient) - .sender(originalSender) - .build(); when(vacationRepository.retrieveVacation(AccountId.fromString(USERNAME))) - .thenReturn(CompletableFuture.completedFuture( - Vacation.builder() - .enabled(true) - .fromDate(Optional.of(DATE_TIME_2016)) - .toDate(Optional.of(DATE_TIME_2018)) - .textBody("Explaining my vacation") - .build())); + .thenReturn(CompletableFuture.completedFuture(VACATION)); when(zonedDateTimeProvider.get()).thenReturn(DATE_TIME_2017); when(automaticallySentMailDetector.isAutomaticallySent(mail)).thenThrow(new MessagingException()); @@ -313,19 +233,8 @@ public class VacationMailetTest { @Test public void serviceShouldNotPropagateExceptionIfSendFails() throws Exception { - FakeMail mail = FakeMail.builder() - .fileName("spamMail.eml") - .recipient(originalRecipient) - .sender(originalSender) - .build(); when(vacationRepository.retrieveVacation(AccountId.fromString(USERNAME))) - .thenReturn(CompletableFuture.completedFuture( - Vacation.builder() - .enabled(true) - .fromDate(Optional.of(DATE_TIME_2016)) - .toDate(Optional.of(DATE_TIME_2018)) - .textBody("Explaining my vacation") - .build())); + .thenReturn(CompletableFuture.completedFuture(VACATION)); when(zonedDateTimeProvider.get()).thenReturn(DATE_TIME_2017); when(automaticallySentMailDetector.isAutomaticallySent(mail)).thenReturn(false); when(notificationRegistry.isRegistered(ACCOUNT_ID, RecipientId.fromMailAddress(originalSender))) --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org