JAMES-1717 VacationReply should handle htmlBody
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/a8d4723e Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/a8d4723e Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/a8d4723e Branch: refs/heads/master Commit: a8d4723efea191584bcae1a4315588e3a6680944 Parents: aa87790 Author: Benoit Tellier <[email protected]> Authored: Thu Jun 2 09:43:46 2016 +0700 Committer: Benoit Tellier <[email protected]> Committed: Fri Jun 3 19:38:15 2016 +0700 ---------------------------------------------------------------------- .../base/AutomaticallySentMailDetector.java | 3 + .../base/AutomaticallySentMailDetectorImpl.java | 4 +- .../james/jmap/mailet/VacationMailet.java | 2 +- .../apache/james/jmap/mailet/VacationReply.java | 81 ++++++++++++++++---- .../james/jmap/mailet/VacationReplyTest.java | 41 ++++++++-- 5 files changed, 107 insertions(+), 24 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/a8d4723e/mailet/base/src/main/java/org/apache/mailet/base/AutomaticallySentMailDetector.java ---------------------------------------------------------------------- diff --git a/mailet/base/src/main/java/org/apache/mailet/base/AutomaticallySentMailDetector.java b/mailet/base/src/main/java/org/apache/mailet/base/AutomaticallySentMailDetector.java index e47c863..c90fc44 100644 --- a/mailet/base/src/main/java/org/apache/mailet/base/AutomaticallySentMailDetector.java +++ b/mailet/base/src/main/java/org/apache/mailet/base/AutomaticallySentMailDetector.java @@ -25,6 +25,9 @@ import org.apache.mailet.Mail; public interface AutomaticallySentMailDetector { + String AUTO_SUBMITTED_HEADER = "Auto-Submitted"; + String AUTO_REPLIED_VALUE = "auto-replied"; + boolean isAutomaticallySent(Mail mail) throws MessagingException; boolean isMailingList(Mail mail) throws MessagingException; http://git-wip-us.apache.org/repos/asf/james-project/blob/a8d4723e/mailet/base/src/main/java/org/apache/mailet/base/AutomaticallySentMailDetectorImpl.java ---------------------------------------------------------------------- diff --git a/mailet/base/src/main/java/org/apache/mailet/base/AutomaticallySentMailDetectorImpl.java b/mailet/base/src/main/java/org/apache/mailet/base/AutomaticallySentMailDetectorImpl.java index 032556a..72fad65 100644 --- a/mailet/base/src/main/java/org/apache/mailet/base/AutomaticallySentMailDetectorImpl.java +++ b/mailet/base/src/main/java/org/apache/mailet/base/AutomaticallySentMailDetectorImpl.java @@ -60,10 +60,10 @@ public class AutomaticallySentMailDetectorImpl implements AutomaticallySentMailD } public boolean isAutoSubmitted(Mail mail) throws MessagingException { - String[] headers = mail.getMessage().getHeader("Auto-Submitted"); + String[] headers = mail.getMessage().getHeader(AUTO_SUBMITTED_HEADER); if (headers != null) { for (String header : headers) { - if (header.equalsIgnoreCase("auto-replied")) { + if (header.equalsIgnoreCase(AUTO_REPLIED_VALUE)) { return true; } } http://git-wip-us.apache.org/repos/asf/james-project/blob/a8d4723e/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 02258e4..c5ae96a 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 @@ -94,7 +94,7 @@ public class VacationMailet extends GenericMailet { try { VacationReply vacationReply = VacationReply.builder(processedMail) .receivedMailRecipient(recipient) - .reason(vacation.getTextBody()) + .vacation(vacation) .build(); sendNotification(vacationReply); notificationRegistry.register(AccountId.fromString(recipient.toString()), http://git-wip-us.apache.org/repos/asf/james-project/blob/a8d4723e/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/VacationReply.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/VacationReply.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/VacationReply.java index 0638eb6..3b8ae2a 100644 --- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/VacationReply.java +++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/VacationReply.java @@ -19,14 +19,23 @@ package org.apache.james.jmap.mailet; +import java.io.IOException; import java.util.List; import java.util.Optional; +import javax.activation.DataHandler; import javax.mail.MessagingException; +import javax.mail.Multipart; +import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; +import javax.mail.util.ByteArrayDataSource; +import org.apache.james.jmap.api.vacation.Vacation; +import org.apache.james.mime4j.dom.field.ContentTypeField; import org.apache.mailet.Mail; import org.apache.mailet.MailAddress; +import org.apache.mailet.base.AutomaticallySentMailDetector; import com.github.fge.lambdas.Throwing; import com.google.common.base.Preconditions; @@ -34,6 +43,10 @@ import com.google.common.collect.ImmutableList; public class VacationReply { + public static final String FROM_HEADER = "from"; + public static final String TO_HEADER = "to"; + public static final String MIXED = "mixed"; + public static Builder builder(Mail originalMail) { return new Builder(originalMail); } @@ -43,8 +56,7 @@ public class VacationReply { public static final boolean NOT_REPLY_TO_ALL = false; private final Mail originalMail; private MailAddress mailRecipient; - private String reason; - private Optional<String> subject = Optional.empty(); + private Vacation vacation; private Builder(Mail originalMail) { Preconditions.checkNotNull(originalMail, "Origin mail shall not be null"); @@ -57,14 +69,8 @@ public class VacationReply { return this; } - public Builder reason(String reason) { - Preconditions.checkNotNull(reason); - this.reason = reason; - return this; - } - - public Builder subject(Optional<String> subject) { - this.subject = subject; + public Builder vacation(Vacation vacation) { + this.vacation = vacation; return this; } @@ -72,18 +78,63 @@ public class VacationReply { Preconditions.checkState(mailRecipient != null, "Original recipient address should not be null"); Preconditions.checkState(originalMail.getSender() != null, "Original sender address should not be null"); + MimeMessage reply = (MimeMessage) originalMail.getMessage().reply(false); + reply.setContent(generateMultipart()); + return new VacationReply(mailRecipient, ImmutableList.of(originalMail.getSender()), generateMimeMessage()); } private MimeMessage generateMimeMessage() throws MessagingException { MimeMessage reply = (MimeMessage) originalMail.getMessage().reply(NOT_REPLY_TO_ALL); - subject.ifPresent(Throwing.consumer(subjectString -> reply.setHeader("subject", subjectString))); - reply.setText(reason); - reply.setHeader("from", mailRecipient.toString()); - reply.setHeader("to", originalMail.getSender().toString()); - reply.setHeader("Auto-Submitted", "auto-replied"); + vacation.getSubject().ifPresent(Throwing.consumer(subjectString -> reply.setHeader("subject", subjectString))); + reply.setHeader(FROM_HEADER, mailRecipient.toString()); + reply.setHeader(TO_HEADER, originalMail.getSender().toString()); + reply.setHeader(AutomaticallySentMailDetector.AUTO_SUBMITTED_HEADER, AutomaticallySentMailDetector.AUTO_REPLIED_VALUE); + + return addBody(reply); + } + + private MimeMessage addBody(MimeMessage reply) throws MessagingException { + if (! vacation.getHtmlBody().isPresent()) { + reply.setText(vacation.getTextBody().get()); + } else { + reply.setContent(generateMultipart()); + } return reply; } + + + private Multipart generateMultipart() throws MessagingException { + try { + Multipart multipart = new MimeMultipart(MIXED); + addPlainPart(multipart, vacation.getTextBody()); + addHtmlPart(multipart, vacation.getHtmlBody()); + return multipart; + } catch (IOException e) { + throw new MessagingException("Cannot read specified content", e); + } + } + + private Multipart addPlainPart(Multipart multipart, Optional<String> textBody) throws MessagingException, IOException { + textBody.ifPresent(Throwing.consumer(text -> addTextPart(multipart, text, ContentTypeField.TYPE_TEXT_PLAIN))); + return multipart; + } + + private Multipart addHtmlPart(Multipart multipart, Optional<String> htmlBody) throws MessagingException, IOException { + htmlBody.ifPresent(Throwing.consumer(html -> addTextPart(multipart, html, "text/html"))); + return multipart; + } + + private Multipart addTextPart(Multipart multipart, String text, String contentType) throws MessagingException, IOException { + MimeBodyPart textReasonPart = new MimeBodyPart(); + textReasonPart.setDataHandler( + new DataHandler( + new ByteArrayDataSource( + text, + contentType + "; charset=UTF-8"))); + multipart.addBodyPart(textReasonPart); + return multipart; + } } private final MailAddress sender; http://git-wip-us.apache.org/repos/asf/james-project/blob/a8d4723e/server/protocols/jmap/src/test/java/org/apache/james/jmap/mailet/VacationReplyTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/mailet/VacationReplyTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/mailet/VacationReplyTest.java index 93d7ffc..b42c799 100644 --- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/mailet/VacationReplyTest.java +++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/mailet/VacationReplyTest.java @@ -28,6 +28,7 @@ import javax.mail.Session; import javax.mail.internet.MimeMessage; import org.apache.commons.io.IOUtils; +import org.apache.james.jmap.api.vacation.Vacation; import org.apache.mailet.MailAddress; import org.apache.mailet.base.test.FakeMail; import org.junit.Before; @@ -36,7 +37,9 @@ import org.junit.Test; public class VacationReplyTest { public static final String REASON = "I am in vacation dudes !"; - public static final Optional<String> SUBJECT = Optional.of("Vacation subject specified by the user!"); + public static final String HTML_REASON = "<p>I am in vacation dudes !</p>"; + public static final String SUBJECT = "subject"; + private MailAddress originalSender; private MailAddress originalRecipient; private FakeMail mail; @@ -55,19 +58,42 @@ public class VacationReplyTest { public void vacationReplyShouldGenerateASuitableAnswer() throws Exception { VacationReply vacationReply = VacationReply.builder(mail) - .reason(REASON) + .vacation(Vacation.builder() + .enabled(true) + .textBody(REASON) + .htmlBody(HTML_REASON) + .build()) .receivedMailRecipient(originalRecipient) .build(); assertThat(vacationReply.getRecipients()).containsExactly(originalSender); assertThat(vacationReply.getSender()).isEqualTo(originalRecipient); assertThat(IOUtils.toString(vacationReply.getMimeMessage().getInputStream())).contains(REASON); + assertThat(IOUtils.toString(vacationReply.getMimeMessage().getInputStream())).contains(HTML_REASON); + } + + @Test + public void vacationReplyShouldNotBeMultipartWhenVacationHaveNoHTML() throws Exception { + VacationReply vacationReply = VacationReply.builder(mail) + .vacation(Vacation.builder() + .enabled(true) + .textBody(REASON) + .build()) + .receivedMailRecipient(originalRecipient) + .build(); + + assertThat(vacationReply.getRecipients()).containsExactly(originalSender); + assertThat(vacationReply.getSender()).isEqualTo(originalRecipient); + assertThat(IOUtils.toString(vacationReply.getMimeMessage().getInputStream())).isEqualTo(REASON); } @Test public void vacationReplyShouldAddReSuffixToSubjectByDefault() throws Exception { VacationReply vacationReply = VacationReply.builder(mail) - .reason(REASON) + .vacation(Vacation.builder() + .enabled(true) + .textBody(REASON) + .build()) .receivedMailRecipient(originalRecipient) .build(); @@ -77,12 +103,15 @@ public class VacationReplyTest { @Test public void aUserShouldBeAbleToSetTheSubjectOfTheGeneratedMimeMessage() throws Exception { VacationReply vacationReply = VacationReply.builder(mail) - .reason(REASON) - .subject(SUBJECT) + .vacation(Vacation.builder() + .enabled(true) + .textBody(REASON) + .subject(Optional.of(SUBJECT)) + .build()) .receivedMailRecipient(originalRecipient) .build(); - assertThat(vacationReply.getMimeMessage().getHeader("subject")).containsExactly(SUBJECT.get()); + assertThat(vacationReply.getMimeMessage().getHeader("subject")).containsExactly(SUBJECT); } @Test(expected = NullPointerException.class) --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
