You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2018/04/17 03:20:09 UTC

[1/2] james-project git commit: JAMES-2361 implement the mailet that refers to the MDN original Jmap Id

Repository: james-project
Updated Branches:
  refs/heads/master 4e44ec150 -> 2387fd8ee


JAMES-2361 implement the mailet that refers to the MDN original Jmap Id


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/2387fd8e
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/2387fd8e
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/2387fd8e

Branch: refs/heads/master
Commit: 2387fd8ee22ef5586ff50a194fb8f990b94b8ff1
Parents: 8bae242
Author: Matthieu Baechler <ma...@apache.org>
Authored: Fri Apr 6 14:43:46 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Mon Apr 16 15:11:46 2018 +0200

----------------------------------------------------------------------
 .../org/apache/james/mdn/MDNReportParser.java   |   7 +
 .../src/test/resources/mailetcontainer.xml      |   6 +
 .../methods/integration/SendMDNMethodTest.java  |  32 ++--
 .../src/test/resources/mailetcontainer.xml      |   7 +
 .../mailet/ExtractMDNOriginalJMAPMessageId.java | 165 +++++++++++++++++++
 .../ExtractMDNOriginalJMAPMessageIdTest.java    | 106 ++++++++++++
 6 files changed, 309 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/2387fd8e/mdn/src/main/java/org/apache/james/mdn/MDNReportParser.java
----------------------------------------------------------------------
diff --git a/mdn/src/main/java/org/apache/james/mdn/MDNReportParser.java b/mdn/src/main/java/org/apache/james/mdn/MDNReportParser.java
index d002c87..a1dc416 100644
--- a/mdn/src/main/java/org/apache/james/mdn/MDNReportParser.java
+++ b/mdn/src/main/java/org/apache/james/mdn/MDNReportParser.java
@@ -19,8 +19,11 @@
 
 package org.apache.james.mdn;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.Optional;
 
+import org.apache.commons.io.IOUtils;
 import org.apache.james.mdn.action.mode.DispositionActionMode;
 import org.apache.james.mdn.fields.AddressType;
 import org.apache.james.mdn.fields.Disposition;
@@ -46,6 +49,10 @@ public class MDNReportParser {
     public MDNReportParser() {
     }
 
+    public Optional<MDNReport> parse(InputStream is, String charset) throws IOException {
+        return parse(IOUtils.toString(is, charset));
+    }
+
     public Optional<MDNReport> parse(String mdnReport) {
         Parser parser = Parboiled.createParser(MDNReportParser.Parser.class);
         ParsingResult<Object> result = new ReportingParseRunner<>(parser.dispositionNotificationContent()).run(mdnReport);

http://git-wip-us.apache.org/repos/asf/james-project/blob/2387fd8e/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/mailetcontainer.xml
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/mailetcontainer.xml b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/mailetcontainer.xml
index 0698316..b9c4b75 100644
--- a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/mailetcontainer.xml
+++ b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/resources/mailetcontainer.xml
@@ -43,6 +43,11 @@
         </processor>
 
         <processor state="transport" enableJmx="false">
+            <matcher name="mdn-matcher" match="org.apache.james.mailetcontainer.impl.matchers.And">
+                <matcher match="HasMimeType=multipart/report"/>
+                <matcher match="HasMimeTypeParameter=report-type=disposition-notification"/>
+            </matcher>
+
             <mailet match="SMTPAuthSuccessful" class="SetMimeHeader">
                 <name>X-UserIsAuth</name>
                 <value>true</value>
@@ -53,6 +58,7 @@
             <mailet match="All" class="org.apache.james.jmap.mailet.TextCalendarBodyToAttachment"/>
             <mailet match="All" class="RecipientRewriteTable" />
             <mailet match="RecipientIsLocal" class="org.apache.james.jmap.mailet.VacationMailet"/>
+            <mailet match="mdn-matcher" class="org.apache.james.jmap.mailet.ExtractMDNOriginalJMAPMessageId" />
             <mailet match="RecipientIsLocal" class="Sieve"/>
             <mailet match="RecipientIsLocal" class="SpamAssassin">
                 <onMailetException>ignore</onMailetException>

http://git-wip-us.apache.org/repos/asf/james-project/blob/2387fd8e/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SendMDNMethodTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SendMDNMethodTest.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SendMDNMethodTest.java
index e283bd4..65422f5 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SendMDNMethodTest.java
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SendMDNMethodTest.java
@@ -63,6 +63,7 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import com.google.common.collect.Iterables;
 import com.jayway.restassured.RestAssured;
 import com.jayway.restassured.parsing.Parser;
 
@@ -100,7 +101,7 @@ public abstract class SendMDNMethodTest {
         bartAccessToken = authenticateJamesUser(baseUri(jmapServer), BART, BOB_PASSWORD);
     }
 
-    private void bartSendMessageToHomer() {
+    private String bartSendMessageToHomer() {
         String messageCreationId = "creationId";
         String outboxId = getOutboxId(bartAccessToken);
         String requestBody = "[" +
@@ -121,7 +122,7 @@ public abstract class SendMDNMethodTest {
             "  ]" +
             "]";
 
-        with()
+        String id = with()
             .header("Authorization", bartAccessToken.serialize())
             .body(requestBody)
             .post("/jmap")
@@ -131,6 +132,7 @@ public abstract class SendMDNMethodTest {
             .path(ARGUMENTS + ".created." + messageCreationId + ".id");
 
         calmlyAwait.until(() -> !listMessageIdsForAccount(homerAccessToken).isEmpty());
+        return id;
     }
 
     private void sendAWrongInitialMessage() {
@@ -276,9 +278,9 @@ public abstract class SendMDNMethodTest {
 
     @Test
     public void sendMDNShouldSendAMDNBackToTheOriginalMessageAuthor() {
-        bartSendMessageToHomer();
+        String bartSentJmapMessageId = bartSendMessageToHomer();
 
-        List<String> messageIds = listMessageIdsForAccount(homerAccessToken);
+        String homerReceivedMessageId = Iterables.getOnlyElement(listMessageIdsForAccount(homerAccessToken));
 
         // HOMER sends a MDN back to BART
         String creationId = "creation-1";
@@ -286,7 +288,7 @@ public abstract class SendMDNMethodTest {
             .header("Authorization", homerAccessToken.serialize())
             .body("[[\"setMessages\", {\"sendMDN\": {" +
                 "\"" + creationId + "\":{" +
-                "    \"messageId\":\"" + messageIds.get(0) + "\"," +
+                "    \"messageId\":\"" + homerReceivedMessageId + "\"," +
                 "    \"subject\":\"subject\"," +
                 "    \"textBody\":\"Read confirmation\"," +
                 "    \"reportingUA\":\"reportingUA\"," +
@@ -301,22 +303,24 @@ public abstract class SendMDNMethodTest {
 
         // BART should have received it
         calmlyAwait.until(() -> !listMessageIdsInMailbox(bartAccessToken, getInboxId(bartAccessToken)).isEmpty());
-        List<String> bobInboxMessageIds = listMessageIdsInMailbox(bartAccessToken, getInboxId(bartAccessToken));
+        String bartInboxMessageIds = Iterables.getOnlyElement(listMessageIdsInMailbox(bartAccessToken, getInboxId(bartAccessToken)));
 
+        String firstMessage = ARGUMENTS + ".list[0]";
         given()
             .header("Authorization", bartAccessToken.serialize())
-            .body("[[\"getMessages\", {\"ids\": [\"" + bobInboxMessageIds.get(0) + "\"]}, \"#0\"]]")
+            .body("[[\"getMessages\", {\"ids\": [\"" + bartInboxMessageIds + "\"]}, \"#0\"]]")
         .when()
             .post("/jmap")
         .then()
             .statusCode(200)
-            .body(ARGUMENTS + ".list[0].from.email", is(HOMER))
-            .body(ARGUMENTS + ".list[0].to.email", contains(BART))
-            .body(ARGUMENTS + ".list[0].hasAttachment", is(true))
-            .body(ARGUMENTS + ".list[0].textBody", is("Read confirmation"))
-            .body(ARGUMENTS + ".list[0].subject", is("subject"))
-            .body(ARGUMENTS + ".list[0].headers.Content-Type", startsWith("multipart/report;"))
-            .body(ARGUMENTS + ".list[0].attachments[0].type", startsWith("message/disposition-notification"));
+            .body(firstMessage + ".from.email", is(HOMER))
+            .body(firstMessage + ".to.email", contains(BART))
+            .body(firstMessage + ".hasAttachment", is(true))
+            .body(firstMessage + ".textBody", is("Read confirmation"))
+            .body(firstMessage + ".subject", is("subject"))
+            .body(firstMessage + ".headers.Content-Type", startsWith("multipart/report;"))
+            .body(firstMessage + ".headers.X-JAMES-MDN-JMAP-MESSAGE-ID", equalTo(bartSentJmapMessageId))
+            .body(firstMessage + ".attachments[0].type", startsWith("message/disposition-notification"));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/james-project/blob/2387fd8e/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/mailetcontainer.xml
----------------------------------------------------------------------
diff --git a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/mailetcontainer.xml b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/mailetcontainer.xml
index fdbe341..878b948 100644
--- a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/mailetcontainer.xml
+++ b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/resources/mailetcontainer.xml
@@ -30,6 +30,7 @@
     </spooler>
 
     <processors>
+
         <processor state="root" enableJmx="false">
             <mailet match="All" class="PostmasterAlias"/>
             <mailet match="RelayLimit=30" class="Null"/>
@@ -43,6 +44,11 @@
         </processor>
 
         <processor state="transport" enableJmx="false">
+            <matcher name="mdn-matcher" match="org.apache.james.mailetcontainer.impl.matchers.And">
+                <matcher match="HasMimeType=multipart/report"/>
+                <matcher match="HasMimeTypeParameter=report-type=disposition-notification"/>
+            </matcher>
+
             <mailet match="SMTPAuthSuccessful" class="SetMimeHeader">
                 <name>X-UserIsAuth</name>
                 <value>true</value>
@@ -53,6 +59,7 @@
             <mailet match="All" class="org.apache.james.jmap.mailet.TextCalendarBodyToAttachment"/>
             <mailet match="All" class="RecipientRewriteTable" />
             <mailet match="RecipientIsLocal" class="org.apache.james.jmap.mailet.VacationMailet"/>
+            <mailet match="mdn-matcher" class="org.apache.james.jmap.mailet.ExtractMDNOriginalJMAPMessageId" />
             <mailet match="RecipientIsLocal" class="Sieve"/>
             <mailet match="RecipientIsLocal" class="SpamAssassin">
                 <onMailetException>ignore</onMailetException>

http://git-wip-us.apache.org/repos/asf/james-project/blob/2387fd8e/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/ExtractMDNOriginalJMAPMessageId.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/ExtractMDNOriginalJMAPMessageId.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/ExtractMDNOriginalJMAPMessageId.java
new file mode 100644
index 0000000..06cc2e5
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/ExtractMDNOriginalJMAPMessageId.java
@@ -0,0 +1,165 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+package org.apache.james.jmap.mailet;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Optional;
+
+import javax.inject.Inject;
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.james.core.MailAddress;
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MessageId;
+import org.apache.james.mailbox.model.MultimailboxesSearchQuery;
+import org.apache.james.mailbox.model.SearchQuery;
+import org.apache.james.mdn.MDNReport;
+import org.apache.james.mdn.MDNReportParser;
+import org.apache.james.mdn.fields.OriginalMessageId;
+import org.apache.james.mime4j.dom.Entity;
+import org.apache.james.mime4j.dom.Message;
+import org.apache.james.mime4j.dom.Multipart;
+import org.apache.james.mime4j.dom.SingleBody;
+import org.apache.james.mime4j.message.DefaultMessageBuilder;
+import org.apache.mailet.Mail;
+import org.apache.mailet.base.GenericMailet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Iterables;
+
+/**
+ * This mailet handles MDN messages and define a header X-JAMES-MDN-JMAP-MESSAGE-ID referencing
+ * the original message (by its Jmap Id) asking for the recipient to send an MDN.
+ */
+public class ExtractMDNOriginalJMAPMessageId extends GenericMailet {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ExtractMDNOriginalJMAPMessageId.class);
+
+    private static final String MESSAGE_DISPOSITION_NOTIFICATION = "message/disposition-notification";
+    private static final String X_JAMES_MDN_JMAP_MESSAGE_ID = "X-JAMES-MDN-JMAP-MESSAGE-ID";
+
+    private final MailboxManager mailboxManager;
+
+    @Inject
+    public ExtractMDNOriginalJMAPMessageId(MailboxManager mailboxManager) {
+        this.mailboxManager = mailboxManager;
+    }
+
+    @Override
+    public void service(Mail mail) throws MessagingException {
+        if (mail.getRecipients().size() != 1) {
+            LOGGER.warn("MDN should only be sent to a single recipient");
+            return;
+        }
+        MailAddress recipient = Iterables.getOnlyElement(mail.getRecipients());
+        MimeMessage mimeMessage = mail.getMessage();
+
+        findReport(mimeMessage)
+            .flatMap(this::parseReport)
+            .flatMap(MDNReport::getOriginalMessageIdField)
+            .map(OriginalMessageId::getOriginalMessageId)
+            .flatMap(messageId -> findMessageIdForRFC822MessageId(messageId, recipient))
+            .ifPresent(messageId -> setJmapMessageIdAsHeader(mimeMessage, messageId));
+    }
+
+    private void setJmapMessageIdAsHeader(MimeMessage mimeMessage, MessageId messageId) {
+        try {
+            mimeMessage.addHeader(X_JAMES_MDN_JMAP_MESSAGE_ID, messageId.serialize());
+        } catch (MessagingException e) {
+            LOGGER.error("unable to add " + X_JAMES_MDN_JMAP_MESSAGE_ID + " header to message", e);
+        }
+    }
+
+    private Optional<MessageId> findMessageIdForRFC822MessageId(String messageId, MailAddress recipient) {
+        try {
+            MailboxSession session = mailboxManager.createSystemSession(recipient.asString());
+            int limit = 1;
+            MultimailboxesSearchQuery searchByRFC822MessageId = MultimailboxesSearchQuery
+                .from(new SearchQuery(SearchQuery.mimeMessageID(messageId)))
+                .build();
+            return mailboxManager.search(searchByRFC822MessageId, session, limit).stream().findFirst();
+        } catch (MailboxException e) {
+            LOGGER.error("unable to find message with Message-Id: " + messageId, e);
+        }
+        return Optional.empty();
+    }
+
+    private Optional<MDNReport> parseReport(Entity report) {
+        try {
+            return new MDNReportParser().parse(((SingleBody)report.getBody()).getInputStream(), report.getCharset());
+        } catch (IOException e) {
+            LOGGER.error("unable to parse MESSAGE_DISPOSITION_NOTIFICATION part", e);
+            return Optional.empty();
+        }
+    }
+
+    private Optional<Entity> findReport(MimeMessage mimeMessage) {
+        return parseMessage(mimeMessage).flatMap(this::extractReport);
+    }
+
+    @VisibleForTesting Optional<Entity> extractReport(Message message) {
+        if (!message.isMultipart()) {
+            LOGGER.debug("MDN Message must be multipart");
+            return Optional.empty();
+        }
+        List<Entity> bodyParts = ((Multipart) message.getBody()).getBodyParts();
+        if (bodyParts.size() < 2) {
+            LOGGER.debug("MDN Message must contain at least two parts");
+            return Optional.empty();
+        }
+        Entity report = bodyParts.get(1);
+        if (!isDispositionNotification(report)) {
+            LOGGER.debug("MDN Message second part must be of type " + MESSAGE_DISPOSITION_NOTIFICATION);
+            return Optional.empty();
+        }
+        return Optional.of(report);
+    }
+
+    private boolean isDispositionNotification(Entity entity) {
+        return entity
+            .getMimeType()
+            .startsWith(MESSAGE_DISPOSITION_NOTIFICATION);
+    }
+
+    private Optional<Message> parseMessage(MimeMessage mimeMessage) {
+        try {
+            ByteArrayOutputStream os = new ByteArrayOutputStream();
+            mimeMessage.writeTo(os);
+            Message message = new DefaultMessageBuilder().parseMessage(new ByteArrayInputStream(os.toByteArray()));
+            return Optional.of(message);
+        } catch (IOException | MessagingException e) {
+            LOGGER.error("unable to parse message", e);
+            return Optional.empty();
+        }
+    }
+
+    @Override
+    public String getMailetInfo() {
+        return "ExtractMDNOriginalJMAPMessageId";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/2387fd8e/server/protocols/jmap/src/test/java/org/apache/james/jmap/mailet/ExtractMDNOriginalJMAPMessageIdTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/mailet/ExtractMDNOriginalJMAPMessageIdTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/mailet/ExtractMDNOriginalJMAPMessageIdTest.java
new file mode 100644
index 0000000..0c7ce1d
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/mailet/ExtractMDNOriginalJMAPMessageIdTest.java
@@ -0,0 +1,106 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.jmap.mailet;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mime4j.dom.Message;
+import org.apache.james.mime4j.message.BodyPart;
+import org.apache.james.mime4j.message.BodyPartBuilder;
+import org.apache.james.mime4j.message.MultipartBuilder;
+import org.apache.james.mime4j.message.SingleBodyBuilder;
+import org.junit.Test;
+
+public class ExtractMDNOriginalJMAPMessageIdTest {
+
+    @Test
+    public void extractReportShouldRejectNonMultipartMessage() throws IOException {
+        ExtractMDNOriginalJMAPMessageId testee = new ExtractMDNOriginalJMAPMessageId(mock(MailboxManager.class));
+
+        Message message = Message.Builder.of()
+            .setBody("content", StandardCharsets.UTF_8)
+            .build();
+
+        assertThat(testee.extractReport(message)).isEmpty();
+    }
+
+    @Test
+    public void extractReportShouldRejectMultipartWithSinglePart() throws Exception {
+        ExtractMDNOriginalJMAPMessageId testee = new ExtractMDNOriginalJMAPMessageId(mock(MailboxManager.class));
+
+        Message message = Message.Builder.of()
+            .setBody(
+                MultipartBuilder.create()
+                    .setSubType("report")
+                    .addTextPart("content", StandardCharsets.UTF_8)
+                    .build())
+            .build();
+
+        assertThat(testee.extractReport(message)).isEmpty();
+    }
+
+    @Test
+    public void extractReportShouldRejectSecondPartWithBadContentType() throws IOException {
+        ExtractMDNOriginalJMAPMessageId testee = new ExtractMDNOriginalJMAPMessageId(mock(MailboxManager.class));
+
+        Message message = Message.Builder.of()
+            .setBody(MultipartBuilder.create()
+                .setSubType("report")
+                .addTextPart("first", StandardCharsets.UTF_8)
+                .addTextPart("second", StandardCharsets.UTF_8)
+                .build())
+            .build();
+
+        assertThat(testee.extractReport(message)).isEmpty();
+    }
+
+    @Test
+    public void extractReportShouldExtractMDNWhenValidMDN() throws IOException {
+        ExtractMDNOriginalJMAPMessageId testee = new ExtractMDNOriginalJMAPMessageId(mock(MailboxManager.class));
+
+        BodyPart mdn = BodyPartBuilder
+            .create()
+            .setBody(SingleBodyBuilder.create()
+                .setText(
+                    "Reporting-UA: linagora.com; Evolution 3.26.5-1+b1 \n" +
+                        "Final-Recipient: rfc822; homer@linagora.com\n" +
+                        "Original-Message-ID: <15...@apache.org>\n" +
+                        "Disposition: manual-action/MDN-sent-manually;displayed\n")
+                .buildText())
+            .setContentType("message/disposition-notification")
+            .build();
+
+        Message message = Message.Builder.of()
+            .setBody(MultipartBuilder.create("report")
+                .addTextPart("first", StandardCharsets.UTF_8)
+                .addBodyPart(mdn)
+                .build())
+            .build();
+
+        assertThat(testee.extractReport(message))
+            .isNotEmpty()
+            .contains(mdn);
+    }
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[2/2] james-project git commit: JAMES-2361 mime4j MDN report must include the right disposition

Posted by bt...@apache.org.
JAMES-2361 mime4j MDN report must include the right disposition


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/8bae242a
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/8bae242a
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/8bae242a

Branch: refs/heads/master
Commit: 8bae242a05473b33d47765aa04af812e56ec86e7
Parents: 4e44ec1
Author: Matthieu Baechler <ma...@apache.org>
Authored: Fri Apr 6 15:11:19 2018 +0200
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Mon Apr 16 15:11:46 2018 +0200

----------------------------------------------------------------------
 mdn/src/main/java/org/apache/james/mdn/MDN.java     | 1 +
 mdn/src/test/java/org/apache/james/mdn/MDNTest.java | 6 ++----
 2 files changed, 3 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/8bae242a/mdn/src/main/java/org/apache/james/mdn/MDN.java
----------------------------------------------------------------------
diff --git a/mdn/src/main/java/org/apache/james/mdn/MDN.java b/mdn/src/main/java/org/apache/james/mdn/MDN.java
index 082c6ce..02e1ac4 100644
--- a/mdn/src/main/java/org/apache/james/mdn/MDN.java
+++ b/mdn/src/main/java/org/apache/james/mdn/MDN.java
@@ -136,6 +136,7 @@ public class MDN {
 
     private Multipart asMime4JMultipart() throws IOException {
         MultipartBuilder builder = MultipartBuilder.create(REPORT_SUB_TYPE);
+        builder.addContentTypeParameter(new NameValuePair("report-type", DISPOSITION_NOTIFICATION_REPORT_TYPE));
         builder.addBodyPart(BodyPartBuilder.create()
             .use(new BasicBodyFactory())
             .setBody(humanReadableText, Charsets.UTF_8)

http://git-wip-us.apache.org/repos/asf/james-project/blob/8bae242a/mdn/src/test/java/org/apache/james/mdn/MDNTest.java
----------------------------------------------------------------------
diff --git a/mdn/src/test/java/org/apache/james/mdn/MDNTest.java b/mdn/src/test/java/org/apache/james/mdn/MDNTest.java
index 6decac0..905a209 100644
--- a/mdn/src/test/java/org/apache/james/mdn/MDNTest.java
+++ b/mdn/src/test/java/org/apache/james/mdn/MDNTest.java
@@ -33,7 +33,6 @@ import org.apache.james.mdn.sending.mode.DispositionSendingMode;
 import org.apache.james.mdn.type.DispositionType;
 import org.apache.james.mime4j.dom.Message;
 import org.apache.james.mime4j.message.DefaultMessageWriter;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -73,7 +72,7 @@ public class MDNTest {
 
         assertThat(new String(byteArrayOutputStream.toByteArray(), StandardCharsets.UTF_8))
             .containsPattern(
-                Pattern.compile("Content-Type: multipart/report;.*report-type=disposition-notification", Pattern.DOTALL));
+                Pattern.compile("Content-Type: multipart/report;.*(\r\n.+)*report-type=disposition-notification.*\r\n\r\n"));
     }
 
     @Test
@@ -211,7 +210,6 @@ public class MDNTest {
     }
 
 
-    @Ignore("Content-Type Parameters are not supported by mime4j")
     @Test
     public void mime4JMessageExportShouldGenerateExpectedContentType() throws Exception {
         Message message = MDN.builder()
@@ -222,7 +220,7 @@ public class MDNTest {
             .build();
 
         assertThat(asString(message))
-            .containsPattern(Pattern.compile("Content-Type: multipart/report;.*report-type=disposition-notification", Pattern.DOTALL));
+            .containsPattern(Pattern.compile("Content-Type: multipart/report;.*(\r\n.+)*report-type=disposition-notification.*(\r\n.+)*\r\n\r\n"));
     }
 
     private String asString(Message message) throws Exception {


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org