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 2017/09/01 01:18:40 UTC

[27/27] james-project git commit: JAMES-2132 Reject empty and folding white space values + trim where relevant

JAMES-2132 Reject empty and folding white space values + trim where relevant


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

Branch: refs/heads/master
Commit: 8d9287ff92e6722e210227bbf52978d450374645
Parents: 599bec3
Author: benwa <bt...@linagora.com>
Authored: Thu Aug 31 09:26:06 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Fri Sep 1 08:16:14 2017 +0700

----------------------------------------------------------------------
 .../java/org/apache/james/mdn/Constants.java    | 24 -----
 mdn/src/main/java/org/apache/james/mdn/MDN.java |  4 +-
 .../apache/james/mdn/fields/AddressType.java    | 60 ++++++++++++
 .../apache/james/mdn/fields/FinalRecipient.java | 15 +--
 .../org/apache/james/mdn/fields/Gateway.java    | 12 +--
 .../james/mdn/fields/OriginalMessageId.java     |  4 +-
 .../james/mdn/fields/OriginalRecipient.java     | 16 ++--
 .../james/mdn/fields/ReportingUserAgent.java    | 11 ++-
 .../java/org/apache/james/mdn/fields/Text.java  |  5 +-
 .../james/mdn/modifier/DispositionModifier.java |  5 +-
 .../james/mdn/MDNReportFormattingTest.java      | 13 +--
 .../test/java/org/apache/james/mdn/MDNTest.java | 74 +++++++++++----
 .../james/mdn/fields/AddressTypeTest.java       | 99 ++++++++++++++++++++
 .../james/mdn/fields/FinalRecipientTest.java    | 17 +---
 .../apache/james/mdn/fields/GatewayTest.java    | 16 +---
 .../james/mdn/fields/OriginalMessageIdTest.java | 37 ++++++++
 .../james/mdn/fields/OriginalRecipientTest.java |  9 +-
 .../mdn/fields/ReportingUserAgentTest.java      | 64 +++++++++++++
 .../org/apache/james/mdn/fields/TextTest.java   |  6 +-
 .../mdn/modifier/DispositionModifierTest.java   | 28 ++++++
 20 files changed, 409 insertions(+), 110 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/8d9287ff/mdn/src/main/java/org/apache/james/mdn/Constants.java
----------------------------------------------------------------------
diff --git a/mdn/src/main/java/org/apache/james/mdn/Constants.java b/mdn/src/main/java/org/apache/james/mdn/Constants.java
deleted file mode 100644
index 5e07c00..0000000
--- a/mdn/src/main/java/org/apache/james/mdn/Constants.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/****************************************************************
- * 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.mdn;
-
-public interface Constants {
-    String RFC_822 = "rfc822";
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/8d9287ff/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 06f6ebb..ad65f8c 100644
--- a/mdn/src/main/java/org/apache/james/mdn/MDN.java
+++ b/mdn/src/main/java/org/apache/james/mdn/MDN.java
@@ -52,6 +52,8 @@ public class MDN {
         public MDN build() {
             Preconditions.checkState(report != null);
             Preconditions.checkState(humanReadableText != null);
+            Preconditions.checkState(!humanReadableText.trim().isEmpty());
+
             return new MDN(humanReadableText, report);
         }
     }
@@ -63,7 +65,7 @@ public class MDN {
     private final String humanReadableText;
     private final MDNReport report;
 
-    public MDN(String humanReadableText, MDNReport report) {
+    private MDN(String humanReadableText, MDNReport report) {
         this.humanReadableText = humanReadableText;
         this.report = report;
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/8d9287ff/mdn/src/main/java/org/apache/james/mdn/fields/AddressType.java
----------------------------------------------------------------------
diff --git a/mdn/src/main/java/org/apache/james/mdn/fields/AddressType.java b/mdn/src/main/java/org/apache/james/mdn/fields/AddressType.java
new file mode 100644
index 0000000..ccadbc4
--- /dev/null
+++ b/mdn/src/main/java/org/apache/james/mdn/fields/AddressType.java
@@ -0,0 +1,60 @@
+/****************************************************************
+ * 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.mdn.fields;
+
+import java.util.Objects;
+
+import com.google.common.base.Preconditions;
+
+public class AddressType {
+    public static final AddressType DNS = new AddressType("dns");
+    public static final AddressType RFC_822 = new AddressType("rfc822");
+    public static final AddressType UNKNOWN = new AddressType("unknown");
+
+    private final String type;
+
+    public AddressType(String type) {
+        Preconditions.checkNotNull(type);
+        Preconditions.checkArgument(!type.contains("\n"), "Address type can not be multiline");
+        String trimmedType = type.trim();
+        Preconditions.checkArgument(!trimmedType.isEmpty(), "Address type can not be empty");
+
+        this.type = trimmedType;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof AddressType) {
+            AddressType that = (AddressType) o;
+
+            return Objects.equals(this.type, that.type);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/8d9287ff/mdn/src/main/java/org/apache/james/mdn/fields/FinalRecipient.java
----------------------------------------------------------------------
diff --git a/mdn/src/main/java/org/apache/james/mdn/fields/FinalRecipient.java b/mdn/src/main/java/org/apache/james/mdn/fields/FinalRecipient.java
index 8f87170..0775479 100644
--- a/mdn/src/main/java/org/apache/james/mdn/fields/FinalRecipient.java
+++ b/mdn/src/main/java/org/apache/james/mdn/fields/FinalRecipient.java
@@ -21,8 +21,6 @@ package org.apache.james.mdn.fields;
 
 import java.util.Objects;
 
-import org.apache.james.mdn.Constants;
-
 import com.google.common.base.Preconditions;
 
 /**
@@ -34,28 +32,31 @@ public class FinalRecipient implements Field {
     public static final String FIELD_NAME = "Final-Recipient";
 
     private final Text finalRecipient;
-    private final String addressType;
+    private final AddressType addressType;
 
-    public FinalRecipient(String addressType, Text finalRecipient) {
+    public FinalRecipient(AddressType addressType, Text finalRecipient) {
         Preconditions.checkNotNull(finalRecipient);
         Preconditions.checkNotNull(addressType);
-        Preconditions.checkArgument(!addressType.contains("\n"), "Address type can not be multiline");
 
         this.finalRecipient = finalRecipient;
         this.addressType = addressType;
     }
 
     public FinalRecipient(Text finalRecipient) {
-        this(Constants.RFC_822, finalRecipient);
+        this(AddressType.RFC_822, finalRecipient);
     }
 
     public Text getFinalRecipient() {
         return finalRecipient;
     }
 
+    public AddressType getAddressType() {
+        return addressType;
+    }
+
     @Override
     public String formattedValue() {
-        return FIELD_NAME + ": " + addressType + "; " + finalRecipient.formatted();
+        return FIELD_NAME + ": " + addressType.getType() + "; " + finalRecipient.formatted();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/8d9287ff/mdn/src/main/java/org/apache/james/mdn/fields/Gateway.java
----------------------------------------------------------------------
diff --git a/mdn/src/main/java/org/apache/james/mdn/fields/Gateway.java b/mdn/src/main/java/org/apache/james/mdn/fields/Gateway.java
index f11bc7a..c988b37 100644
--- a/mdn/src/main/java/org/apache/james/mdn/fields/Gateway.java
+++ b/mdn/src/main/java/org/apache/james/mdn/fields/Gateway.java
@@ -27,31 +27,29 @@ import com.google.common.base.Preconditions;
  * MDN-Gateway field as specified in https://tools.ietf.org/html/rfc8098#section-3.2.2
  */
 public class Gateway implements Field {
-    public static final String DNS = "dns";
     public static final String FIELD_NAME = "MDN-Gateway";
 
-    private final String nameType;
+    private final AddressType nameType;
     private final Text name;
 
-    public Gateway(String nameType, Text name) {
+    public Gateway(AddressType nameType, Text name) {
         Preconditions.checkNotNull(nameType);
         Preconditions.checkNotNull(name);
-        Preconditions.checkArgument(!nameType.contains("\n"));
 
         this.nameType = nameType;
         this.name = name;
     }
 
     public Gateway(Text name) {
-        this(DNS, name);
+        this(AddressType.DNS, name);
     }
 
     @Override
     public String formattedValue() {
-        return FIELD_NAME + ": " + nameType + ";" + name.formatted();
+        return FIELD_NAME + ": " + nameType.getType() + ";" + name.formatted();
     }
 
-    public String getNameType() {
+    public AddressType getNameType() {
         return nameType;
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/8d9287ff/mdn/src/main/java/org/apache/james/mdn/fields/OriginalMessageId.java
----------------------------------------------------------------------
diff --git a/mdn/src/main/java/org/apache/james/mdn/fields/OriginalMessageId.java b/mdn/src/main/java/org/apache/james/mdn/fields/OriginalMessageId.java
index 8d0c6f1..45538bf 100644
--- a/mdn/src/main/java/org/apache/james/mdn/fields/OriginalMessageId.java
+++ b/mdn/src/main/java/org/apache/james/mdn/fields/OriginalMessageId.java
@@ -35,8 +35,10 @@ public class OriginalMessageId implements Field {
     public OriginalMessageId(String originalMessageId) {
         Preconditions.checkNotNull(originalMessageId);
         Preconditions.checkArgument(!originalMessageId.contains("\n"));
+        String trimmedMessageId = originalMessageId.trim();
+        Preconditions.checkArgument(!trimmedMessageId.isEmpty());
 
-        this.originalMessageId = originalMessageId;
+        this.originalMessageId = trimmedMessageId;
     }
 
     public String getOriginalMessageId() {

http://git-wip-us.apache.org/repos/asf/james-project/blob/8d9287ff/mdn/src/main/java/org/apache/james/mdn/fields/OriginalRecipient.java
----------------------------------------------------------------------
diff --git a/mdn/src/main/java/org/apache/james/mdn/fields/OriginalRecipient.java b/mdn/src/main/java/org/apache/james/mdn/fields/OriginalRecipient.java
index d1c7d33..c12a87f 100644
--- a/mdn/src/main/java/org/apache/james/mdn/fields/OriginalRecipient.java
+++ b/mdn/src/main/java/org/apache/james/mdn/fields/OriginalRecipient.java
@@ -21,8 +21,6 @@ package org.apache.james.mdn.fields;
 
 import java.util.Objects;
 
-import org.apache.james.mdn.Constants;
-
 import com.google.common.base.Preconditions;
 
 /**
@@ -31,32 +29,32 @@ import com.google.common.base.Preconditions;
  * https://tools.ietf.org/html/rfc8098#section-3.2.3
  */
 public class OriginalRecipient implements Field {
-    private static final String UNKNOWN = "unknown";
     private static final String FIELD_NAME = "Original-Recipient";
 
     public static OriginalRecipient ofUnknown(Text address) {
-        return new OriginalRecipient(UNKNOWN, address);
+        return new OriginalRecipient(AddressType.UNKNOWN, address);
     }
 
     private final Text originalRecipient;
-    private final String addressType;
+    private final AddressType addressType;
 
-    public OriginalRecipient(String addressType, Text originalRecipient) {
+    public OriginalRecipient(AddressType addressType, Text originalRecipient) {
         Preconditions.checkNotNull(addressType);
         Preconditions.checkNotNull(originalRecipient);
+
         this.addressType = addressType;
         this.originalRecipient = originalRecipient;
     }
 
     public OriginalRecipient(Text originalRecipient) {
-        this(Constants.RFC_822, originalRecipient);
+        this(AddressType.RFC_822, originalRecipient);
     }
 
     public Text getOriginalRecipient() {
         return originalRecipient;
     }
 
-    public String getAddressType() {
+    public AddressType getAddressType() {
         return addressType;
     }
 
@@ -78,7 +76,7 @@ public class OriginalRecipient implements Field {
 
     @Override
     public String formattedValue() {
-        return FIELD_NAME + ": " + addressType + "; " + originalRecipient.formatted();
+        return FIELD_NAME + ": " + addressType.getType() + "; " + originalRecipient.formatted();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/8d9287ff/mdn/src/main/java/org/apache/james/mdn/fields/ReportingUserAgent.java
----------------------------------------------------------------------
diff --git a/mdn/src/main/java/org/apache/james/mdn/fields/ReportingUserAgent.java b/mdn/src/main/java/org/apache/james/mdn/fields/ReportingUserAgent.java
index 62bc92b..f3c67fb 100644
--- a/mdn/src/main/java/org/apache/james/mdn/fields/ReportingUserAgent.java
+++ b/mdn/src/main/java/org/apache/james/mdn/fields/ReportingUserAgent.java
@@ -21,6 +21,7 @@ package org.apache.james.mdn.fields;
 
 import java.util.Objects;
 import java.util.Optional;
+import java.util.function.Predicate;
 
 import com.google.common.base.Preconditions;
 
@@ -31,6 +32,7 @@ import com.google.common.base.Preconditions;
  */
 public class ReportingUserAgent implements Field {
     private static final String FIELD_NAME = "Reporting-UA";
+    public static final Predicate<String> IS_EMPTY = String::isEmpty;
     private final String userAgentName;
     private final Optional<String> userAgentProduct;
 
@@ -45,9 +47,14 @@ public class ReportingUserAgent implements Field {
     public ReportingUserAgent(String userAgentName, Optional<String> userAgentProduct) {
         Preconditions.checkNotNull(userAgentName);
         Preconditions.checkNotNull(userAgentProduct);
+        Preconditions.checkArgument(!userAgentName.contains("\n"), "Name should not contain line break");
+        String trimmedName = userAgentName.trim();
+        Preconditions.checkArgument(!trimmedName.isEmpty(), "Name should not be empty");
 
-        this.userAgentName = userAgentName;
-        this.userAgentProduct = userAgentProduct;
+        this.userAgentName = trimmedName;
+        this.userAgentProduct = userAgentProduct
+            .map(String::trim)
+            .filter(IS_EMPTY.negate());
     }
 
     public String getUserAgentName() {

http://git-wip-us.apache.org/repos/asf/james-project/blob/8d9287ff/mdn/src/main/java/org/apache/james/mdn/fields/Text.java
----------------------------------------------------------------------
diff --git a/mdn/src/main/java/org/apache/james/mdn/fields/Text.java b/mdn/src/main/java/org/apache/james/mdn/fields/Text.java
index d3592cf..7c99b7d 100644
--- a/mdn/src/main/java/org/apache/james/mdn/fields/Text.java
+++ b/mdn/src/main/java/org/apache/james/mdn/fields/Text.java
@@ -28,7 +28,10 @@ public class Text {
 
     public static Text fromRawText(String rawText) {
         Preconditions.checkNotNull(rawText);
-        return new Text(replaceLineBreaksByContinuation(rawText));
+        String trimmedText = rawText.trim();
+        Preconditions.checkArgument(!trimmedText.isEmpty(), "Text should not be empty");
+
+        return new Text(replaceLineBreaksByContinuation(trimmedText));
     }
 
     private static String replaceLineBreaksByContinuation(String rawText) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/8d9287ff/mdn/src/main/java/org/apache/james/mdn/modifier/DispositionModifier.java
----------------------------------------------------------------------
diff --git a/mdn/src/main/java/org/apache/james/mdn/modifier/DispositionModifier.java b/mdn/src/main/java/org/apache/james/mdn/modifier/DispositionModifier.java
index f7e9171..fec53fd 100644
--- a/mdn/src/main/java/org/apache/james/mdn/modifier/DispositionModifier.java
+++ b/mdn/src/main/java/org/apache/james/mdn/modifier/DispositionModifier.java
@@ -42,7 +42,10 @@ public class DispositionModifier {
     public DispositionModifier(String value) {
         Preconditions.checkNotNull(value);
         Preconditions.checkArgument(!value.contains("\n"), "Multiline Disposition modifier are forbiden");
-        this.value = value;
+        String trimmedValue = value.trim();
+        Preconditions.checkArgument(!trimmedValue.isEmpty(), "Disposition modifier can not be empty");
+
+        this.value = trimmedValue;
     }
 
     public String getValue() {

http://git-wip-us.apache.org/repos/asf/james-project/blob/8d9287ff/mdn/src/test/java/org/apache/james/mdn/MDNReportFormattingTest.java
----------------------------------------------------------------------
diff --git a/mdn/src/test/java/org/apache/james/mdn/MDNReportFormattingTest.java b/mdn/src/test/java/org/apache/james/mdn/MDNReportFormattingTest.java
index 8168915..3f1555e 100644
--- a/mdn/src/test/java/org/apache/james/mdn/MDNReportFormattingTest.java
+++ b/mdn/src/test/java/org/apache/james/mdn/MDNReportFormattingTest.java
@@ -22,6 +22,7 @@ package org.apache.james.mdn;
 import static org.assertj.core.api.Assertions.assertThat;
 
 import org.apache.james.mdn.action.mode.DispositionActionMode;
+import org.apache.james.mdn.fields.AddressType;
 import org.apache.james.mdn.fields.Disposition;
 import org.apache.james.mdn.fields.Error;
 import org.apache.james.mdn.fields.ExtensionField;
@@ -421,7 +422,7 @@ public class MDNReportFormattingTest {
             .reportingUserAgentField(new ReportingUserAgent(
                 "UA_name",
                 "UA_product"))
-            .gatewayField(new Gateway("postal", Text.fromRawText("5 rue Charles mercier")))
+            .gatewayField(new Gateway(new AddressType("postal"), Text.fromRawText("5 rue Charles mercier")))
             .finalRecipientField(new FinalRecipient(Text.fromRawText("final_recipient")))
             .originalRecipientField(new OriginalRecipient(Text.fromRawText("originalRecipient")))
             .originalMessageIdField(new OriginalMessageId("original_message_id"))
@@ -453,7 +454,7 @@ public class MDNReportFormattingTest {
                 "UA_name",
                 "UA_product"))
             .finalRecipientField(new FinalRecipient(Text.fromRawText("final_recipient")))
-            .originalRecipientField(new OriginalRecipient("roomNumber", Text.fromRawText("385")))
+            .originalRecipientField(new OriginalRecipient(new AddressType("roomNumber"), Text.fromRawText("385")))
             .originalMessageIdField(new OriginalMessageId("original_message_id"))
             .dispositionField(disposition)
             .build()
@@ -481,9 +482,9 @@ public class MDNReportFormattingTest {
             .reportingUserAgentField(new ReportingUserAgent(
                 "UA_name",
                 "UA_product"))
-            .gatewayField(new Gateway("postal", Text.fromRawText("8 rue Charles mercier\n 36555 Saint Coincoin\n France")))
-            .finalRecipientField(new FinalRecipient("postal", Text.fromRawText("5 rue Mercier\n 36555 Saint Coincoin\n France")))
-            .originalRecipientField(new OriginalRecipient("postal", Text.fromRawText("3 rue Mercier\n 36555 Saint Coincoin\n France")))
+            .gatewayField(new Gateway(new AddressType("postal"), Text.fromRawText("8 rue Charles mercier\n 36555 Saint Coincoin\n France")))
+            .finalRecipientField(new FinalRecipient(new AddressType("postal"), Text.fromRawText("5 rue Mercier\n 36555 Saint Coincoin\n France")))
+            .originalRecipientField(new OriginalRecipient(new AddressType("postal"), Text.fromRawText("3 rue Mercier\n 36555 Saint Coincoin\n France")))
             .originalMessageIdField(new OriginalMessageId("original_message_id"))
             .dispositionField(disposition)
             .build()
@@ -547,7 +548,7 @@ public class MDNReportFormattingTest {
             .reportingUserAgentField(new ReportingUserAgent(
                 "UA_name",
                 "UA_product"))
-            .finalRecipientField(new FinalRecipient("roomNumber", Text.fromRawText("781")))
+            .finalRecipientField(new FinalRecipient(new AddressType("roomNumber"), Text.fromRawText("781")))
             .originalRecipientField(new OriginalRecipient(Text.fromRawText("originalRecipient")))
             .originalMessageIdField(new OriginalMessageId("original_message_id"))
             .dispositionField(disposition)

http://git-wip-us.apache.org/repos/asf/james-project/blob/8d9287ff/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 cf8b522..2282e05 100644
--- a/mdn/src/test/java/org/apache/james/mdn/MDNTest.java
+++ b/mdn/src/test/java/org/apache/james/mdn/MDNTest.java
@@ -39,6 +39,14 @@ import nl.jqno.equalsverifier.EqualsVerifier;
 
 public class MDNTest {
 
+    public static final MDNReport MINIMAL_REPORT = MDNReport.builder()
+        .finalRecipientField("final@domain.com")
+        .dispositionField(Disposition.builder()
+            .actionMode(DispositionActionMode.Automatic)
+            .sendingMode(DispositionSendingMode.Automatic)
+            .type(DispositionType.Deleted)
+            .build())
+        .build();
     @Rule
     public ExpectedException expectedException = ExpectedException.none();
 
@@ -53,14 +61,7 @@ public class MDNTest {
     public void asMimeMessageShouldComportExplanationPartAndReportPart() throws Exception {
         MimeMessage mimeMessage = MDN.builder()
             .humanReadableText("Explanation")
-            .report(MDNReport.builder()
-                .finalRecipientField("final@domain.com")
-                .dispositionField(Disposition.builder()
-                    .actionMode(DispositionActionMode.Automatic)
-                    .sendingMode(DispositionSendingMode.Automatic)
-                    .type(DispositionType.Deleted)
-                    .build())
-                .build())
+            .report(MINIMAL_REPORT)
             .build()
             .asMimeMessage();
 
@@ -84,15 +85,8 @@ public class MDNTest {
     @Test
     public void asMimeMessageShouldDisplayEmptyExplanation() throws Exception {
         MimeMessage mimeMessage = MDN.builder()
-            .humanReadableText("")
-            .report(MDNReport.builder()
-                .finalRecipientField("final@domain.com")
-                .dispositionField(Disposition.builder()
-                    .actionMode(DispositionActionMode.Automatic)
-                    .sendingMode(DispositionSendingMode.Automatic)
-                    .type(DispositionType.Deleted)
-                    .build())
-                .build())
+            .humanReadableText("Explanation")
+            .report(MINIMAL_REPORT)
             .build()
             .asMimeMessage();
 
@@ -103,7 +97,8 @@ public class MDNTest {
                 "Content-Type: text/plain; charset=UTF-8\r\n" +
                     "Content-Transfer-Encoding: 7bit\r\n" +
                     "Content-Disposition: inline\r\n" +
-                    "\r\n")
+                    "\r\n" +
+                    "Explanation")
             .contains(
                 "Content-Type: message/disposition-notification\r\n" +
                     "Content-Transfer-Encoding: 7bit\r\n" +
@@ -127,4 +122,47 @@ public class MDNTest {
         MDN.builder()
             .humanReadableText(null);
     }
+
+    @Test
+    public void buildShouldThrowOnEmptyHumanReadableText() {
+        expectedException.expect(IllegalStateException.class);
+
+        MDN.builder()
+            .humanReadableText("")
+            .report(MINIMAL_REPORT)
+            .build();
+    }
+
+    @Test
+    public void buildShouldThrowOnFoldingWhiteHumanReadableText() {
+        expectedException.expect(IllegalStateException.class);
+
+        MDN.builder()
+            .humanReadableText("  ")
+            .report(MINIMAL_REPORT)
+            .build();
+    }
+
+    @Test
+    public void humanReadableTextShouldNotBeTrimmed() throws Exception {
+        MimeMessage mimeMessage = MDN.builder()
+            .humanReadableText("Explanation:\n" +
+                " - We should always write detailed unit tests\n" +
+                " - We should think of all edge cases\n")
+            .report(MINIMAL_REPORT)
+            .build()
+            .asMimeMessage();
+
+        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+        mimeMessage.writeTo(byteArrayOutputStream);
+        assertThat(new String(byteArrayOutputStream.toByteArray(), Charsets.UTF_8))
+            .contains(
+                "Content-Type: text/plain; charset=UTF-8\r\n" +
+                    "Content-Transfer-Encoding: 7bit\r\n" +
+                    "Content-Disposition: inline\r\n" +
+                    "\r\n" +
+                    "Explanation:\n" +
+                    " - We should always write detailed unit tests\n" +
+                    " - We should think of all edge cases\n");
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/8d9287ff/mdn/src/test/java/org/apache/james/mdn/fields/AddressTypeTest.java
----------------------------------------------------------------------
diff --git a/mdn/src/test/java/org/apache/james/mdn/fields/AddressTypeTest.java b/mdn/src/test/java/org/apache/james/mdn/fields/AddressTypeTest.java
new file mode 100644
index 0000000..ee2520b
--- /dev/null
+++ b/mdn/src/test/java/org/apache/james/mdn/fields/AddressTypeTest.java
@@ -0,0 +1,99 @@
+/****************************************************************
+ * 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.mdn.fields;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+public class AddressTypeTest {
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
+    @Test
+    public void shouldMatchBeanContract() {
+        EqualsVerifier.forClass(AddressType.class)
+            .allFieldsShouldBeUsed()
+            .verify();
+    }
+
+    @Test
+    public void constructorShouldThrowOnNull() {
+        expectedException.expect(NullPointerException.class);
+
+        new AddressType(null);
+    }
+
+    @Test
+    public void constructorShouldThrowOnEmpty() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        new AddressType("");
+    }
+
+    @Test
+    public void constructorShouldThrowOnFoldingWhiteSpaces() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        new AddressType("   ");
+    }
+
+    @Test
+    public void constructorShouldThrowOnLineBreaks() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        new AddressType("a\nb");
+    }
+
+    @Test
+    public void constructorShouldThrowOnLineBreakAtTheEnd() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        new AddressType("a\n");
+    }
+
+    @Test
+    public void constructorShouldThrowOnLineBreakAtTheBeginning() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        new AddressType("\na");
+    }
+
+    @Test
+    public void constructorShouldAcceptValidValue() {
+        String type = "ab";
+        AddressType addressType = new AddressType(type);
+
+        assertThat(addressType.getType())
+            .isEqualTo(type);
+    }
+
+    @Test
+    public void typeShouldBeTrimmed() {
+        AddressType addressType = new AddressType("  ab  ");
+
+        assertThat(addressType.getType())
+            .isEqualTo("ab");
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/8d9287ff/mdn/src/test/java/org/apache/james/mdn/fields/FinalRecipientTest.java
----------------------------------------------------------------------
diff --git a/mdn/src/test/java/org/apache/james/mdn/fields/FinalRecipientTest.java b/mdn/src/test/java/org/apache/james/mdn/fields/FinalRecipientTest.java
index c424a0c..b53cf61 100644
--- a/mdn/src/test/java/org/apache/james/mdn/fields/FinalRecipientTest.java
+++ b/mdn/src/test/java/org/apache/james/mdn/fields/FinalRecipientTest.java
@@ -21,7 +21,6 @@ package org.apache.james.mdn.fields;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-import org.apache.james.mdn.Constants;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -51,22 +50,14 @@ public class FinalRecipientTest {
     public void shouldThrowOnNullAddressWithType() {
         expectedException.expect(NullPointerException.class);
 
-        new FinalRecipient("customType", null);
+        new FinalRecipient(new AddressType("customType"), null);
     }
 
     @Test
     public void shouldThrowOnNullType() {
         expectedException.expect(NullPointerException.class);
 
-        String addressType = null;
-        new FinalRecipient(addressType, Text.fromRawText("address"));
-    }
-
-    @Test
-    public void shouldThrowOnMultilineType() {
-        expectedException.expect(IllegalArgumentException.class);
-
-        String addressType = "a\nb";
+        AddressType addressType = null;
         new FinalRecipient(addressType, Text.fromRawText("address"));
     }
 
@@ -74,7 +65,7 @@ public class FinalRecipientTest {
     public void typeShouldDefaultToRfc822() {
         Text address = Text.fromRawText("address");
         assertThat(new FinalRecipient(address))
-            .isEqualTo(new FinalRecipient(Constants.RFC_822, address));
+            .isEqualTo(new FinalRecipient(AddressType.RFC_822, address));
     }
 
     @Test
@@ -86,7 +77,7 @@ public class FinalRecipientTest {
 
     @Test
     public void formattedValueShouldDisplayCustomType() {
-        assertThat(new FinalRecipient("postal", Text.fromRawText("Plop"))
+        assertThat(new FinalRecipient(new AddressType("postal"), Text.fromRawText("Plop"))
             .formattedValue())
             .isEqualTo("Final-Recipient: postal; Plop");
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/8d9287ff/mdn/src/test/java/org/apache/james/mdn/fields/GatewayTest.java
----------------------------------------------------------------------
diff --git a/mdn/src/test/java/org/apache/james/mdn/fields/GatewayTest.java b/mdn/src/test/java/org/apache/james/mdn/fields/GatewayTest.java
index b5041fd..3d69440 100644
--- a/mdn/src/test/java/org/apache/james/mdn/fields/GatewayTest.java
+++ b/mdn/src/test/java/org/apache/james/mdn/fields/GatewayTest.java
@@ -52,22 +52,14 @@ public class GatewayTest {
         expectedException.expect(NullPointerException.class);
 
         Text name = null;
-        new Gateway("type", name);
+        new Gateway(new AddressType("type"), name);
     }
 
     @Test
     public void shouldThrowOnNullType() {
         expectedException.expect(NullPointerException.class);
 
-        String nameType = null;
-        new Gateway(nameType, Text.fromRawText("name"));
-    }
-
-    @Test
-    public void shouldThrowOnMultilineType() {
-        expectedException.expect(IllegalArgumentException.class);
-
-        String nameType = "name\ntype";
+        AddressType nameType = null;
         new Gateway(nameType, Text.fromRawText("name"));
     }
 
@@ -75,7 +67,7 @@ public class GatewayTest {
     public void addressTypeSHouldDefaultToDNS() {
         Text address = Text.fromRawText("address");
         assertThat(new Gateway(address))
-            .isEqualTo(new Gateway(Gateway.DNS, address));
+            .isEqualTo(new Gateway(AddressType.DNS, address));
     }
 
     @Test
@@ -95,7 +87,7 @@ public class GatewayTest {
 
     @Test
     public void formattedValueShouldDisplayCustomAddress() {
-        assertThat(new Gateway("custom", Text.fromRawText("address"))
+        assertThat(new Gateway(new AddressType("custom"), Text.fromRawText("address"))
             .formattedValue())
             .isEqualTo("MDN-Gateway: custom;address");
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/8d9287ff/mdn/src/test/java/org/apache/james/mdn/fields/OriginalMessageIdTest.java
----------------------------------------------------------------------
diff --git a/mdn/src/test/java/org/apache/james/mdn/fields/OriginalMessageIdTest.java b/mdn/src/test/java/org/apache/james/mdn/fields/OriginalMessageIdTest.java
index 58f12c1..fb5719a 100644
--- a/mdn/src/test/java/org/apache/james/mdn/fields/OriginalMessageIdTest.java
+++ b/mdn/src/test/java/org/apache/james/mdn/fields/OriginalMessageIdTest.java
@@ -54,9 +54,46 @@ public class OriginalMessageIdTest {
     }
 
     @Test
+    public void constructorShouldThrowOnEmpty() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        new OriginalMessageId("");
+    }
+
+    @Test
+    public void constructorShouldThrowOnFoldingWhiteSpaces() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        new OriginalMessageId("   ");
+    }
+
+    @Test
+    public void shouldThrowOnNameWithLineBreakAtTheEnd() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        String userAgentName = "a\n";
+        new OriginalMessageId(userAgentName);
+    }
+
+    @Test
+    public void shouldThrowOnNameWithLineBreakAtTheBeginning() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        String userAgentName = "\nb";
+        new OriginalMessageId(userAgentName);
+    }
+
+    @Test
     public void formattedValueShouldDisplayMessageId() {
         assertThat(new OriginalMessageId("msgId")
             .formattedValue())
             .isEqualTo("Original-Message-ID: msgId");
     }
+
+    @Test
+    public void messageIdShouldBeTrimmed() {
+        assertThat(new OriginalMessageId(" msgId ")
+            .getOriginalMessageId())
+            .isEqualTo("msgId");
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/8d9287ff/mdn/src/test/java/org/apache/james/mdn/fields/OriginalRecipientTest.java
----------------------------------------------------------------------
diff --git a/mdn/src/test/java/org/apache/james/mdn/fields/OriginalRecipientTest.java b/mdn/src/test/java/org/apache/james/mdn/fields/OriginalRecipientTest.java
index 7a37e54..5f9e4a6 100644
--- a/mdn/src/test/java/org/apache/james/mdn/fields/OriginalRecipientTest.java
+++ b/mdn/src/test/java/org/apache/james/mdn/fields/OriginalRecipientTest.java
@@ -21,7 +21,6 @@ package org.apache.james.mdn.fields;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-import org.apache.james.mdn.Constants;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -54,21 +53,21 @@ public class OriginalRecipientTest {
         expectedException.expect(NullPointerException.class);
 
         Text originalRecipient = null;
-        new OriginalRecipient("customType", originalRecipient);
+        new OriginalRecipient(new AddressType("customType"), originalRecipient);
     }
 
     @Test
     public void shouldThrowOnNullAddressType() {
         expectedException.expect(NullPointerException.class);
 
-        String addressType = null;
+        AddressType addressType = null;
         new OriginalRecipient(addressType, ADDRESS);
     }
 
     @Test
     public void addressTypeShouldDefaultToRfc822() {
         assertThat(new OriginalRecipient(ADDRESS))
-            .isEqualTo(new OriginalRecipient(Constants.RFC_822, ADDRESS));
+            .isEqualTo(new OriginalRecipient(AddressType.RFC_822, ADDRESS));
     }
 
     @Test
@@ -80,7 +79,7 @@ public class OriginalRecipientTest {
 
     @Test
     public void formattedValueShouldDisplayCustomType() {
-        assertThat(new OriginalRecipient("custom", ADDRESS)
+        assertThat(new OriginalRecipient(new AddressType("custom"), ADDRESS)
             .formattedValue())
             .isEqualTo("Original-Recipient: custom; address");
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/8d9287ff/mdn/src/test/java/org/apache/james/mdn/fields/ReportingUserAgentTest.java
----------------------------------------------------------------------
diff --git a/mdn/src/test/java/org/apache/james/mdn/fields/ReportingUserAgentTest.java b/mdn/src/test/java/org/apache/james/mdn/fields/ReportingUserAgentTest.java
index 74f3a97..53954b8 100644
--- a/mdn/src/test/java/org/apache/james/mdn/fields/ReportingUserAgentTest.java
+++ b/mdn/src/test/java/org/apache/james/mdn/fields/ReportingUserAgentTest.java
@@ -80,12 +80,76 @@ public class ReportingUserAgentTest {
     }
 
     @Test
+    public void shouldThrowOnEmptyName() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        String userAgentName = "";
+        new ReportingUserAgent(userAgentName);
+    }
+
+    @Test
+    public void shouldThrowOnFoldingWhiteSpaceName() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        String userAgentName = "   ";
+        new ReportingUserAgent(userAgentName);
+    }
+
+    @Test
+    public void shouldThrowOnNameWithLineBreak() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        String userAgentName = "a\nb";
+        new ReportingUserAgent(userAgentName);
+    }
+
+    @Test
+    public void shouldThrowOnNameWithLineBreakAtTheEnd() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        String userAgentName = "a\n";
+        new ReportingUserAgent(userAgentName);
+    }
+
+    @Test
+    public void shouldThrowOnNameWithLineBreakAtTheBeginning() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        String userAgentName = "\nb";
+        new ReportingUserAgent(userAgentName);
+    }
+
+    @Test
+    public void nameShouldBeTrimmed() {
+        assertThat(new ReportingUserAgent(" name ").getUserAgentName())
+            .isEqualTo(USER_AGENT_NAME);
+    }
+
+    @Test
+    public void productShouldBeTrimmed() {
+        assertThat(new ReportingUserAgent(USER_AGENT_NAME, " product ").getUserAgentProduct())
+            .contains(USER_AGENT_PRODUCT);
+    }
+
+    @Test
     public void formattedValueShouldDisplayNameWhenProductMissing() {
         assertThat(new ReportingUserAgent(USER_AGENT_NAME).formattedValue())
             .isEqualTo("Reporting-UA: name; ");
     }
 
     @Test
+    public void emptyProductShouldBeFilteredOut() {
+        assertThat(new ReportingUserAgent(USER_AGENT_NAME, "").getUserAgentProduct())
+            .isEmpty();
+    }
+
+    @Test
+    public void foldingWhiteSpaceProductShouldBeFilteredOut() {
+        assertThat(new ReportingUserAgent(USER_AGENT_NAME, "  ").getUserAgentProduct())
+            .isEmpty();
+    }
+
+    @Test
     public void formattedValueShouldDisplayProduct() {
         assertThat(new ReportingUserAgent(USER_AGENT_NAME, USER_AGENT_PRODUCT).formattedValue())
             .isEqualTo("Reporting-UA: name; product");

http://git-wip-us.apache.org/repos/asf/james-project/blob/8d9287ff/mdn/src/test/java/org/apache/james/mdn/fields/TextTest.java
----------------------------------------------------------------------
diff --git a/mdn/src/test/java/org/apache/james/mdn/fields/TextTest.java b/mdn/src/test/java/org/apache/james/mdn/fields/TextTest.java
index 938b6fe..0d82c28 100644
--- a/mdn/src/test/java/org/apache/james/mdn/fields/TextTest.java
+++ b/mdn/src/test/java/org/apache/james/mdn/fields/TextTest.java
@@ -47,10 +47,10 @@ public class TextTest {
     }
 
     @Test
-    public void formattedShouldRenderEmptyStrings() {
-        Text text = Text.fromRawText("");
+    public void fromRawTextShouldThrowOnEmptyStrings() {
+        expectedException.expect(IllegalArgumentException.class);
 
-        assertThat(text.formatted()).isEqualTo("");
+        Text.fromRawText("");
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/james-project/blob/8d9287ff/mdn/src/test/java/org/apache/james/mdn/modifier/DispositionModifierTest.java
----------------------------------------------------------------------
diff --git a/mdn/src/test/java/org/apache/james/mdn/modifier/DispositionModifierTest.java b/mdn/src/test/java/org/apache/james/mdn/modifier/DispositionModifierTest.java
index a408b51..dccf3dd 100644
--- a/mdn/src/test/java/org/apache/james/mdn/modifier/DispositionModifierTest.java
+++ b/mdn/src/test/java/org/apache/james/mdn/modifier/DispositionModifierTest.java
@@ -50,4 +50,32 @@ public class DispositionModifierTest {
 
         new DispositionModifier("multi\nline");
     }
+
+    @Test
+    public void shouldThrowOnEndBreakLine() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        new DispositionModifier("multi\n");
+    }
+
+    @Test
+    public void shouldThrowOnBeginningBreakLine() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        new DispositionModifier("\nline");
+    }
+
+    @Test
+    public void shouldThrowOnEmptyValue() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        new DispositionModifier("");
+    }
+
+    @Test
+    public void shouldThrowOnFoldingWhiteSpaceValue() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        new DispositionModifier("    ");
+    }
 }


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