james-server-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rouaz...@apache.org
Subject [james-project] 01/07: JAMES-2578 Fix warning using Mailet new API
Date Fri, 15 Feb 2019 13:30:36 GMT
This is an automated email from the ASF dual-hosted git repository.

rouazana pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 23e94c4e3300105f12f900ecf070d7cd96961d16
Author: Gautier DI FOLCO <gdifolco@linagora.com>
AuthorDate: Wed Jan 23 15:40:21 2019 +0100

    JAMES-2578 Fix warning using Mailet new API
---
 .../java/org/apache/mailet/ContractMailTest.java   |   2 +-
 .../transport/mailets/ICALToJsonAttribute.java     |   7 +
 .../transport/mailets/ICALToJsonAttributeTest.java | 312 +++++++++++----------
 .../transport/mailets/ICalendarParserTest.java     |  28 +-
 .../transport/mailets/RemoveMailAttribute.java     |  18 +-
 .../mailets/RemoveAllMailAttributesTest.java       |   7 +-
 .../transport/mailets/SetMailAttributeTest.java    |  19 +-
 .../apache/mailet/base/test/FakeMailContext.java   |  53 ++--
 .../org/apache/james/server/core/MailImpl.java     |   6 -
 .../mailrepository/jdbc/JDBCMailRepository.java    |  25 +-
 .../impl/camel/CamelMailetProcessor.java           |   2 +-
 .../mailetcontainer/impl/camel/MatcherMatch.java   |   2 +-
 .../impl/camel/MatcherSplitter.java                |   9 +-
 .../mailets/AbstractRecipientRewriteTable.java     |   9 +-
 .../mailets/WithStorageDirectiveTest.java          |  18 +-
 .../mailets/delivery/SieveIntegrationTest.java     | 168 +++++------
 .../remote/delivery/RemoteDeliveryTest.java        |  15 +-
 .../cassandra/CassandraMailRepositoryMailDAO.java  |  23 +-
 .../CassandraMailRepositoryMailDAOTest.java        |   8 +-
 .../org/apache/james/webadmin/dto/MailDto.java     |   8 +-
 .../queue/activemq/ActiveMQMailQueueItem.java      |   2 +-
 .../james/queue/activemq/ActiveMQSupport.java      |   3 +-
 .../apache/james/queue/api/MailQueueContract.java  |   1 +
 .../queue/api/ManageableMailQueueContract.java     |  17 +-
 .../org/apache/james/queue/jms/JMSMailQueue.java   |  16 +-
 .../james/queue/library/MailQueueManagement.java   |  19 +-
 26 files changed, 449 insertions(+), 348 deletions(-)

diff --git a/mailet/api/src/test/java/org/apache/mailet/ContractMailTest.java b/mailet/api/src/test/java/org/apache/mailet/ContractMailTest.java
index 8e1f562..3d63f77 100644
--- a/mailet/api/src/test/java/org/apache/mailet/ContractMailTest.java
+++ b/mailet/api/src/test/java/org/apache/mailet/ContractMailTest.java
@@ -152,7 +152,7 @@ public abstract class ContractMailTest {
 
     @SuppressWarnings("deprecation")
     @Nested
-    public class DeprecatedtedAttributes {
+    public class DeprecatedAttributes {
         @Test
         void setAttributeShouldReturnNullWhenNoPreviousValue() {
             Mail mail = newMail();
diff --git a/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToJsonAttribute.java b/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToJsonAttribute.java
index f1605bb..630e23c 100644
--- a/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToJsonAttribute.java
+++ b/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToJsonAttribute.java
@@ -36,6 +36,7 @@ import org.apache.james.core.MailAddress;
 import org.apache.james.transport.mailets.model.ICAL;
 import org.apache.james.util.OptionalUtils;
 import org.apache.james.util.StreamUtils;
+import org.apache.mailet.AttributeName;
 import org.apache.mailet.Mail;
 import org.apache.mailet.base.GenericMailet;
 import org.slf4j.Logger;
@@ -90,6 +91,12 @@ public class ICALToJsonAttribute extends GenericMailet {
     public static final String DEFAULT_SOURCE_ATTRIBUTE_NAME = "icalendar";
     public static final String DEFAULT_RAW_SOURCE_ATTRIBUTE_NAME = "attachments";
     public static final String DEFAULT_DESTINATION_ATTRIBUTE_NAME = "icalendarJson";
+    public static final AttributeName SOURCE = AttributeName.of(SOURCE_ATTRIBUTE_NAME);
+    public static final AttributeName RAW_SOURCE = AttributeName.of(RAW_SOURCE_ATTRIBUTE_NAME);
+    public static final AttributeName DESTINATION = AttributeName.of(DESTINATION_ATTRIBUTE_NAME);
+    public static final AttributeName DEFAULT_SOURCE = AttributeName.of(DEFAULT_SOURCE_ATTRIBUTE_NAME);
+    public static final AttributeName DEFAULT_RAW_SOURCE = AttributeName.of(DEFAULT_RAW_SOURCE_ATTRIBUTE_NAME);
+    public static final AttributeName DEFAULT_DESTINATION = AttributeName.of(DEFAULT_DESTINATION_ATTRIBUTE_NAME);
 
     static {
         ICal4JConfigurator.configure();
diff --git a/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToJsonAttributeTest.java b/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToJsonAttributeTest.java
index 7eb84d2..685497c 100644
--- a/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToJsonAttributeTest.java
+++ b/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToJsonAttributeTest.java
@@ -26,6 +26,7 @@ import java.io.ByteArrayInputStream;
 import java.nio.charset.StandardCharsets;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 import javax.mail.MessagingException;
@@ -34,6 +35,7 @@ import org.apache.james.core.MailAddress;
 import org.apache.james.core.builder.MimeMessageBuilder;
 import org.apache.james.util.ClassLoaderUtils;
 import org.apache.james.util.MimeMessageUtil;
+import org.apache.mailet.AttributeUtils;
 import org.apache.mailet.Mail;
 import org.apache.mailet.base.MailAddressFixture;
 import org.apache.mailet.base.test.FakeMail;
@@ -50,6 +52,7 @@ import net.fortuna.ical4j.model.Calendar;
 
 public class ICALToJsonAttributeTest {
     public static final MailAddress SENDER = MailAddressFixture.ANY_AT_JAMES;
+    public static final Class<Map<String, byte[]>> MAP_STRING_BYTES_CLASS = (Class<Map<String, byte[]>>) (Object) Map.class;
 
     @Rule
     public ExpectedException expectedException = ExpectedException.none();
@@ -127,8 +130,8 @@ public class ICALToJsonAttributeTest {
             .build();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME))
-            .isNull();
+        assertThat(mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION))
+            .isEmpty();
     }
 
     @Test
@@ -142,8 +145,8 @@ public class ICALToJsonAttributeTest {
             .build();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME))
-            .isNull();
+        assertThat(mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION))
+            .isEmpty();
     }
 
     @Test
@@ -157,8 +160,8 @@ public class ICALToJsonAttributeTest {
             .build();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME))
-            .isNull();
+        assertThat(mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION))
+            .isEmpty();
     }
 
     @Test
@@ -173,8 +176,8 @@ public class ICALToJsonAttributeTest {
             .build();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME))
-            .isNull();
+        assertThat(mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION))
+            .isEmpty();
     }
 
     @Test
@@ -189,8 +192,8 @@ public class ICALToJsonAttributeTest {
             .build();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME))
-            .isNull();
+        assertThat(mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION))
+            .isEmpty();
     }
 
     @Test
@@ -207,8 +210,8 @@ public class ICALToJsonAttributeTest {
             .build();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME))
-            .isNull();
+        assertThat(mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION))
+            .isEmpty();
     }
 
     @Test
@@ -226,8 +229,9 @@ public class ICALToJsonAttributeTest {
             .build();
         testee.service(mail);
 
-        assertThat((Map<?,?>) mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME))
-            .isEmpty();
+        assertThat(AttributeUtils.getValueAndCastFromMail(mail, ICALToJsonAttribute.DEFAULT_DESTINATION, Map.class))
+            .isPresent()
+            .hasValueSatisfying(map -> assertThat(map).isEmpty());
     }
 
     @SuppressWarnings("unchecked")
@@ -248,19 +252,22 @@ public class ICALToJsonAttributeTest {
             .build();
         testee.service(mail);
 
-        Map<String, byte[]> jsons = (Map<String, byte[]>) mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME);
-        assertThat(jsons).hasSize(1);
-        assertThatJson(new String(jsons.values().iterator().next(), StandardCharsets.UTF_8))
-            .isEqualTo("{" +
-                "\"ical\": \"" + toJsonValue(ics) + "\"," +
-                "\"sender\": \"" + SENDER.asString() + "\"," +
-                "\"recipient\": \"" + recipient.asString() + "\"," +
-                "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," +
-                "\"sequence\": \"0\"," +
-                "\"dtstamp\": \"20170106T115036Z\"," +
-                "\"method\": \"REQUEST\"," +
-                "\"recurrence-id\": null" +
-                "}");
+        assertThat(AttributeUtils.getValueAndCastFromMail(mail, ICALToJsonAttribute.DEFAULT_DESTINATION, MAP_STRING_BYTES_CLASS))
+            .isPresent()
+            .hasValueSatisfying(jsons -> {
+                assertThat(jsons).hasSize(1);
+                assertThatJson(new String(jsons.values().iterator().next(), StandardCharsets.UTF_8))
+                    .isEqualTo("{" +
+                        "\"ical\": \"" + toJsonValue(ics) + "\"," +
+                        "\"sender\": \"" + SENDER.asString() + "\"," +
+                        "\"recipient\": \"" + recipient.asString() + "\"," +
+                        "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," +
+                        "\"sequence\": \"0\"," +
+                        "\"dtstamp\": \"20170106T115036Z\"," +
+                        "\"method\": \"REQUEST\"," +
+                        "\"recurrence-id\": null" +
+                        "}");
+            });
     }
 
     private String toJsonValue(byte[] ics) {
@@ -284,30 +291,33 @@ public class ICALToJsonAttributeTest {
             .build();
         testee.service(mail);
 
-        Map<String, byte[]> jsons = (Map<String, byte[]>) mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME);
-        assertThat(jsons).hasSize(2);
-        List<String> actual = toSortedValueList(jsons);
-
-        assertThatJson(actual.get(0)).isEqualTo("{" +
-            "\"ical\": \"" + toJsonValue(ics) + "\"," +
-            "\"sender\": \"" + SENDER.asString() + "\"," +
-            "\"recipient\": \"" + MailAddressFixture.ANY_AT_JAMES2.asString() + "\"," +
-            "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," +
-            "\"sequence\": \"0\"," +
-            "\"dtstamp\": \"20170106T115036Z\"," +
-            "\"method\": \"REQUEST\"," +
-            "\"recurrence-id\": null" +
-            "}");
-        assertThatJson(actual.get(1)).isEqualTo("{" +
-            "\"ical\": \"" + toJsonValue(ics) + "\"," +
-            "\"sender\": \"" + SENDER.asString() + "\"," +
-            "\"recipient\": \"" + MailAddressFixture.OTHER_AT_JAMES.asString() + "\"," +
-            "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," +
-            "\"sequence\": \"0\"," +
-            "\"dtstamp\": \"20170106T115036Z\"," +
-            "\"method\": \"REQUEST\"," +
-            "\"recurrence-id\": null" +
-            "}");
+        assertThat(AttributeUtils.getValueAndCastFromMail(mail, ICALToJsonAttribute.DEFAULT_DESTINATION, MAP_STRING_BYTES_CLASS))
+                .isPresent()
+                .hasValueSatisfying(jsons -> {
+                    assertThat(jsons).hasSize(2);
+                    List<String> actual = toSortedValueList(jsons);
+
+                    assertThatJson(actual.get(0)).isEqualTo("{" +
+                        "\"ical\": \"" + toJsonValue(ics) + "\"," +
+                        "\"sender\": \"" + SENDER.asString() + "\"," +
+                        "\"recipient\": \"" + MailAddressFixture.ANY_AT_JAMES2.asString() + "\"," +
+                        "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," +
+                        "\"sequence\": \"0\"," +
+                        "\"dtstamp\": \"20170106T115036Z\"," +
+                        "\"method\": \"REQUEST\"," +
+                        "\"recurrence-id\": null" +
+                        "}");
+                    assertThatJson(actual.get(1)).isEqualTo("{" +
+                        "\"ical\": \"" + toJsonValue(ics) + "\"," +
+                        "\"sender\": \"" + SENDER.asString() + "\"," +
+                        "\"recipient\": \"" + MailAddressFixture.OTHER_AT_JAMES.asString() + "\"," +
+                        "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," +
+                        "\"sequence\": \"0\"," +
+                        "\"dtstamp\": \"20170106T115036Z\"," +
+                        "\"method\": \"REQUEST\"," +
+                        "\"recurrence-id\": null" +
+                        "}");
+                });
     }
 
     @SuppressWarnings("unchecked")
@@ -330,30 +340,33 @@ public class ICALToJsonAttributeTest {
             .build();
         testee.service(mail);
 
-        Map<String, byte[]> jsons = (Map<String, byte[]>) mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME);
-        assertThat(jsons).hasSize(2);
-        List<String> actual = toSortedValueList(jsons);
-
-        assertThatJson(actual.get(0)).isEqualTo("{" +
-            "\"ical\": \"" + toJsonValue(ics2) + "\"," +
-            "\"sender\": \"" + SENDER.asString() + "\"," +
-            "\"recipient\": \"" + recipient.asString() + "\"," +
-            "\"uid\": \"f1514f44bf39311568d64072ac247c17656ceafde3b4b3eba961c8c5184cdc6ee047feb2aab16e43439a608f28671ab7c10e754c301b1e32001ad51dd20eac2fc7af20abf4093bbe\"," +
-            "\"sequence\": \"0\"," +
-            "\"dtstamp\": \"20170103T103250Z\"," +
-            "\"method\": \"REQUEST\"," +
-            "\"recurrence-id\": null" +
-            "}");
-        assertThatJson(actual.get(1)).isEqualTo("{" +
-            "\"ical\": \"" + toJsonValue(ics) + "\"," +
-            "\"sender\": \"" + SENDER.asString() + "\"," +
-            "\"recipient\": \"" + recipient.asString() + "\"," +
-            "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," +
-            "\"sequence\": \"0\"," +
-            "\"dtstamp\": \"20170106T115036Z\"," +
-            "\"method\": \"REQUEST\"," +
-            "\"recurrence-id\": null" +
-            "}");
+        assertThat(AttributeUtils.getValueAndCastFromMail(mail, ICALToJsonAttribute.DEFAULT_DESTINATION, MAP_STRING_BYTES_CLASS))
+                .isPresent()
+                .hasValueSatisfying(jsons -> {
+                    assertThat(jsons).hasSize(2);
+                    List<String> actual = toSortedValueList(jsons);
+
+                    assertThatJson(actual.get(0)).isEqualTo("{" +
+                        "\"ical\": \"" + toJsonValue(ics2) + "\"," +
+                        "\"sender\": \"" + SENDER.asString() + "\"," +
+                        "\"recipient\": \"" + recipient.asString() + "\"," +
+                        "\"uid\": \"f1514f44bf39311568d64072ac247c17656ceafde3b4b3eba961c8c5184cdc6ee047feb2aab16e43439a608f28671ab7c10e754c301b1e32001ad51dd20eac2fc7af20abf4093bbe\"," +
+                        "\"sequence\": \"0\"," +
+                        "\"dtstamp\": \"20170103T103250Z\"," +
+                        "\"method\": \"REQUEST\"," +
+                        "\"recurrence-id\": null" +
+                        "}");
+                    assertThatJson(actual.get(1)).isEqualTo("{" +
+                        "\"ical\": \"" + toJsonValue(ics) + "\"," +
+                        "\"sender\": \"" + SENDER.asString() + "\"," +
+                        "\"recipient\": \"" + recipient.asString() + "\"," +
+                        "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," +
+                        "\"sequence\": \"0\"," +
+                        "\"dtstamp\": \"20170106T115036Z\"," +
+                        "\"method\": \"REQUEST\"," +
+                        "\"recurrence-id\": null" +
+                        "}");
+                    });
     }
 
     @SuppressWarnings("unchecked")
@@ -376,20 +389,23 @@ public class ICALToJsonAttributeTest {
             .build();
         testee.service(mail);
 
-        Map<String, byte[]> jsons = (Map<String, byte[]>) mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME);
-        assertThat(jsons).hasSize(1);
-        List<String> actual = toSortedValueList(jsons);
-
-        assertThatJson(actual.get(0)).isEqualTo("{" +
-            "\"ical\": \"" + toJsonValue(ics) + "\"," +
-            "\"sender\": \"" + SENDER.asString() + "\"," +
-            "\"recipient\": \"" + recipient.asString() + "\"," +
-            "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," +
-            "\"sequence\": \"0\"," +
-            "\"dtstamp\": \"20170106T115036Z\"," +
-            "\"method\": \"REQUEST\"," +
-            "\"recurrence-id\": null" +
-            "}");
+        assertThat(AttributeUtils.getValueAndCastFromMail(mail, ICALToJsonAttribute.DEFAULT_DESTINATION, MAP_STRING_BYTES_CLASS))
+                .isPresent()
+                .hasValueSatisfying(jsons -> {
+                    assertThat(jsons).hasSize(1);
+                    List<String> actual = toSortedValueList(jsons);
+
+                    assertThatJson(actual.get(0)).isEqualTo("{" +
+                        "\"ical\": \"" + toJsonValue(ics) + "\"," +
+                        "\"sender\": \"" + SENDER.asString() + "\"," +
+                        "\"recipient\": \"" + recipient.asString() + "\"," +
+                        "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," +
+                        "\"sequence\": \"0\"," +
+                        "\"dtstamp\": \"20170106T115036Z\"," +
+                        "\"method\": \"REQUEST\"," +
+                        "\"recurrence-id\": null" +
+                        "}");
+                });
     }
 
     @SuppressWarnings("unchecked")
@@ -412,20 +428,23 @@ public class ICALToJsonAttributeTest {
             .build();
         testee.service(mail);
 
-        Map<String, byte[]> jsons = (Map<String, byte[]>) mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME);
-        assertThat(jsons).hasSize(1);
-        List<String> actual = toSortedValueList(jsons);
-
-        assertThatJson(actual.get(0)).isEqualTo("{" +
-            "\"ical\": \"" + toJsonValue(ics) + "\"," +
-            "\"sender\": \"" + SENDER.asString() + "\"," +
-            "\"recipient\": \"" + recipient.asString() + "\"," +
-            "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," +
-            "\"sequence\": \"0\"," +
-            "\"dtstamp\": \"20170106T115036Z\"," +
-            "\"method\": \"REQUEST\"," +
-            "\"recurrence-id\": null" +
-            "}");
+        assertThat(AttributeUtils.getValueAndCastFromMail(mail, ICALToJsonAttribute.DEFAULT_DESTINATION, MAP_STRING_BYTES_CLASS))
+                .isPresent()
+                .hasValueSatisfying(jsons -> {
+                    assertThat(jsons).hasSize(1);
+                    List<String> actual = toSortedValueList(jsons);
+
+                    assertThatJson(actual.get(0)).isEqualTo("{" +
+                        "\"ical\": \"" + toJsonValue(ics) + "\"," +
+                        "\"sender\": \"" + SENDER.asString() + "\"," +
+                        "\"recipient\": \"" + recipient.asString() + "\"," +
+                        "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," +
+                        "\"sequence\": \"0\"," +
+                        "\"dtstamp\": \"20170106T115036Z\"," +
+                        "\"method\": \"REQUEST\"," +
+                        "\"recurrence-id\": null" +
+                        "}");
+                });
     }
 
     @SuppressWarnings("unchecked")
@@ -449,19 +468,22 @@ public class ICALToJsonAttributeTest {
             .build();
         testee.service(mail);
 
-        Map<String, byte[]> jsons = (Map<String, byte[]>) mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME);
-        assertThat(jsons).hasSize(1);
-        assertThatJson(new String(jsons.values().iterator().next(), StandardCharsets.UTF_8))
-            .isEqualTo("{" +
-                "\"ical\": \"" + toJsonValue(ics) + "\"," +
-                "\"sender\": \"" + from + "\"," +
-                "\"recipient\": \"" + recipient.asString() + "\"," +
-                "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," +
-                "\"sequence\": \"0\"," +
-                "\"dtstamp\": \"20170106T115036Z\"," +
-                "\"method\": \"REQUEST\"," +
-                "\"recurrence-id\": null" +
-                "}");
+        assertThat(AttributeUtils.getValueAndCastFromMail(mail, ICALToJsonAttribute.DEFAULT_DESTINATION, MAP_STRING_BYTES_CLASS))
+                .isPresent()
+                .hasValueSatisfying(jsons -> {
+                    assertThat(jsons).hasSize(1);
+                    assertThatJson(new String(jsons.values().iterator().next(), StandardCharsets.UTF_8))
+                        .isEqualTo("{" +
+                            "\"ical\": \"" + toJsonValue(ics) + "\"," +
+                            "\"sender\": \"" + from + "\"," +
+                            "\"recipient\": \"" + recipient.asString() + "\"," +
+                            "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," +
+                            "\"sequence\": \"0\"," +
+                            "\"dtstamp\": \"20170106T115036Z\"," +
+                            "\"method\": \"REQUEST\"," +
+                            "\"recurrence-id\": null" +
+                            "}");
+                });
     }
 
     @SuppressWarnings("unchecked")
@@ -483,19 +505,22 @@ public class ICALToJsonAttributeTest {
             .build();
         testee.service(mail);
 
-        Map<String, byte[]> jsons = (Map<String, byte[]>) mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME);
-        assertThat(jsons).hasSize(1);
-        assertThatJson(new String(jsons.values().iterator().next(), StandardCharsets.UTF_8))
-            .isEqualTo("{" +
-                "\"ical\": \"" + toJsonValue(ics) + "\"," +
-                "\"sender\": \"" + SENDER.asString() + "\"," +
-                "\"recipient\": \"" + recipient.asString() + "\"," +
-                "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," +
-                "\"sequence\": \"0\"," +
-                "\"dtstamp\": \"20170106T115036Z\"," +
-                "\"method\": \"REQUEST\"," +
-                "\"recurrence-id\": null" +
-                "}");
+        assertThat(AttributeUtils.getValueAndCastFromMail(mail, ICALToJsonAttribute.DEFAULT_DESTINATION, MAP_STRING_BYTES_CLASS))
+                .isPresent()
+                .hasValueSatisfying(jsons -> {
+                    assertThat(jsons).hasSize(1);
+                    assertThatJson(new String(jsons.values().iterator().next(), StandardCharsets.UTF_8))
+                        .isEqualTo("{" +
+                            "\"ical\": \"" + toJsonValue(ics) + "\"," +
+                            "\"sender\": \"" + SENDER.asString() + "\"," +
+                            "\"recipient\": \"" + recipient.asString() + "\"," +
+                            "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," +
+                            "\"sequence\": \"0\"," +
+                            "\"dtstamp\": \"20170106T115036Z\"," +
+                            "\"method\": \"REQUEST\"," +
+                            "\"recurrence-id\": null" +
+                            "}");
+                });
     }
 
     @SuppressWarnings("unchecked")
@@ -518,19 +543,22 @@ public class ICALToJsonAttributeTest {
             .build();
         testee.service(mail);
 
-        Map<String, byte[]> jsons = (Map<String, byte[]>) mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME);
-        assertThat(jsons).hasSize(1);
-        assertThatJson(new String(jsons.values().iterator().next(), StandardCharsets.UTF_8))
-            .isEqualTo("{" +
-                "\"ical\": \"" + toJsonValue(ics) + "\"," +
-                "\"sender\": \"" + from + "\"," +
-                "\"recipient\": \"" + recipient.asString() + "\"," +
-                "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," +
-                "\"sequence\": \"0\"," +
-                "\"dtstamp\": \"20170106T115036Z\"," +
-                "\"method\": \"REQUEST\"," +
-                "\"recurrence-id\": null" +
-                "}");
+        assertThat(AttributeUtils.getValueAndCastFromMail(mail, ICALToJsonAttribute.DEFAULT_DESTINATION, MAP_STRING_BYTES_CLASS))
+                .isPresent()
+                .hasValueSatisfying(jsons -> {
+                    assertThat(jsons).hasSize(1);
+                    assertThatJson(new String(jsons.values().iterator().next(), StandardCharsets.UTF_8))
+                        .isEqualTo("{" +
+                            "\"ical\": \"" + toJsonValue(ics) + "\"," +
+                            "\"sender\": \"" + from + "\"," +
+                            "\"recipient\": \"" + recipient.asString() + "\"," +
+                            "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," +
+                            "\"sequence\": \"0\"," +
+                            "\"dtstamp\": \"20170106T115036Z\"," +
+                            "\"method\": \"REQUEST\"," +
+                            "\"recurrence-id\": null" +
+                            "}");
+                });
     }
 
     private List<String> toSortedValueList(Map<String, byte[]> jsons) {
diff --git a/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICalendarParserTest.java b/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICalendarParserTest.java
index a61fba9..8f15ddb 100644
--- a/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICalendarParserTest.java
+++ b/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICalendarParserTest.java
@@ -22,10 +22,15 @@ import static org.assertj.core.api.Assertions.assertThat;
 
 import java.io.Serializable;
 import java.util.Map;
+import java.util.Optional;
 
 import javax.mail.MessagingException;
 
 import org.apache.james.util.ClassLoaderUtils;
+import org.apache.mailet.Attribute;
+import org.apache.mailet.AttributeName;
+import org.apache.mailet.AttributeUtils;
+import org.apache.mailet.AttributeValue;
 import org.apache.mailet.Mail;
 import org.apache.mailet.base.test.FakeMail;
 import org.apache.mailet.base.test.FakeMailetConfig;
@@ -43,7 +48,9 @@ public class ICalendarParserTest {
     private static final String SOURCE_ATTRIBUTE = "sourceAttribute";
 
     private static final String DESTINATION_CUSTOM_ATTRIBUTE = "ics.dest.attribute";
+    private static final AttributeName DESTINATION_CUSTOM_ATTRIBUTE_NAME = AttributeName.of(DESTINATION_CUSTOM_ATTRIBUTE);
     private static final String SOURCE_CUSTOM_ATTRIBUTE = "ics.source.attribute";
+    private static final AttributeName SOURCE_CUSTOM_ATTRIBUTE_NAME = AttributeName.of(SOURCE_CUSTOM_ATTRIBUTE);
 
     private static final String RIGHT_ICAL_VALUE = "BEGIN:VCALENDAR\n" +
         "END:VCALENDAR";
@@ -128,7 +135,7 @@ public class ICalendarParserTest {
 
         mailet.service(mail);
 
-        assertThat(mail.getAttributeNames()).isEmpty();
+        assertThat(mail.attributes()).isEmpty();
     }
 
     @Test
@@ -141,13 +148,14 @@ public class ICalendarParserTest {
         mailet.init(mailetConfiguration);
 
         Mail mail = FakeMail.builder()
-            .attribute(SOURCE_CUSTOM_ATTRIBUTE, ImmutableMap.of())
+            .attribute(new Attribute(SOURCE_CUSTOM_ATTRIBUTE_NAME, AttributeValue.of(ImmutableMap.of())))
             .build();
 
         mailet.service(mail);
 
-        assertThat((Map<?, ?>)mail.getAttribute(DESTINATION_CUSTOM_ATTRIBUTE))
-            .isEmpty();
+        assertThat(mail.getAttribute(DESTINATION_CUSTOM_ATTRIBUTE_NAME))
+            .isPresent()
+            .hasValueSatisfying(attribute -> assertThat((Map) attribute.getValue().value()).isEmpty());
     }
 
     @Test
@@ -160,12 +168,12 @@ public class ICalendarParserTest {
         mailet.init(mailetConfiguration);
 
         Mail mail = FakeMail.builder()
-            .attribute(SOURCE_CUSTOM_ATTRIBUTE, "anyValue")
+            .attribute(new Attribute(SOURCE_CUSTOM_ATTRIBUTE_NAME, AttributeValue.of("anyValue")))
             .build();
 
         mailet.service(mail);
 
-        assertThat(mail.getAttribute(DESTINATION_CUSTOM_ATTRIBUTE)).isNull();
+        assertThat(mail.getAttribute(DESTINATION_CUSTOM_ATTRIBUTE_NAME)).isEmpty();
     }
 
     @Test
@@ -188,8 +196,12 @@ public class ICalendarParserTest {
 
         mailet.service(mail);
 
-        Map<String, Calendar> expectedCalendars = (Map<String, Calendar>)mail.getAttribute(DESTINATION_CUSTOM_ATTRIBUTE);
-        assertThat(expectedCalendars).hasSize(1);
+        Optional<Map<String, Calendar>> expectedCalendars = AttributeUtils.getValueAndCastFromMail(mail, DESTINATION_CUSTOM_ATTRIBUTE_NAME, (Class<Map<String, Calendar>>)(Object) Map.class);
+        assertThat(expectedCalendars)
+            .isPresent()
+            .hasValueSatisfying(calendars ->
+                    assertThat(calendars)
+                        .hasSize(1));
     }
 
     @Test
diff --git a/mailet/standard/src/main/java/org/apache/james/transport/mailets/RemoveMailAttribute.java b/mailet/standard/src/main/java/org/apache/james/transport/mailets/RemoveMailAttribute.java
index 72a39d0..4102908 100644
--- a/mailet/standard/src/main/java/org/apache/james/transport/mailets/RemoveMailAttribute.java
+++ b/mailet/standard/src/main/java/org/apache/james/transport/mailets/RemoveMailAttribute.java
@@ -23,10 +23,13 @@ package org.apache.james.transport.mailets;
 
 import javax.mail.MessagingException;
 
+import org.apache.james.util.streams.Iterators;
+import org.apache.mailet.AttributeName;
 import org.apache.mailet.Mail;
 import org.apache.mailet.MailetException;
 import org.apache.mailet.base.GenericMailet;
 
+import com.github.steveash.guavate.Guavate;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Splitter;
 import com.google.common.base.Strings;
@@ -51,7 +54,7 @@ public class RemoveMailAttribute extends GenericMailet {
     private static final char ATTRIBUTE_SEPARATOR_CHAR = ',';
     protected static final String MAILET_NAME_PARAMETER = "name";
 
-    private ImmutableList<String> attributesToRemove;
+    private ImmutableList<AttributeName> attributesToRemove;
 
     @Override
     public String getMailetInfo() {
@@ -69,17 +72,18 @@ public class RemoveMailAttribute extends GenericMailet {
         attributesToRemove = getAttributes(name);
     }
 
-    private ImmutableList<String> getAttributes(String name) {
-        return ImmutableList.copyOf(Splitter.on(ATTRIBUTE_SEPARATOR_CHAR)
+    private ImmutableList<AttributeName> getAttributes(String name) {
+        return Iterators.toStream(Splitter.on(ATTRIBUTE_SEPARATOR_CHAR)
             .trimResults()
-            .split(name));
+            .split(name)
+            .iterator())
+            .map(AttributeName::of)
+            .collect(Guavate.toImmutableList());
     }
 
     @Override
     public void service(Mail mail) throws MessagingException {
         Preconditions.checkNotNull(mail);
-        for (String attributeToRemove : attributesToRemove) {
-            mail.removeAttribute(attributeToRemove);
-        }
+        attributesToRemove.forEach(mail::removeAttribute);
     }
 }
diff --git a/mailet/standard/src/test/java/org/apache/james/transport/mailets/RemoveAllMailAttributesTest.java b/mailet/standard/src/test/java/org/apache/james/transport/mailets/RemoveAllMailAttributesTest.java
index 0dba54c..def4e6b 100644
--- a/mailet/standard/src/test/java/org/apache/james/transport/mailets/RemoveAllMailAttributesTest.java
+++ b/mailet/standard/src/test/java/org/apache/james/transport/mailets/RemoveAllMailAttributesTest.java
@@ -24,6 +24,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 
 import javax.mail.MessagingException;
 
+import org.apache.mailet.Attribute;
 import org.apache.mailet.Mail;
 import org.apache.mailet.Mailet;
 import org.apache.mailet.base.test.FakeMailetConfig;
@@ -53,11 +54,11 @@ public class RemoveAllMailAttributesTest {
     @Test
     public void serviceShouldRemoveAllMailAttributes() throws MessagingException {
         mail = MailUtil.createMockMail2Recipients();
-        mail.setAttribute("org.apache.james.test.junit", "true");
+        mail.setAttribute(Attribute.convertToAttribute("org.apache.james.test.junit", "true"));
 
         mailet.service(mail);
 
-        assertThat(mail.getAttributeNames()).isEmpty();
+        assertThat(mail.attributes()).isEmpty();
     }
 
     @Test
@@ -66,6 +67,6 @@ public class RemoveAllMailAttributesTest {
 
         mailet.service(mail);
 
-        assertThat(mail.getAttributeNames()).isEmpty();
+        assertThat(mail.attributes()).isEmpty();
     }
 }
diff --git a/mailet/standard/src/test/java/org/apache/james/transport/mailets/SetMailAttributeTest.java b/mailet/standard/src/test/java/org/apache/james/transport/mailets/SetMailAttributeTest.java
index e5614a1..7edd609 100644
--- a/mailet/standard/src/test/java/org/apache/james/transport/mailets/SetMailAttributeTest.java
+++ b/mailet/standard/src/test/java/org/apache/james/transport/mailets/SetMailAttributeTest.java
@@ -25,6 +25,9 @@ import static org.assertj.core.api.Assertions.assertThat;
 import javax.mail.MessagingException;
 
 import org.apache.james.util.MimeMessageUtil;
+import org.apache.mailet.Attribute;
+import org.apache.mailet.AttributeName;
+import org.apache.mailet.AttributeValue;
 import org.apache.mailet.Mail;
 import org.apache.mailet.Mailet;
 import org.apache.mailet.base.test.FakeMailetConfig;
@@ -43,10 +46,16 @@ class SetMailAttributeTest {
 
     @Test
     void shouldAddConfiguredAttributes() throws MessagingException {
+        AttributeName name1 = AttributeName.of("org.apache.james.junit1");
+        AttributeName name2 = AttributeName.of("org.apache.james.junit2");
+        AttributeValue<String> value1 = AttributeValue.of("true");
+        AttributeValue<String> value2 = AttributeValue.of("happy");
+        Attribute attribute1 = new Attribute(name1, value1);
+        Attribute attribute2 = new Attribute(name2, value2);
         FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
                 .mailetName("Test")
-                .setProperty("org.apache.james.junit1", "true")
-                .setProperty("org.apache.james.junit2", "happy")
+                .setProperty(name1.asString(), value1.value())
+                .setProperty(name2.asString(), value2.value())
                 .build();
 
         mailet.init(mailetConfig);
@@ -55,8 +64,8 @@ class SetMailAttributeTest {
         
         mailet.service(mail);
 
-        assertThat(mail.getAttribute("org.apache.james.junit1")).isEqualTo("true");
-        assertThat(mail.getAttribute("org.apache.james.junit2")).isEqualTo("happy");
+        assertThat(mail.getAttribute(name1)).contains(attribute1);
+        assertThat(mail.getAttribute(name2)).contains(attribute2);
     }
     
     @Test
@@ -71,7 +80,7 @@ class SetMailAttributeTest {
         
         mailet.service(mail);
 
-        assertThat(mail.getAttributeNames()).isEmpty();
+        assertThat(mail.attributes()).isEmpty();
     }
     
     @Test
diff --git a/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMailContext.java b/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMailContext.java
index 7fbb014..d34f5d4 100644
--- a/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMailContext.java
+++ b/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMailContext.java
@@ -29,6 +29,7 @@ import java.util.Objects;
 import java.util.Optional;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
 
 import javax.mail.MessagingException;
 import javax.mail.internet.AddressException;
@@ -37,6 +38,8 @@ import javax.mail.internet.MimeMessage;
 import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
 import org.apache.james.core.builder.MimeMessageWrapper;
+import org.apache.mailet.Attribute;
+import org.apache.mailet.AttributeName;
 import org.apache.mailet.HostAddress;
 import org.apache.mailet.LookupException;
 import org.apache.mailet.Mail;
@@ -45,11 +48,11 @@ import org.slf4j.Logger;
 
 import com.github.fge.lambdas.Throwing;
 import com.github.fge.lambdas.functions.ThrowingFunction;
+import com.github.steveash.guavate.Guavate;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
 
 @SuppressWarnings("deprecation")
 public class FakeMailContext implements MailetContext {
@@ -68,19 +71,10 @@ public class FakeMailContext implements MailetContext {
             .recipients(mail.getRecipients())
             .message(mail.getMessage())
             .state(mail.getState())
-            .attributes(buildAttributesMap(mail))
+            .attributes(mail.attributes().collect(Guavate.toImmutableList()))
             .fromMailet();
     }
 
-    private static ImmutableMap<String, Serializable> buildAttributesMap(Mail mail) {
-        Map<String, Serializable> result = new HashMap<>();
-        List<String> attributesNames = Lists.newArrayList(mail.getAttributeNames());
-        for (String attributeName: attributesNames) {
-            result.put(attributeName, mail.getAttribute(attributeName));
-        }
-        return ImmutableMap.copyOf(result);
-    }
-
     public static FakeMailContext defaultContext() {
         return builder().build();
     }
@@ -123,7 +117,7 @@ public class FakeMailContext implements MailetContext {
             private MailAddress sender;
             private Optional<Collection<MailAddress>> recipients = Optional.empty();
             private MimeMessage msg;
-            private Map<String, Serializable> attributes = new HashMap<>();
+            private Map<AttributeName, Attribute> attributes = new HashMap<>();
             private Optional<String> state = Optional.empty();
             private Optional<Boolean> fromMailet = Optional.empty();
             private Optional<Delay> delay = Optional.empty();
@@ -172,13 +166,23 @@ public class FakeMailContext implements MailetContext {
                 return this;
             }
 
-            public Builder attributes(Map<String, Serializable> attributes) {
-                this.attributes.putAll(attributes);
+            public Builder attributes(List<Attribute> attributes) {
+                this.attributes.putAll(attributes
+                    .stream()
+                    .collect(Guavate.toImmutableMap(
+                            attribute -> attribute.getName(),
+                            Function.identity()
+                    )));
                 return this;
             }
 
+            @Deprecated
             public Builder attribute(String key, Serializable value) {
-                this.attributes.put(key, value);
+                return attribute(Attribute.convertToAttribute(key, value));
+            }
+
+            public Builder attribute(Attribute attribute) {
+                this.attributes.put(attribute.getName(), attribute);
                 return this;
             }
 
@@ -205,11 +209,11 @@ public class FakeMailContext implements MailetContext {
         private final Collection<MailAddress> recipients;
         private final MimeMessage msg;
         private final Optional<String> subject;
-        private final Map<String, Serializable> attributes;
+        private final Map<AttributeName, Attribute> attributes;
         private final String state;
         private final Optional<Delay> delay;
 
-        private SentMail(MailAddress sender, Collection<MailAddress> recipients, MimeMessage msg, Map<String, Serializable> attributes, String state, Optional<Delay> delay) throws MessagingException {
+        private SentMail(MailAddress sender, Collection<MailAddress> recipients, MimeMessage msg, Map<AttributeName, Attribute> attributes, String state, Optional<Delay> delay) throws MessagingException {
             this.sender = sender;
             this.recipients = ImmutableList.copyOf(recipients);
             this.msg = tryCopyMimeMessage(msg);
@@ -369,7 +373,7 @@ public class FakeMailContext implements MailetContext {
         }
     }
 
-    private final HashMap<String, Object> attributes;
+    private final HashMap<AttributeName, Attribute> attributes;
     private final Collection<SentMail> sentMails;
     private final Collection<BouncedMail> bouncedMails;
     private final Optional<Logger> logger;
@@ -413,7 +417,11 @@ public class FakeMailContext implements MailetContext {
 
     @Override
     public Iterator<String> getAttributeNames() {
-        return attributes.keySet().iterator();
+        return attributes
+            .keySet()
+            .stream()
+            .map(AttributeName::asString)
+            .iterator();
     }
 
     @Override
@@ -525,8 +533,13 @@ public class FakeMailContext implements MailetContext {
                 .build());
     }
 
+    @Deprecated
     public void setAttribute(String name, Serializable object) {
-        attributes.put(name,object);
+        setAttribute(Attribute.convertToAttribute(name, object));
+    }
+
+    public void setAttribute(Attribute attribute) {
+        attributes.put(attribute.getName(), attribute);
     }
 
     public void storeMail(MailAddress sender, MailAddress recipient, MimeMessage msg) throws MessagingException {
diff --git a/server/container/core/src/main/java/org/apache/james/server/core/MailImpl.java b/server/container/core/src/main/java/org/apache/james/server/core/MailImpl.java
index 9d97f30..e9b2583 100644
--- a/server/container/core/src/main/java/org/apache/james/server/core/MailImpl.java
+++ b/server/container/core/src/main/java/org/apache/james/server/core/MailImpl.java
@@ -222,12 +222,6 @@ public class MailImpl implements Disposable, Mail {
             return this;
         }
 
-        @Deprecated
-        public Builder attributes(Map<String, Serializable> attributes) {
-            this.attributes(toAttributeMap(attributes).values());
-            return this;
-        }
-
         public Builder attribute(Attribute attribute) {
             this.attributes.put(attribute.getName(), attribute);
             return this;
diff --git a/server/data/data-jdbc/src/main/java/org/apache/james/mailrepository/jdbc/JDBCMailRepository.java b/server/data/data-jdbc/src/main/java/org/apache/james/mailrepository/jdbc/JDBCMailRepository.java
index 4839de7..8c8572b 100644
--- a/server/data/data-jdbc/src/main/java/org/apache/james/mailrepository/jdbc/JDBCMailRepository.java
+++ b/server/data/data-jdbc/src/main/java/org/apache/james/mailrepository/jdbc/JDBCMailRepository.java
@@ -64,9 +64,12 @@ import org.apache.james.server.core.MimeMessageWrapper;
 import org.apache.james.util.sql.JDBCUtil;
 import org.apache.james.util.sql.SqlResources;
 import org.apache.mailet.Mail;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.github.steveash.guavate.Guavate;
+
 /**
  * Implementation of a MailRepository on a database.
  * 
@@ -474,11 +477,12 @@ public class JDBCMailRepository extends AbstractMailRepository {
                             if (mc instanceof MailImpl) {
                                 oos.writeObject(((MailImpl) mc).getAttributesRaw());
                             } else {
-                                HashMap<String, Serializable> temp = new HashMap<>();
-                                for (Iterator<String> i = mc.getAttributeNames(); i.hasNext();) {
-                                    String hashKey = i.next();
-                                    temp.put(hashKey, mc.getAttribute(hashKey));
-                                }
+                                Map<String, Serializable> temp = mc.attributes()
+                                    .collect(Guavate.toImmutableMap(
+                                            attribute -> attribute.getName().asString(),
+                                            attribute -> (Serializable) attribute.getValue().value()
+                                    ));
+
                                 oos.writeObject(temp);
                             }
                             oos.flush();
@@ -562,11 +566,12 @@ public class JDBCMailRepository extends AbstractMailRepository {
                             if (mc instanceof MailImpl) {
                                 oos.writeObject(((MailImpl) mc).getAttributesRaw());
                             } else {
-                                HashMap<String, Serializable> temp = new HashMap<>();
-                                for (Iterator<String> i = mc.getAttributeNames(); i.hasNext();) {
-                                    String hashKey = i.next();
-                                    temp.put(hashKey, mc.getAttribute(hashKey));
-                                }
+                                Map<String, Serializable> temp = mc.attributes()
+                                        .collect(Guavate.toImmutableMap(
+                                                attribute -> attribute.getName().asString(),
+                                                attribute -> (Serializable) attribute.getValue().value()
+                                        ));
+
                                 oos.writeObject(temp);
                             }
                             oos.flush();
diff --git a/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/CamelMailetProcessor.java b/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/CamelMailetProcessor.java
index 1c9a473..16c0dab 100644
--- a/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/CamelMailetProcessor.java
+++ b/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/CamelMailetProcessor.java
@@ -173,7 +173,7 @@ public class CamelMailetProcessor extends AbstractStateMailetProcessor implement
 
         private void handleMailet(Exchange exchange, CamelMailetProcessor container, CamelProcessor mailetProccessor) throws Exception {
             Mail mail = exchange.getIn().getBody(Mail.class);
-            boolean isMatched = mail.removeAttribute(MatcherSplitter.MATCHER_MATCHED_ATTRIBUTE) != null;
+            boolean isMatched = mail.removeAttribute(MatcherSplitter.MATCHER_MATCHED_ATTRIBUTE).isPresent();
             if (isMatched) {
                 mailetProccessor.process(mail);
             }
diff --git a/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/MatcherMatch.java b/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/MatcherMatch.java
index 038f05d..41c61ad 100644
--- a/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/MatcherMatch.java
+++ b/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/MatcherMatch.java
@@ -33,6 +33,6 @@ public class MatcherMatch implements Predicate {
     @Override
     public boolean matches(Exchange arg0) {
         Mail m = arg0.getIn().getBody(Mail.class);
-        return m.removeAttribute(MatcherSplitter.MATCHER_MATCHED_ATTRIBUTE) != null;
+        return m.removeAttribute(MatcherSplitter.MATCHER_MATCHED_ATTRIBUTE).isPresent();
     }
 }
diff --git a/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/MatcherSplitter.java b/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/MatcherSplitter.java
index 7f328fe..03fe79a 100644
--- a/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/MatcherSplitter.java
+++ b/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/MatcherSplitter.java
@@ -39,6 +39,9 @@ import org.apache.james.metrics.api.MetricFactory;
 import org.apache.james.metrics.api.TimeMetric;
 import org.apache.james.server.core.MailImpl;
 import org.apache.james.util.MDCBuilder;
+import org.apache.mailet.Attribute;
+import org.apache.mailet.AttributeName;
+import org.apache.mailet.AttributeValue;
 import org.apache.mailet.Mail;
 import org.apache.mailet.Matcher;
 import org.slf4j.Logger;
@@ -55,7 +58,7 @@ public class MatcherSplitter {
     private static final Logger LOGGER = LoggerFactory.getLogger(MatcherSplitter.class);
 
     /** Headername which is used to indicate that the matcher matched */
-    public static final String MATCHER_MATCHED_ATTRIBUTE = "matched";
+    public static final AttributeName MATCHER_MATCHED_ATTRIBUTE = AttributeName.of("matched");
 
     private final MetricFactory metricFactory;
     private final CamelMailetProcessor container;
@@ -154,7 +157,7 @@ public class MatcherSplitter {
 
                     // Set a header because the matcher matched. This can be
                     // used later when processing the route
-                    newMail.setAttribute(MATCHER_MATCHED_ATTRIBUTE, true);
+                    newMail.setAttribute(new Attribute(MATCHER_MATCHED_ATTRIBUTE, AttributeValue.of(true)));
 
                     // add the new generated mail to the mails list
                     mails.add(newMail);
@@ -164,7 +167,7 @@ public class MatcherSplitter {
             if (fullMatch) {
                 // Set a header because the matcher matched. This can be used
                 // later when processing the route
-                mail.setAttribute(MATCHER_MATCHED_ATTRIBUTE, true);
+                mail.setAttribute(new Attribute(MATCHER_MATCHED_ATTRIBUTE, AttributeValue.of(true)));
             }
 
             // add mailMsg to the mails list
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java
index 391da56..a83fc32 100755
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/AbstractRecipientRewriteTable.java
@@ -42,6 +42,9 @@ import org.apache.james.rrt.api.RecipientRewriteTable;
 import org.apache.james.rrt.lib.Mapping;
 import org.apache.james.rrt.lib.UserRewritter;
 import org.apache.james.server.core.MailImpl;
+import org.apache.mailet.Attribute;
+import org.apache.mailet.AttributeName;
+import org.apache.mailet.AttributeValue;
 import org.apache.mailet.Experimental;
 import org.apache.mailet.Mail;
 import org.apache.mailet.base.GenericMailet;
@@ -59,7 +62,7 @@ import org.slf4j.LoggerFactory;
 @Experimental
 public abstract class AbstractRecipientRewriteTable extends GenericMailet {
     private static final Logger LOGGER = LoggerFactory.getLogger(AbstractRecipientRewriteTable.class);
-    private static final String MARKER = "org.apache.james.transport.mailets.AbstractRecipientRewriteTable.mapped";
+    private static final AttributeName MARKER = AttributeName.of("org.apache.james.transport.mailets.AbstractRecipientRewriteTable.mapped");
     private DNSService dns;
     private DomainList domainList;
 
@@ -83,7 +86,7 @@ public abstract class AbstractRecipientRewriteTable extends GenericMailet {
      */
     @Override
     public void service(Mail mail) throws MessagingException {
-        if (mail.getAttribute(MARKER) != null) {
+        if (mail.getAttribute(MARKER).isPresent()) {
             mail.removeAttribute(MARKER);
             return;
         }
@@ -203,7 +206,7 @@ public abstract class AbstractRecipientRewriteTable extends GenericMailet {
                 }
 
                 newMail.setRecipients(recipientsToAddForward);
-                newMail.setAttribute(MARKER, Boolean.TRUE);
+                newMail.setAttribute(new Attribute(MARKER, AttributeValue.of(Boolean.TRUE)));
                 getMailetContext().sendMail(newMail);
             } finally {
                 newMail.dispose();
diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/WithStorageDirectiveTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/WithStorageDirectiveTest.java
index 2f61236..1c26498 100644
--- a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/WithStorageDirectiveTest.java
+++ b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/WithStorageDirectiveTest.java
@@ -101,22 +101,26 @@ public class WithStorageDirectiveTest {
 
     @Test
     public void serviceShouldOverridePreviousStorageDirectives() throws Exception {
-        String targetFolderName = "Spam";
+        AttributeName name1 = AttributeName.of("DeliveryPath_recipient1@localhost");
+        AttributeName name2 = AttributeName.of("DeliveryPath_recipient2@localhost");
+        AttributeValue<String> targetFolderName = AttributeValue.of("Spam");
+        Attribute attribute1 = new Attribute(name1, targetFolderName);
+        Attribute attribute2 = new Attribute(name2, targetFolderName);
         testee.init(FakeMailetConfig.builder()
-            .setProperty(WithStorageDirective.TARGET_FOLDER_NAME, targetFolderName)
+            .setProperty(WithStorageDirective.TARGET_FOLDER_NAME, targetFolderName.value())
             .build());
 
         FakeMail mail = FakeMail.builder()
             .recipients(MailAddressFixture.RECIPIENT1, MailAddressFixture.RECIPIENT2)
-            .attribute("DeliveryPath_recipient2@localhost", "otherFolder")
+            .attribute(new Attribute(name2, AttributeValue.of("otherFolder")))
             .build();
 
         testee.service(mail);
 
-        softly.assertThat(mail.getAttributeNames())
-            .containsOnly("DeliveryPath_recipient2@localhost", "DeliveryPath_recipient1@localhost");
-        softly.assertThat(mail.getAttribute("DeliveryPath_recipient1@localhost")).isEqualTo(targetFolderName);
-        softly.assertThat(mail.getAttribute("DeliveryPath_recipient2@localhost")).isEqualTo(targetFolderName);
+        softly.assertThat(mail.attributes())
+            .containsExactlyInAnyOrder(attribute1, attribute2);
+        softly.assertThat(mail.getAttribute(name1)).contains(attribute1);
+        softly.assertThat(mail.getAttribute(name2)).contains(attribute2);
     }
 
 }
\ No newline at end of file
diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/SieveIntegrationTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/SieveIntegrationTest.java
index 66ac1cb..bfee91b 100644
--- a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/SieveIntegrationTest.java
+++ b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/SieveIntegrationTest.java
@@ -38,6 +38,9 @@ import org.apache.james.transport.mailets.Sieve;
 import org.apache.james.transport.mailets.jsieve.ResourceLocator;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.james.util.MimeMessageUtil;
+import org.apache.mailet.Attribute;
+import org.apache.mailet.AttributeName;
+import org.apache.mailet.AttributeValue;
 import org.apache.mailet.Mail;
 import org.apache.mailet.base.test.FakeMail;
 import org.apache.mailet.base.test.FakeMailContext;
@@ -58,6 +61,15 @@ public class SieveIntegrationTest {
     public static final MailboxPath NOT_SELECTED_MAILBOX = MailboxPath.forUser(LOCAL_PART, "INBOX.not.selected");
     public static final MailboxPath SELECTED_MAILBOX = MailboxPath.forUser(LOCAL_PART, "INBOX.select");
     public static final MailboxPath INBOX = MailboxPath.forUser(LOCAL_PART, "INBOX");
+    public static final MailboxPath INBOX_ANY = MailboxPath.forUser(LOCAL_PART, "INBOX.any");
+
+    public static final AttributeName ATTRIBUTE_NAME = AttributeName.of(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART);
+    public static final Attribute ATTRIBUTE_INBOX = new Attribute(ATTRIBUTE_NAME, AttributeValue.of(expressMailboxNameWithSlash(INBOX.getName())));
+    public static final Attribute ATTRIBUTE_INBOX_ANY = new Attribute(ATTRIBUTE_NAME, AttributeValue.of(expressMailboxNameWithSlash(INBOX_ANY.getName())));
+    public static final Attribute ATTRIBUTE_SELECTED_MAILBOX = new Attribute(ATTRIBUTE_NAME, AttributeValue.of(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName())));
+    public static final Attribute ATTRIBUTE_NOT_SELECTED_MAILBOX = new Attribute(ATTRIBUTE_NAME, AttributeValue.of(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName())));
+    public static final AttributeName ATTRIBUTE_NAME_DOMAIN = AttributeName.of(MailStore.DELIVERY_PATH_PREFIX + RECEIVER_DOMAIN_COM);
+    public static final Attribute ATTRIBUTE_INBOX_DOMAIN = new Attribute(ATTRIBUTE_NAME_DOMAIN, AttributeValue.of(expressMailboxNameWithSlash(INBOX.getName())));
 
     private Sieve testee;
     private UsersRepository usersRepository;
@@ -83,7 +95,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + RECEIVER_DOMAIN_COM)).isNull();
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME_DOMAIN)).isEmpty();
         assertThat(mail.getState()).isEqualTo(Mail.DEFAULT);
     }
 
@@ -96,7 +108,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + RECEIVER_DOMAIN_COM)).isEqualTo("/INBOX");
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME_DOMAIN)).contains(ATTRIBUTE_INBOX_DOMAIN);
     }
 
     @Test
@@ -108,7 +120,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo("/INBOX");
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_INBOX);
     }
 
     @Test
@@ -118,7 +130,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo("/INBOX");
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_INBOX);
     }
 
     @Test
@@ -138,7 +150,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo("/INBOX/any");
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_INBOX_ANY);
     }
 
     @Test
@@ -148,7 +160,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -158,7 +170,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -168,7 +180,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -178,7 +190,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -188,7 +200,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -198,7 +210,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -208,7 +220,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -218,7 +230,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -228,7 +240,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -238,7 +250,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -248,7 +260,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(INBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_INBOX);
     }
 
     @Test
@@ -258,7 +270,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -274,8 +286,8 @@ public class SieveIntegrationTest {
             .build();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART))
-            .isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME))
+            .contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
 
@@ -286,7 +298,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubject("JAMES-1620 revolution");
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -297,7 +309,7 @@ public class SieveIntegrationTest {
         mail.setMessageSize(100);
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -308,7 +320,7 @@ public class SieveIntegrationTest {
         mail.setMessageSize(100);
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -319,7 +331,7 @@ public class SieveIntegrationTest {
         mail.setMessageSize(1000);
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -330,7 +342,7 @@ public class SieveIntegrationTest {
         mail.setMessageSize(1000);
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -340,7 +352,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Cc", "source@any.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
 
@@ -351,7 +363,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Cc", "source1@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
 
@@ -362,7 +374,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Cc", "source1@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -372,7 +384,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Cc", "source@domain.org"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -382,7 +394,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Cc", "source@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -392,7 +404,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Bcc", "source@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -402,7 +414,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Bcc", "source2@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -412,7 +424,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Bcc", "source@domain.org"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -439,7 +451,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Resend-From", "source@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -449,7 +461,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Cc", "source@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -459,7 +471,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Cc", "source2@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -469,7 +481,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Cc", "source@domain.org"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -479,7 +491,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Cc", "source@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -489,7 +501,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("From", "source@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -499,7 +511,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("From", "source2@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -509,7 +521,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("From", "source@domain.org"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -519,7 +531,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Resent-To", "source@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -529,7 +541,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("To", "source@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -539,7 +551,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("To", "source2@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -549,7 +561,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("To", "source@domain.org"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -559,7 +571,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("To", "source@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -569,7 +581,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Sender", "source@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -579,7 +591,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Sender", "source2@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -589,7 +601,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Sender", "source@domain.org"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -599,7 +611,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("From", "source@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -609,7 +621,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Resend-From", "source@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -619,7 +631,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Resend-From", "source2@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -629,7 +641,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Resend-From", "source@domain.org"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -639,7 +651,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("To", "source@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -649,7 +661,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Resend-To", "source@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -659,7 +671,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Resend-To", "source2@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -669,7 +681,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("Resend-To", "source@domain.org"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -679,7 +691,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMailWithSubjectAndHeaders("Default", new Header("From", "source@domain.com"));
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -689,7 +701,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -699,7 +711,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -709,7 +721,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -719,7 +731,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -729,7 +741,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -739,7 +751,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -749,7 +761,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -759,7 +771,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -769,7 +781,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(NOT_SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_NOT_SELECTED_MAILBOX);
     }
 
     @Test
@@ -779,7 +791,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
     }
 
     @Test
@@ -796,7 +808,7 @@ public class SieveIntegrationTest {
             .fromMailet()
             .build());
         // No action taken
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isNull();
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).isEmpty();
     }
 
     @Test
@@ -806,7 +818,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(INBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_INBOX);
 
         FakeMailContext.SentMail expectedSentMail = FakeMailContext.sentMailBuilder()
             .sender(new MailAddress(RECEIVER_DOMAIN_COM))
@@ -824,7 +836,7 @@ public class SieveIntegrationTest {
 
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(INBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_INBOX);
         assertThat(fakeMailContext.getSentMails()).isEmpty();
     }
 
@@ -835,7 +847,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(INBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_INBOX);
         assertThat(fakeMailContext.getSentMails()).isEmpty();
     }
 
@@ -846,7 +858,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
         assertThat(fakeMailContext.getSentMails()).isEmpty();
     }
 
@@ -857,7 +869,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(INBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_INBOX);
         assertThat(fakeMailContext.getSentMails()).isEmpty();
     }
 
@@ -868,7 +880,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(INBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_INBOX);
         FakeMailContext.SentMail expectedSentMail = FakeMailContext.sentMailBuilder()
             .sender(new MailAddress(RECEIVER_DOMAIN_COM))
             .recipient(new MailAddress("sender@any.com"))
@@ -884,7 +896,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(SELECTED_MAILBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_SELECTED_MAILBOX);
         FakeMailContext.SentMail expectedSentMail = FakeMailContext.sentMailBuilder()
             .sender(new MailAddress(RECEIVER_DOMAIN_COM))
             .recipient(new MailAddress("sender@any.com"))
@@ -900,7 +912,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(INBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_INBOX);
         FakeMailContext.SentMail expectedSentMail = FakeMailContext.sentMailBuilder()
             .sender(new MailAddress("benwa@apache.org"))
             .recipient(new MailAddress("sender@any.com"))
@@ -916,7 +928,7 @@ public class SieveIntegrationTest {
         FakeMail mail = createMail();
         testee.service(mail);
 
-        assertThat(mail.getAttribute(MailStore.DELIVERY_PATH_PREFIX + LOCAL_PART)).isEqualTo(expressMailboxNameWithSlash(INBOX.getName()));
+        assertThat(mail.getAttribute(ATTRIBUTE_NAME)).contains(ATTRIBUTE_INBOX);
         FakeMailContext.SentMail expectedSentMail = FakeMailContext.sentMailBuilder()
             .sender(new MailAddress(RECEIVER_DOMAIN_COM))
             .recipient(new MailAddress("sender@any.com"))
@@ -966,7 +978,7 @@ public class SieveIntegrationTest {
             .build();
     }
 
-    private String expressMailboxNameWithSlash(String name) {
+    private static String expressMailboxNameWithSlash(String name) {
         return '/' + name.replace('.', '/');
     }
 }
diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remote/delivery/RemoteDeliveryTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remote/delivery/RemoteDeliveryTest.java
index d9f84fc..f7b5bd1 100644
--- a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remote/delivery/RemoteDeliveryTest.java
+++ b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remote/delivery/RemoteDeliveryTest.java
@@ -22,13 +22,11 @@ package org.apache.james.transport.mailets.remote.delivery;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 
-import java.io.Serializable;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
-import org.apache.commons.lang3.tuple.Pair;
 import org.apache.james.core.MailAddress;
 import org.apache.james.dnsservice.api.DNSService;
 import org.apache.james.domainlist.api.DomainList;
@@ -39,7 +37,8 @@ import org.apache.james.queue.api.ManageableMailQueue;
 import org.apache.james.queue.api.RawMailQueueItemDecoratorFactory;
 import org.apache.james.queue.memory.MemoryMailQueueFactory;
 import org.apache.james.transport.mailets.RemoteDelivery;
-import org.apache.james.util.streams.Iterators;
+import org.apache.mailet.Attribute;
+import org.apache.mailet.AttributeName;
 import org.apache.mailet.Mail;
 import org.apache.mailet.base.MailAddressFixture;
 import org.apache.mailet.base.test.FakeMail;
@@ -47,7 +46,6 @@ import org.apache.mailet.base.test.FakeMailetConfig;
 import org.junit.Before;
 import org.junit.Test;
 
-import com.github.steveash.guavate.Guavate;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 
@@ -55,10 +53,7 @@ public class RemoteDeliveryTest {
 
     public static class MailProjection {
         public static MailProjection from(Mail mail) {
-            return new MailProjection(mail.getName(), mail.getRecipients(),
-                Iterators.toStream(mail.getAttributeNames())
-                    .map(name -> Pair.of(name, mail.getAttribute(name)))
-                    .collect(Guavate.toImmutableMap(Pair::getKey, Pair::getValue)));
+            return new MailProjection(mail.getName(), mail.getRecipients(), mail.attributesMap());
         }
 
         public static MailProjection from(ManageableMailQueue.MailQueueItemView item) {
@@ -67,9 +62,9 @@ public class RemoteDeliveryTest {
 
         private final String name;
         private final List<MailAddress> recipients;
-        private final Map<String, Serializable> attributes;
+        private final ImmutableMap<AttributeName, Attribute> attributes;
 
-        public MailProjection(String name, Collection<MailAddress> recipients, Map<String, Serializable> attributes) {
+        public MailProjection(String name, Collection<MailAddress> recipients, Map<AttributeName, Attribute> attributes) {
             this.name = name;
             this.recipients = ImmutableList.copyOf(recipients);
             this.attributes = ImmutableMap.copyOf(attributes);
diff --git a/server/mailrepository/mailrepository-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryMailDAO.java b/server/mailrepository/mailrepository-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryMailDAO.java
index 98b3bf8..6e83900 100644
--- a/server/mailrepository/mailrepository-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryMailDAO.java
+++ b/server/mailrepository/mailrepository-cassandra/src/main/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryMailDAO.java
@@ -69,7 +69,9 @@ import org.apache.james.core.MaybeSender;
 import org.apache.james.mailrepository.api.MailKey;
 import org.apache.james.mailrepository.api.MailRepositoryUrl;
 import org.apache.james.server.core.MailImpl;
-import org.apache.james.util.streams.Iterators;
+import org.apache.mailet.Attribute;
+import org.apache.mailet.AttributeName;
+import org.apache.mailet.AttributeValue;
 import org.apache.mailet.Mail;
 import org.apache.mailet.PerRecipientHeaders;
 
@@ -208,11 +210,11 @@ public class CassandraMailRepositoryMailDAO implements CassandraMailRepositoryMa
             blobIdFactory.from(row.getString(BODY_BLOB_ID)));
     }
 
-    private Map<String, Serializable> toAttributes(Map<String, ByteBuffer> rowAttributes) {
+    private ImmutableList<Attribute> toAttributes(Map<String, ByteBuffer> rowAttributes) {
         return rowAttributes.entrySet()
             .stream()
-            .map(entry -> Pair.of(entry.getKey(), fromByteBuffer(entry.getValue())))
-            .collect(Guavate.toImmutableMap(Pair::getLeft, Pair::getRight));
+            .map(entry -> new Attribute(AttributeName.of(entry.getKey()), fromByteBuffer(entry.getValue())))
+            .collect(Guavate.toImmutableList());
     }
 
     private ImmutableList<String> asStringList(Collection<MailAddress> mailAddresses) {
@@ -220,10 +222,11 @@ public class CassandraMailRepositoryMailDAO implements CassandraMailRepositoryMa
     }
 
     private ImmutableMap<String, ByteBuffer> toRawAttributeMap(Mail mail) {
-        return Iterators.toStream(mail.getAttributeNames())
-            .map(name -> Pair.of(name, mail.getAttribute(name)))
-            .map(pair -> Pair.of(pair.getLeft(), toByteBuffer(pair.getRight())))
-            .collect(Guavate.toImmutableMap(Pair::getLeft, Pair::getRight));
+        return mail.attributes()
+            .map(attribute -> Pair.of(attribute.getName(), attribute.getValue()))
+            .collect(Guavate.toImmutableMap(
+                pair -> pair.getLeft().asString(),
+                pair -> toByteBuffer((Serializable) pair.getRight().value())));
     }
 
     private ImmutableMap<String, UDTValue> toHeaderMap(PerRecipientHeaders perRecipientHeaders) {
@@ -261,12 +264,12 @@ public class CassandraMailRepositoryMailDAO implements CassandraMailRepositoryMa
         }
     }
 
-    private Serializable fromByteBuffer(ByteBuffer byteBuffer) {
+    private AttributeValue<?> fromByteBuffer(ByteBuffer byteBuffer) {
         try {
             byte[] data = new byte[byteBuffer.remaining()];
             byteBuffer.get(data);
             ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(data));
-            return (Serializable) objectInputStream.readObject();
+            return AttributeValue.ofAny(objectInputStream.readObject());
         } catch (IOException | ClassNotFoundException e) {
             throw new RuntimeException(e);
         }
diff --git a/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryMailDAOTest.java b/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryMailDAOTest.java
index 7a48bcb..eebf29a 100644
--- a/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryMailDAOTest.java
+++ b/server/mailrepository/mailrepository-cassandra/src/test/java/org/apache/james/mailrepository/cassandra/CassandraMailRepositoryMailDAOTest.java
@@ -144,8 +144,8 @@ class CassandraMailRepositoryMailDAOTest {
             String remoteAddr = "remoteAddr";
             String remoteHost = "remoteHost";
             PerRecipientHeaders.Header header = PerRecipientHeaders.Header.builder().name("headerName").value("headerValue").build();
-            String attributeName = "att1";
             ImmutableList<String> attributeValue = ImmutableList.of("value1", "value2");
+            Attribute attribute = Attribute.convertToAttribute("att1", attributeValue);
 
             testee.store(URL,
                 FakeMail.builder()
@@ -157,7 +157,7 @@ class CassandraMailRepositoryMailDAOTest {
                     .remoteAddr(remoteAddr)
                     .remoteHost(remoteHost)
                     .addHeaderForRecipient(header, MailAddressFixture.RECIPIENT1)
-                    .attribute(attributeName, attributeValue)
+                    .attribute(attribute)
                     .build(),
                 blobIdHeader,
                 blobIdBody)
@@ -174,8 +174,8 @@ class CassandraMailRepositoryMailDAOTest {
                 softly.assertThat(partialMail.getState()).isEqualTo(state);
                 softly.assertThat(partialMail.getRemoteAddr()).isEqualTo(remoteAddr);
                 softly.assertThat(partialMail.getRemoteHost()).isEqualTo(remoteHost);
-                softly.assertThat(partialMail.getAttributeNames()).containsOnly(attributeName);
-                softly.assertThat(partialMail.getAttribute(attributeName)).isEqualTo(attributeValue);
+                softly.assertThat(partialMail.attributes()).containsOnly(attribute);
+                softly.assertThat(partialMail.getAttribute(attribute.getName())).contains(attribute);
                 softly.assertThat(partialMail.getPerRecipientSpecificHeaders().getRecipientsWithSpecificHeaders())
                     .containsOnly(MailAddressFixture.RECIPIENT1);
                 softly.assertThat(partialMail.getPerRecipientSpecificHeaders().getHeadersForRecipient(MailAddressFixture.RECIPIENT1))
diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/MailDto.java b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/MailDto.java
index 053a2bc..210979e 100644
--- a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/MailDto.java
+++ b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/dto/MailDto.java
@@ -29,7 +29,6 @@ import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
-import java.util.function.Function;
 
 import javax.mail.Header;
 import javax.mail.MessagingException;
@@ -41,7 +40,6 @@ import org.apache.james.mime4j.stream.MimeConfig;
 import org.apache.james.mime4j.util.MimeUtil;
 import org.apache.james.util.mime.MessageContentExtractor;
 import org.apache.james.util.mime.MessageContentExtractor.MessageContent;
-import org.apache.james.util.streams.Iterators;
 import org.apache.mailet.Mail;
 import org.apache.mailet.PerRecipientHeaders;
 
@@ -172,8 +170,10 @@ public class MailDto {
             return Optional.empty();
         }
 
-        return Optional.of(Iterators.toStream(mail.getAttributeNames())
-            .collect(Guavate.toImmutableMap(Function.identity(), attributeName -> mail.getAttribute(attributeName).toString())));
+        return Optional.of(mail.attributes()
+            .collect(Guavate.toImmutableMap(
+                attribute -> attribute.getName().asString(),
+                attribute -> attribute.getValue().value().toString())));
     }
 
     private final String name;
diff --git a/server/queue/queue-activemq/src/main/java/org/apache/james/queue/activemq/ActiveMQMailQueueItem.java b/server/queue/queue-activemq/src/main/java/org/apache/james/queue/activemq/ActiveMQMailQueueItem.java
index e9d0e98..297c613 100644
--- a/server/queue/queue-activemq/src/main/java/org/apache/james/queue/activemq/ActiveMQMailQueueItem.java
+++ b/server/queue/queue-activemq/src/main/java/org/apache/james/queue/activemq/ActiveMQMailQueueItem.java
@@ -52,7 +52,7 @@ public class ActiveMQMailQueueItem extends JMSMailQueueItem implements ActiveMQS
     public void done(boolean success) throws MailQueueException {
         super.done(success);
         if (success) {
-            if (message instanceof ActiveMQBlobMessage && getMail().getAttribute(JAMES_REUSE_BLOB_URL) == null) {
+            if (message instanceof ActiveMQBlobMessage && !getMail().getAttribute(JAMES_REUSE_BLOB_URL).isPresent()) {
 
                 // This should get removed once this jira issue was fixed
                 // https://issues.apache.org/activemq/browse/AMQ-1529
diff --git a/server/queue/queue-activemq/src/main/java/org/apache/james/queue/activemq/ActiveMQSupport.java b/server/queue/queue-activemq/src/main/java/org/apache/james/queue/activemq/ActiveMQSupport.java
index 8b9e4d2..56841fa 100644
--- a/server/queue/queue-activemq/src/main/java/org/apache/james/queue/activemq/ActiveMQSupport.java
+++ b/server/queue/queue-activemq/src/main/java/org/apache/james/queue/activemq/ActiveMQSupport.java
@@ -19,6 +19,7 @@
 package org.apache.james.queue.activemq;
 
 import org.apache.james.queue.jms.JMSSupport;
+import org.apache.mailet.AttributeName;
 
 /**
  * Interface which should get implemented by ActiveMQ depending implementions
@@ -38,6 +39,6 @@ public interface ActiveMQSupport extends JMSSupport {
     /**
      * Indicate that the Blobmessage content is reused for a new message
      */
-    String JAMES_REUSE_BLOB_URL = " JAMES_REUSE_BLOB_URL";
+    AttributeName JAMES_REUSE_BLOB_URL = AttributeName.of(" JAMES_REUSE_BLOB_URL");
 
 }
diff --git a/server/queue/queue-api/src/test/java/org/apache/james/queue/api/MailQueueContract.java b/server/queue/queue-api/src/test/java/org/apache/james/queue/api/MailQueueContract.java
index be3029d..d6a3ec5 100644
--- a/server/queue/queue-api/src/test/java/org/apache/james/queue/api/MailQueueContract.java
+++ b/server/queue/queue-api/src/test/java/org/apache/james/queue/api/MailQueueContract.java
@@ -45,6 +45,7 @@ import org.apache.james.core.MaybeSender;
 import org.apache.james.core.builder.MimeMessageBuilder;
 import org.apache.james.junit.ExecutorExtension;
 import org.apache.james.util.concurrency.ConcurrentTestRunner;
+import org.apache.mailet.Attribute;
 import org.apache.mailet.Mail;
 import org.apache.mailet.PerRecipientHeaders;
 import org.apache.mailet.base.test.FakeMail;
diff --git a/server/queue/queue-api/src/test/java/org/apache/james/queue/api/ManageableMailQueueContract.java b/server/queue/queue-api/src/test/java/org/apache/james/queue/api/ManageableMailQueueContract.java
index 5c76b10..0f7b019 100644
--- a/server/queue/queue-api/src/test/java/org/apache/james/queue/api/ManageableMailQueueContract.java
+++ b/server/queue/queue-api/src/test/java/org/apache/james/queue/api/ManageableMailQueueContract.java
@@ -459,20 +459,21 @@ public interface ManageableMailQueueContract extends MailQueueContract {
 
     @Test
     default void browseShouldReturnMailsWithAttributes() throws Exception {
+        Attribute attribute1 = Attribute.convertToAttribute("Attribute Name 1", "Attribute Value 1");
+        Attribute attribute2 = Attribute.convertToAttribute("Attribute Name 2", "Attribute Value 2");
+
         ManageableMailQueue mailQueue = getManageableMailQueue();
         mailQueue.enQueue(defaultMail()
-            .attributes(ImmutableList.of(
-                Attribute.convertToAttribute("Attribute Name 1", "Attribute Value 1"),
-                Attribute.convertToAttribute("Attribute Name 2", "Attribute Value 2")))
+            .attributes(ImmutableList.of(attribute1, attribute2))
             .name("mail with blob")
             .build());
 
         Mail mail = mailQueue.browse().next().getMail();
-        assertSoftly(softly ->  {
-            softly.assertThat(mail.getAttribute("Attribute Name 1"))
-                .isEqualTo("Attribute Value 1");
-            softly.assertThat(mail.getAttribute("Attribute Name 2"))
-                .isEqualTo("Attribute Value 2");
+        assertSoftly(softly -> {
+            softly.assertThat(mail.getAttribute(attribute1.getName()))
+                .contains(attribute1);
+            softly.assertThat(mail.getAttribute(attribute2.getName()))
+                .contains(attribute2);
         });
     }
 
diff --git a/server/queue/queue-jms/src/main/java/org/apache/james/queue/jms/JMSMailQueue.java b/server/queue/queue-jms/src/main/java/org/apache/james/queue/jms/JMSMailQueue.java
index 07b3128..a863479 100644
--- a/server/queue/queue-jms/src/main/java/org/apache/james/queue/jms/JMSMailQueue.java
+++ b/server/queue/queue-jms/src/main/java/org/apache/james/queue/jms/JMSMailQueue.java
@@ -20,6 +20,7 @@ package org.apache.james.queue.jms;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.Serializable;
 import java.time.Instant;
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
@@ -65,6 +66,7 @@ import org.apache.james.queue.api.ManageableMailQueue;
 import org.apache.james.server.core.MailImpl;
 import org.apache.james.server.core.MimeMessageCopyOnWriteProxy;
 import org.apache.james.util.SerializationUtil;
+import org.apache.mailet.AttributeName;
 import org.apache.mailet.Mail;
 import org.apache.mailet.PerRecipientHeaders;
 import org.slf4j.Logger;
@@ -72,8 +74,10 @@ import org.slf4j.LoggerFactory;
 import org.threeten.extra.Temporals;
 
 import com.github.fge.lambdas.Throwing;
+import com.github.steveash.guavate.Guavate;
 import com.google.common.base.Joiner;
 import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterators;
 
 /**
@@ -336,10 +340,16 @@ public class JMSMailQueue implements ManageableMailQueue, JMSSupport, MailPriori
 
         String sender = mail.getMaybeSender().asString("");
 
-        org.apache.james.util.streams.Iterators.toStream(mail.getAttributeNames())
-                .forEach(attrName -> props.put(attrName, SerializationUtil.serialize(mail.getAttribute(attrName))));
+        props.putAll(mail.attributes()
+            .collect(Guavate.toImmutableMap(
+                attribute -> attribute.getName().asString(),
+                attribute -> SerializationUtil.serialize((Serializable) attribute.getValue().value()))));
 
-        props.put(JAMES_MAIL_ATTRIBUTE_NAMES, joiner.join(mail.getAttributeNames()));
+        ImmutableList<String> attributeNames = mail.attributeNames()
+            .map(AttributeName::asString)
+            .collect(Guavate.toImmutableList());
+
+        props.put(JAMES_MAIL_ATTRIBUTE_NAMES, joiner.join(attributeNames));
         props.put(JAMES_MAIL_SENDER, sender);
         props.put(JAMES_MAIL_STATE, mail.getState());
 
diff --git a/server/queue/queue-jms/src/main/java/org/apache/james/queue/library/MailQueueManagement.java b/server/queue/queue-jms/src/main/java/org/apache/james/queue/library/MailQueueManagement.java
index 3d32cd6..6b42d6b 100644
--- a/server/queue/queue-jms/src/main/java/org/apache/james/queue/library/MailQueueManagement.java
+++ b/server/queue/queue-jms/src/main/java/org/apache/james/queue/library/MailQueueManagement.java
@@ -18,7 +18,6 @@
  ****************************************************************/
 package org.apache.james.queue.library;
 
-import java.io.Serializable;
 import java.time.ZonedDateTime;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -45,6 +44,8 @@ import org.apache.james.queue.api.ManageableMailQueue.MailQueueIterator;
 import org.apache.james.queue.api.ManageableMailQueue.Type;
 import org.apache.mailet.Mail;
 
+import com.github.steveash.guavate.Guavate;
+
 /**
  * JMX MBean implementation which expose management functions by wrapping a
  * {@link ManageableMailQueue}
@@ -148,17 +149,11 @@ public class MailQueueManagement extends StandardMBean implements MailQueueManag
             map.put(names[6], m.getRemoteAddr());
             map.put(names[7], m.getRemoteHost());
             map.put(names[8], m.getErrorMessage());
-            Map<String, String> attrs = new HashMap<>();
-            Iterator<String> attrNames = m.getAttributeNames();
-            while (attrNames.hasNext()) {
-                String attrName = attrNames.next();
-                String attrValueString = null;
-                Serializable attrValue = m.getAttribute(attrName);
-                if (attrValue != null) {
-                    attrValueString = attrValue.toString();
-                }
-                attrs.put(attrName, attrValueString);
-            }
+            Map<String, String> attrs = m.attributes()
+                .collect(Guavate.toImmutableMap(
+                    attribute -> attribute.getName().asString(),
+                    attribute -> attribute.getValue().value().toString()));
+
             map.put(names[9], attrs.toString());
             map.put(names[10], nextDelivery);
             CompositeDataSupport c = new CompositeDataSupport(new CompositeType(Mail.class.getName(), "Queue Mail", names, descs, types), map);


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


Mime
View raw message