This is an automated email from the ASF dual-hosted git repository.

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

commit 79a7bdcbd25939e2ece5536a63eb618a97bc05d8
Author: Benoit Tellier <btell...@linagora.com>
AuthorDate: Fri Sep 30 08:29:31 2022 +0700

    JAMES-3828 Fix AttributeValue serialization for calendar related mailet
---
 .../transport/mailets/AmqpForwardAttribute.java    |   3 +-
 .../mailets/AmqpForwardAttributeTest.java          |   6 -
 .../java/org/apache/mailet/AttributeValue.java     |   8 +
 .../main/java/org/apache/mailet/Serializer.java    |  38 +++++
 .../transport/mailets/SMIMECheckSignature.java     |   4 +-
 .../james/transport/mailets/SMIMEDecrypt.java      |   6 +-
 .../james/transport/mailets/ICALToHeader.java      |   8 +-
 .../transport/mailets/ICALToJsonAttribute.java     |  31 ++--
 .../james/transport/mailets/ICalendarParser.java   |  12 +-
 .../james/transport/mailets/ICALToHeadersTest.java |  28 ++--
 .../transport/mailets/ICALToJsonAttributeTest.java | 167 ++++++++++-----------
 .../transport/mailets/ICalendarParserTest.java     |  22 +--
 .../mailets/MailAttributesListToMimeHeaders.java   |  14 +-
 .../transport/mailets/MimeDecodingMailet.java      |  16 +-
 .../james/transport/mailets/RecoverAttachment.java |  14 +-
 .../james/transport/mailets/StripAttachment.java   |  12 +-
 .../MailAttributesListToMimeHeadersTest.java       |  45 ++----
 .../transport/mailets/MimeDecodingMailetTest.java  |  13 +-
 .../transport/mailets/StripAttachmentTest.java     |  16 +-
 19 files changed, 240 insertions(+), 223 deletions(-)

diff --git 
a/mailet/amqp/src/main/java/org/apache/james/transport/mailets/AmqpForwardAttribute.java
 
b/mailet/amqp/src/main/java/org/apache/james/transport/mailets/AmqpForwardAttribute.java
index 2cc268eef4..0dd9068a2b 100644
--- 
a/mailet/amqp/src/main/java/org/apache/james/transport/mailets/AmqpForwardAttribute.java
+++ 
b/mailet/amqp/src/main/java/org/apache/james/transport/mailets/AmqpForwardAttribute.java
@@ -228,7 +228,8 @@ public class AmqpForwardAttribute extends GenericMailet {
     @SuppressWarnings("unchecked")
     private Optional<Stream<byte[]>> extractAttributeValueContent(Object 
attributeContent) {
         if (attributeContent instanceof Map) {
-            return Optional.of(((Map<String, byte[]>) 
attributeContent).values().stream());
+            return Optional.of(((Map<String, AttributeValue<byte[]>>) 
attributeContent).values().stream()
+                .map(AttributeValue::getValue));
         }
         if (attributeContent instanceof List) {
             return Optional.of(((List<AttributeValue<byte[]>>) 
attributeContent).stream().map(AttributeValue::value));
diff --git 
a/mailet/amqp/src/test/java/org/apache/james/transport/mailets/AmqpForwardAttributeTest.java
 
b/mailet/amqp/src/test/java/org/apache/james/transport/mailets/AmqpForwardAttributeTest.java
index de6c298f97..959d9fcd7e 100644
--- 
a/mailet/amqp/src/test/java/org/apache/james/transport/mailets/AmqpForwardAttributeTest.java
+++ 
b/mailet/amqp/src/test/java/org/apache/james/transport/mailets/AmqpForwardAttributeTest.java
@@ -26,7 +26,6 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import java.net.URI;
-import java.nio.charset.StandardCharsets;
 import java.util.Optional;
 
 import javax.mail.MessagingException;
@@ -46,17 +45,12 @@ import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.slf4j.Logger;
 
-import com.google.common.collect.ImmutableMap;
-
 class AmqpForwardAttributeTest {
 
     private static final AttributeName MAIL_ATTRIBUTE = 
AttributeName.of("ampq.attachments");
     private static final String EXCHANGE_NAME = "exchangeName";
     private static final String ROUTING_KEY = "routingKey";
     private static final String AMQP_URI = "amqp://host";
-    private static final byte[] ATTACHMENT_CONTENT = "Attachment 
content".getBytes(StandardCharsets.UTF_8);
-    private static final ImmutableMap<String, byte[]> ATTRIBUTE_VALUE = 
ImmutableMap.of("attachment1.txt", ATTACHMENT_CONTENT);
-    private static final Optional<Attribute> ATTRIBUTE_CONTENT = 
Optional.of(new Attribute(MAIL_ATTRIBUTE, 
AttributeValue.ofAny(ATTRIBUTE_VALUE)));
 
     private AmqpForwardAttribute mailet;
     private MailetContext mailetContext;
diff --git a/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java 
b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
index 322ed729af..23f1f597cf 100644
--- a/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
+++ b/mailet/api/src/main/java/org/apache/mailet/AttributeValue.java
@@ -60,6 +60,11 @@ public class AttributeValue<T> {
         return new AttributeValue<>(value, Serializer.STRING_SERIALIZER);
     }
 
+    public static AttributeValue<byte[]> of(byte[] value) {
+        Preconditions.checkNotNull(value, "value should not be null");
+        return new AttributeValue<>(value, Serializer.BYTES_SERIALIZER);
+    }
+
     public static AttributeValue<Integer> of(Integer value) {
         Preconditions.checkNotNull(value, "value should not be null");
         return new AttributeValue<>(value, Serializer.INT_SERIALIZER);
@@ -137,6 +142,9 @@ public class AttributeValue<T> {
         if (value instanceof String) {
             return of((String) value);
         }
+        if (value instanceof byte[]) {
+            return of((byte[]) value);
+        }
         if (value instanceof Integer) {
             return of((Integer) value);
         }
diff --git a/mailet/api/src/main/java/org/apache/mailet/Serializer.java 
b/mailet/api/src/main/java/org/apache/mailet/Serializer.java
index 5ba1c69c74..f9fc2f07d6 100644
--- a/mailet/api/src/main/java/org/apache/mailet/Serializer.java
+++ b/mailet/api/src/main/java/org/apache/mailet/Serializer.java
@@ -27,6 +27,7 @@ import java.io.UncheckedIOException;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.time.ZonedDateTime;
+import java.util.Base64;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -89,6 +90,7 @@ public interface Serializer<T> {
                     DOUBLE_SERIALIZER,
                     DATE_SERIALIZER,
                     MESSAGE_ID_DTO_SERIALIZER,
+                    BYTES_SERIALIZER,
                     new Serializer.ArbitrarySerializableSerializer<>(),
                     URL_SERIALIZER,
                     new CollectionSerializer<>(),
@@ -690,4 +692,40 @@ public interface Serializer<T> {
         }
     }
 
+    Serializer<byte[]> BYTES_SERIALIZER = new BytesSerializer();
+
+    class BytesSerializer implements Serializer<byte[]> {
+
+        @Override
+        public JsonNode serialize(byte[] object) {
+            return 
STRING_SERIALIZER.serialize(Base64.getEncoder().encodeToString(object));
+        }
+
+        @Override
+        public Optional<byte[]> deserialize(JsonNode json) {
+            return 
STRING_SERIALIZER.deserialize(json).map(Base64.getDecoder()::decode);
+        }
+
+        @Override
+        public String getName() {
+            return "BytesSerializer";
+        }
+
+        @Override
+        public byte[] duplicate(byte[] value) {
+            // Assume byte arrays never to be mutated
+            return value;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            return this.getClass() == other.getClass();
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(getClass());
+        }
+    }
+
 }
diff --git 
a/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMECheckSignature.java
 
b/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMECheckSignature.java
index 81450e6041..f487cd97ed 100644
--- 
a/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMECheckSignature.java
+++ 
b/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMECheckSignature.java
@@ -206,12 +206,12 @@ public class SMIMECheckSignature extends GenericMailet {
         // If at least one mail signer is found 
         // the mail attributes are set.
         if (signers != null) {
-            ArrayList<X509Certificate> signerinfolist = new ArrayList<>();
+            ArrayList<AttributeValue<?>> signerinfolist = new ArrayList<>();
 
             for (SMIMESignerInfo info : signers) {
                 if (info.isSignValid()
                         && (!onlyTrusted || info.getCertPath() != null)) {
-                    signerinfolist.add(info.getSignerCertificate());
+                    
signerinfolist.add(AttributeValue.ofSerializable(info.getSignerCertificate()));
                 }
             }
 
diff --git 
a/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMEDecrypt.java
 
b/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMEDecrypt.java
index df1d0fbd0d..b95efdb060 100644
--- 
a/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMEDecrypt.java
+++ 
b/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMEDecrypt.java
@@ -162,9 +162,9 @@ public class SMIMEDecrypt extends GenericMailet {
             // behavior of the SMIMEVerifySignature mailet. In that way
             // it is possible to reuse the same matchers to analyze
             // the result of the operation.
-            ArrayList<X509Certificate> list = new ArrayList<>(1);
-            list.add(keyHolder.getCertificate());
-            mail.setAttribute(new Attribute(mailAttribute, 
AttributeValue.ofAny(list)));
+            ArrayList<AttributeValue<?>> list = new ArrayList<>(1);
+            
list.add(AttributeValue.ofSerializable(keyHolder.getCertificate()));
+            mail.setAttribute(new Attribute(mailAttribute, 
AttributeValue.of(list)));
 
             // I start the message stripping.
             try {
diff --git 
a/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToHeader.java
 
b/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToHeader.java
index 2e4dae272d..2bf0e9e929 100644
--- 
a/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToHeader.java
+++ 
b/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToHeader.java
@@ -26,6 +26,7 @@ import javax.mail.internet.MimeMessage;
 
 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.GenericMailet;
 import org.slf4j.Logger;
@@ -62,7 +63,7 @@ import net.fortuna.ical4j.model.component.VEvent;
 public class ICALToHeader extends GenericMailet {
     private static final Logger LOGGER = 
LoggerFactory.getLogger(ICALToHeader.class);
     @SuppressWarnings("unchecked")
-    private static final Class<Map<String, Calendar>> MAP_STRING_CALENDAR = 
(Class<Map<String, Calendar>>) (Object) Map.class;
+    private static final Class<Map<String, AttributeValue<?>>> 
MAP_STRING_CALENDAR = (Class<Map<String, AttributeValue<?>>>) (Object) 
Map.class;
 
     public static final String ATTRIBUTE_PROPERTY = "attribute";
     public static final String ATTRIBUTE_DEFAULT_NAME = "icalendar";
@@ -105,11 +106,14 @@ public class ICALToHeader extends GenericMailet {
         }
     }
 
-    private void processCalendars(Map<String, Calendar> calendarMap, Mail 
mail) {
+    private void processCalendars(Map<String, AttributeValue<?>> calendarMap, 
Mail mail) {
         calendarMap
             .values()
             .stream()
             .findAny()
+            .map(AttributeValue::getValue)
+            .filter(Calendar.class::isInstance)
+            .map(Calendar.class::cast)
             .ifPresent(Throwing.<Calendar>consumer(calendar -> 
writeToHeaders(calendar, mail))
                     .sneakyThrow());
     }
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 2e6abcceea..c15f514f20 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
@@ -91,9 +91,9 @@ import net.fortuna.ical4j.model.Calendar;
 public class ICALToJsonAttribute extends GenericMailet {
     private static final Logger LOGGER = 
LoggerFactory.getLogger(ICALToJsonAttribute.class);
     @SuppressWarnings("unchecked")
-    private static final Class<Map<String, byte[]>> MAP_STRING_BYTES_CLASS = 
(Class<Map<String, byte[]>>) (Object) Map.class;
+    private static final Class<Map<String, AttributeValue<byte[]>>> 
MAP_STRING_BYTES_CLASS = (Class<Map<String, AttributeValue<byte[]>>>) (Object) 
Map.class;
     @SuppressWarnings("unchecked")
-    private static final Class<Map<String, Calendar>> 
MAP_STRING_CALENDAR_CLASS = (Class<Map<String, Calendar>>) (Object) Map.class;
+    private static final Class<Map<String, AttributeValue<Calendar>>> 
MAP_STRING_CALENDAR_CLASS = (Class<Map<String, AttributeValue<Calendar>>>) 
(Object) Map.class;
 
     public static final String SOURCE_ATTRIBUTE_NAME = "source";
     public static final String RAW_SOURCE_ATTRIBUTE_NAME = "rawSource";
@@ -164,14 +164,14 @@ public class ICALToJsonAttribute extends GenericMailet {
         try {
             AttributeUtils.getValueAndCastFromMail(mail, sourceAttributeName, 
MAP_STRING_CALENDAR_CLASS)
                 .ifPresent(calendars -> 
AttributeUtils.getValueAndCastFromMail(mail, rawSourceAttributeName, 
MAP_STRING_BYTES_CLASS)
-                    .ifPresent(Throwing.<Map<String, 
byte[]>>consumer(rawCalendars ->
+                    .ifPresent(Throwing.<Map<String, 
AttributeValue<byte[]>>>consumer(rawCalendars ->
                         setAttribute(mail, calendars, 
rawCalendars)).sneakyThrow()));
         } catch (ClassCastException e) {
             LOGGER.error("Received a mail with {} not being an ICAL object for 
mail {}", sourceAttributeName, mail.getName(), e);
         }
     }
 
-    private void setAttribute(Mail mail, Map<String, Calendar> calendars, 
Map<String, byte[]> rawCalendars) throws MessagingException {
+    private void setAttribute(Mail mail, Map<String, AttributeValue<Calendar>> 
calendars, Map<String, AttributeValue<byte[]>> rawCalendars) throws 
MessagingException {
         Optional<MailAddress> sender = retrieveSender(mail);
         if (!sender.isPresent()) {
             LOGGER.info("Skipping {} because no sender and no from", 
mail.getName());
@@ -181,11 +181,11 @@ public class ICALToJsonAttribute extends GenericMailet {
         MailAddress transportSender = sender.get();
         MailAddress replyTo = fetchReplyTo(mail).orElse(transportSender);
 
-        Map<String, byte[]> jsonsInByteForm = calendars.entrySet()
+        Map<String, AttributeValue<?>> jsonsInByteForm = calendars.entrySet()
             .stream()
             .flatMap(calendar -> toJson(calendar, rawCalendars, mail, 
transportSender, replyTo))
             .collect(ImmutableMap.toImmutableMap(Pair::getKey, 
Pair::getValue));
-        mail.setAttribute(new Attribute(destinationAttributeName, 
AttributeValue.ofAny(jsonsInByteForm)));
+        mail.setAttribute(new Attribute(destinationAttributeName, 
AttributeValue.of(jsonsInByteForm)));
     }
 
     private Optional<MailAddress> fetchReplyTo(Mail mail) throws 
MessagingException {
@@ -216,8 +216,8 @@ public class ICALToJsonAttribute extends GenericMailet {
         }
     }
 
-    private Stream<Pair<String, byte[]>> toJson(Map.Entry<String, Calendar> 
entry,
-                                                Map<String, byte[]> 
rawCalendars,
+    private Stream<Pair<String, AttributeValue<byte[]>>> 
toJson(Map.Entry<String, AttributeValue<Calendar>> entry,
+                                                Map<String, 
AttributeValue<byte[]>> rawCalendars,
                                                 Mail mail,
                                                 MailAddress sender,
                                                 MailAddress replyTo) {
@@ -225,7 +225,8 @@ public class ICALToJsonAttribute extends GenericMailet {
             .stream()
             .flatMap(recipient -> toICAL(entry, rawCalendars, recipient, 
sender, replyTo))
             .flatMap(ical -> toJson(ical, mail.getName()))
-            .map(json -> Pair.of(UUID.randomUUID().toString(), 
json.getBytes(StandardCharsets.UTF_8)));
+            .map(json -> Pair.of(UUID.randomUUID().toString(),
+                AttributeValue.of(json.getBytes(StandardCharsets.UTF_8))));
     }
 
     private Stream<String> toJson(ICALAttributeDTO ical, String mailName) {
@@ -240,20 +241,20 @@ public class ICALToJsonAttribute extends GenericMailet {
         }
     }
 
-    private Stream<ICALAttributeDTO> toICAL(Map.Entry<String, Calendar> entry,
-                                            Map<String, byte[]> rawCalendars,
+    private Stream<ICALAttributeDTO> toICAL(Map.Entry<String, 
AttributeValue<Calendar>> entry,
+                                            Map<String, 
AttributeValue<byte[]>> rawCalendars,
                                             MailAddress recipient,
                                             MailAddress sender,
                                             MailAddress replyTo) {
-        Calendar calendar = entry.getValue();
-        byte[] rawICal = rawCalendars.get(entry.getKey());
-        if (rawICal == null) {
+        Calendar calendar = entry.getValue().getValue();
+        Optional<byte[]> rawICal = 
Optional.ofNullable(rawCalendars.get(entry.getKey())).map(AttributeValue::getValue);
+        if (!rawICal.isPresent()) {
             LOGGER.debug("Cannot find matching raw ICAL from key: {}", 
entry.getKey());
             return Stream.of();
         }
         try {
             return Stream.of(ICALAttributeDTO.builder()
-                .from(calendar, rawICal)
+                .from(calendar, rawICal.get())
                 .sender(sender)
                 .recipient(recipient)
                 .replyTo(replyTo));
diff --git 
a/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICalendarParser.java
 
b/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICalendarParser.java
index 0d7a617623..843ef862aa 100644
--- 
a/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICalendarParser.java
+++ 
b/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICalendarParser.java
@@ -69,7 +69,7 @@ import net.fortuna.ical4j.model.Calendar;
 public class ICalendarParser extends GenericMailet {
     private static final Logger LOGGER = 
LoggerFactory.getLogger(ICalendarParser.class);
     @SuppressWarnings("unchecked")
-    private static final Class<Map<String, byte[]>> MAP_STRING_BYTES_CLASS = 
(Class<Map<String, byte[]>>) (Object) Map.class;
+    private static final Class<Map<String, AttributeValue<byte[]>>> 
MAP_STRING_BYTES_CLASS = (Class<Map<String, AttributeValue<byte[]>>>) (Object) 
Map.class;
 
     public static final String SOURCE_ATTRIBUTE_PARAMETER_NAME = 
"sourceAttribute";
     public static final String DESTINATION_ATTRIBUTE_PARAMETER_NAME = 
"destinationAttribute";
@@ -116,13 +116,13 @@ public class ICalendarParser extends GenericMailet {
             .ifPresent(icsAttachments -> addCalendarsToAttribute(mail, 
icsAttachments));
     }
 
-    private void addCalendarsToAttribute(Mail mail, Map<String, byte[]> 
icsAttachments) {
-        Map<String, Calendar> calendars = icsAttachments.entrySet()
+    private void addCalendarsToAttribute(Mail mail, Map<String, 
AttributeValue<byte[]>> icsAttachments) {
+        Map<String, AttributeValue<?>> calendars = icsAttachments.entrySet()
             .stream()
-            .flatMap(entry -> createCalendar(entry.getKey(), entry.getValue()))
-            .collect(ImmutableMap.toImmutableMap(Pair::getKey, 
Pair::getValue));
+            .flatMap(entry -> createCalendar(entry.getKey(), 
entry.getValue().getValue()))
+            .collect(ImmutableMap.toImmutableMap(Pair::getKey, pair -> 
AttributeValue.ofSerializable(pair.getValue())));
 
-        mail.setAttribute(new Attribute(destinationAttributeName, 
AttributeValue.ofAny(calendars)));
+        mail.setAttribute(new Attribute(destinationAttributeName, 
AttributeValue.of(calendars)));
     }
 
     @Override
diff --git 
a/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToHeadersTest.java
 
b/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToHeadersTest.java
index 04618de18e..93d04de746 100644
--- 
a/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToHeadersTest.java
+++ 
b/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToHeadersTest.java
@@ -22,6 +22,8 @@ package org.apache.james.transport.mailets;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
+import java.util.Map;
+
 import javax.mail.MessagingException;
 
 import org.apache.james.util.MimeMessageUtil;
@@ -102,7 +104,7 @@ class ICALToHeadersTest {
         Mail mail = FakeMail.builder()
             .name("mail")
             .mimeMessage(MimeMessageUtil.defaultMimeMessage())
-            .attribute(makeAttribute("This is the wrong type"))
+            .attribute(new Attribute(ICALToHeader.ATTRIBUTE_DEFAULT, 
AttributeValue.of("This is the wrong type")))
             .build();
 
         testee.service(mail);
@@ -112,8 +114,8 @@ class ICALToHeadersTest {
 
     @Test
     void serviceShouldNotFailOnMailsWithWrongParametrizedAttribute() throws 
Exception {
-        ImmutableMap<String, String> wrongParametrizedMap = 
ImmutableMap.<String, String>builder()
-            .put("key", "value")
+        ImmutableMap<String, AttributeValue<?>> wrongParametrizedMap = 
ImmutableMap.<String, AttributeValue<?>>builder()
+            .put("key", AttributeValue.of("value"))
             .build();
 
         testee.init(FakeMailetConfig.builder().build());
@@ -131,8 +133,8 @@ class ICALToHeadersTest {
     @Test
     void serviceShouldWriteSingleICalendarToHeaders() throws Exception {
         Calendar calendar = new 
CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting.ics"));
-        ImmutableMap<String, Calendar> icals = ImmutableMap.<String, 
Calendar>builder()
-            .put("key", calendar)
+        Map<String, AttributeValue<?>> icals = ImmutableMap.<String, 
AttributeValue<?>>builder()
+            .put("key", AttributeValue.ofSerializable(calendar))
             .build();
 
         testee.init(FakeMailetConfig.builder().build());
@@ -158,8 +160,8 @@ class ICALToHeadersTest {
     @Test
     void serviceShouldNotWriteHeaderWhenPropertyIsAbsent() throws Exception {
         Calendar calendar = new 
CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting_without_dtstamp.ics"));
-        ImmutableMap<String, Calendar> icals = ImmutableMap.<String, 
Calendar>builder()
-            .put("key", calendar)
+        Map<String, AttributeValue<?>> icals = ImmutableMap.<String, 
AttributeValue<?>>builder()
+            .put("key", AttributeValue.ofSerializable(calendar))
             .build();
 
         testee.init(FakeMailetConfig.builder().build());
@@ -185,9 +187,9 @@ class ICALToHeadersTest {
     void serviceShouldWriteOnlyOneICalendarToHeaders() throws Exception {
         Calendar calendar = new 
CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting.ics"));
         Calendar calendar2 = new 
CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting_2.ics"));
-        ImmutableMap<String, Calendar> icals = ImmutableMap.<String, 
Calendar>builder()
-            .put("key", calendar)
-            .put("key2", calendar2)
+        Map<String, AttributeValue<?>> icals = ImmutableMap.<String, 
AttributeValue<?>>builder()
+            .put("key", AttributeValue.ofSerializable(calendar))
+            .put("key2", AttributeValue.ofSerializable(calendar2))
             .build();
 
         testee.init(FakeMailetConfig.builder().build());
@@ -204,7 +206,7 @@ class ICALToHeadersTest {
 
     @Test
     void serviceShouldNotFailOnEmptyMaps() throws Exception {
-        ImmutableMap<String, Calendar> icals = ImmutableMap.<String, 
Calendar>builder()
+        Map<String, AttributeValue<?>> icals = ImmutableMap.<String, 
AttributeValue<?>>builder()
             .build();
 
         testee.init(FakeMailetConfig.builder().build());
@@ -219,7 +221,7 @@ class ICALToHeadersTest {
         
assertThat(mail.getMessage().getHeader(ICALToHeader.X_MEETING_UID_HEADER)).isNull();
     }
 
-    private Attribute makeAttribute(Object icals) {
-        return new Attribute(ICALToHeader.ATTRIBUTE_DEFAULT, 
AttributeValue.ofAny(icals));
+    private Attribute makeAttribute(Map<String, AttributeValue<?>> icals) {
+        return new Attribute(ICALToHeader.ATTRIBUTE_DEFAULT, 
AttributeValue.of(icals));
     }
 }
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 3fbb171dea..1cea0b75cb 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
@@ -24,6 +24,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import java.io.ByteArrayInputStream;
+import java.io.Serializable;
 import java.nio.charset.StandardCharsets;
 import java.util.List;
 import java.util.Map;
@@ -53,12 +54,11 @@ import com.fasterxml.jackson.core.io.JsonStringEncoder;
 import com.google.common.collect.ImmutableMap;
 
 import net.fortuna.ical4j.data.CalendarBuilder;
-import net.fortuna.ical4j.model.Calendar;
 
 public class ICALToJsonAttributeTest {
     private static final MailAddress SENDER = MailAddressFixture.ANY_AT_JAMES;
     @SuppressWarnings("unchecked")
-    private static final Class<Map<String, byte[]>> MAP_STRING_BYTES_CLASS = 
(Class<Map<String, byte[]>>) (Object) Map.class;
+    private static final Class<Map<String, AttributeValue<byte[]>>> 
MAP_STRING_BYTES_CLASS = (Class<Map<String, AttributeValue<byte[]>>>) (Object) 
Map.class;
 
     private ICALToJsonAttribute testee;
 
@@ -171,7 +171,7 @@ public class ICALToJsonAttributeTest {
     void serviceShouldNotFailOnWrongAttributeParameter() throws Exception {
         testee.init(FakeMailetConfig.builder().build());
 
-        ImmutableMap<String, String> wrongParametrizedMap = 
ImmutableMap.of("key", "value");
+        ImmutableMap<String, AttributeValue<String>> wrongParametrizedMap = 
ImmutableMap.of("key", AttributeValue.of("value"));
         Mail mail = FakeMail.builder()
             .name("mail")
             .sender(SENDER)
@@ -188,7 +188,7 @@ public class ICALToJsonAttributeTest {
     void serviceShouldNotFailOnWrongRawAttributeParameter() throws Exception {
         testee.init(FakeMailetConfig.builder().build());
 
-        ImmutableMap<String, String> wrongParametrizedMap = 
ImmutableMap.of("key", "value");
+        ImmutableMap<String, AttributeValue<String>> wrongParametrizedMap = 
ImmutableMap.of("key", AttributeValue.of("value"));
         Mail mail = FakeMail.builder()
             .name("mail")
             .sender(SENDER)
@@ -205,9 +205,10 @@ public class ICALToJsonAttributeTest {
     void serviceShouldFilterMailsWithoutSender() throws Exception {
         testee.init(FakeMailetConfig.builder().build());
 
-        byte[] ics = 
ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics");
-        Calendar calendar = new CalendarBuilder().build(new 
ByteArrayInputStream(ics));
-        ImmutableMap<String, Calendar> icals = ImmutableMap.of("key", 
calendar);
+        AttributeValue<byte[]> ics = 
AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics"));
+        AttributeValue<Serializable> calendar = 
AttributeValue.ofSerializable(new CalendarBuilder().build(new 
ByteArrayInputStream(ics.getValue())));
+        Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", 
calendar);
+        Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics);
         Mail mail = FakeMail.builder()
             .name("mail")
             .recipient(MailAddressFixture.OTHER_AT_JAMES)
@@ -225,10 +226,10 @@ public class ICALToJsonAttributeTest {
     void serviceShouldAttachEmptyListWhenNoRecipient() throws Exception {
         testee.init(FakeMailetConfig.builder().build());
 
-        byte[] ics = 
ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics");
-        Calendar calendar = new CalendarBuilder().build(new 
ByteArrayInputStream(ics));
-        ImmutableMap<String, Calendar> icals = ImmutableMap.of("key", 
calendar);
-        ImmutableMap<String, byte[]> rawIcals = ImmutableMap.of("key", ics);
+        AttributeValue<byte[]> ics = 
AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics"));
+        AttributeValue<Serializable> calendar = 
AttributeValue.ofSerializable(new CalendarBuilder().build(new 
ByteArrayInputStream(ics.getValue())));
+        Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", 
calendar);
+        Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics);
         Mail mail = FakeMail.builder()
             .name("mail")
             .sender(SENDER)
@@ -246,10 +247,10 @@ public class ICALToJsonAttributeTest {
     void serviceShouldAttachJson() throws Exception {
         testee.init(FakeMailetConfig.builder().build());
 
-        byte[] ics = 
ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics");
-        Calendar calendar = new CalendarBuilder().build(new 
ByteArrayInputStream(ics));
-        ImmutableMap<String, Calendar> icals = ImmutableMap.of("key", 
calendar);
-        ImmutableMap<String, byte[]> rawIcals = ImmutableMap.of("key", ics);
+        AttributeValue<byte[]> ics = 
AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics"));
+        AttributeValue<Serializable> calendar = 
AttributeValue.ofSerializable(new CalendarBuilder().build(new 
ByteArrayInputStream(ics.getValue())));
+        Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", 
calendar);
+        Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics);
         MailAddress recipient = MailAddressFixture.ANY_AT_JAMES2;
         Mail mail = FakeMail.builder()
             .name("mail")
@@ -264,9 +265,9 @@ public class ICALToJsonAttributeTest {
             .isPresent()
             .hasValueSatisfying(jsons -> {
                 assertThat(jsons).hasSize(1);
-                assertThatJson(new String(jsons.values().iterator().next(), 
StandardCharsets.UTF_8))
+                assertThatJson(new 
String(jsons.values().iterator().next().getValue(), StandardCharsets.UTF_8))
                     .isEqualTo("{" +
-                        "\"ical\": \"" + toJsonValue(ics) + "\"," +
+                        "\"ical\": \"" + toJsonValue(ics.getValue()) + "\"," +
                         "\"sender\": \"" + SENDER.asString() + "\"," +
                         "\"replyTo\": \"" + SENDER.asString() + "\"," +
                         "\"recipient\": \"" + recipient.asString() + "\"," +
@@ -288,10 +289,10 @@ public class ICALToJsonAttributeTest {
     void serviceShouldAttachJsonWithTheReplyToAttributeValueWhenPresent(String 
replyToHeader) throws Exception {
         testee.init(FakeMailetConfig.builder().build());
 
-        byte[] ics = 
ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics");
-        Calendar calendar = new CalendarBuilder().build(new 
ByteArrayInputStream(ics));
-        ImmutableMap<String, Calendar> icals = ImmutableMap.of("key", 
calendar);
-        ImmutableMap<String, byte[]> rawIcals = ImmutableMap.of("key", ics);
+        AttributeValue<byte[]> ics = 
AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics"));
+        AttributeValue<Serializable> calendar = 
AttributeValue.ofSerializable(new CalendarBuilder().build(new 
ByteArrayInputStream(ics.getValue())));
+        Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", 
calendar);
+        Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics);
         MailAddress recipient = MailAddressFixture.ANY_AT_JAMES2;
         MailAddress replyTo = MailAddressFixture.OTHER_AT_JAMES;
         Mail mail = FakeMail.builder()
@@ -309,9 +310,9 @@ public class ICALToJsonAttributeTest {
             .isPresent()
             .hasValueSatisfying(jsons -> {
                 assertThat(jsons).hasSize(1);
-                assertThatJson(new String(jsons.values().iterator().next(), 
StandardCharsets.UTF_8))
+                assertThatJson(new 
String(jsons.values().iterator().next().getValue(), StandardCharsets.UTF_8))
                     .isEqualTo("{" +
-                        "\"ical\": \"" + toJsonValue(ics) + "\"," +
+                        "\"ical\": \"" + toJsonValue(ics.getValue()) + "\"," +
                         "\"sender\": \"" + SENDER.asString() + "\"," +
                         "\"replyTo\": \"" + replyTo.asString() + "\"," +
                         "\"recipient\": \"" + recipient.asString() + "\"," +
@@ -339,10 +340,10 @@ public class ICALToJsonAttributeTest {
     void 
serviceShouldAttachJsonWithTheSenderAsReplyToAttributeValueWhenReplyToIsInvalid()
 throws Exception {
         testee.init(FakeMailetConfig.builder().build());
 
-        byte[] ics = 
ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics");
-        Calendar calendar = new CalendarBuilder().build(new 
ByteArrayInputStream(ics));
-        ImmutableMap<String, Calendar> icals = ImmutableMap.of("key", 
calendar);
-        ImmutableMap<String, byte[]> rawIcals = ImmutableMap.of("key", ics);
+        AttributeValue<byte[]> ics = 
AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics"));
+        AttributeValue<Serializable> calendar = 
AttributeValue.ofSerializable(new CalendarBuilder().build(new 
ByteArrayInputStream(ics.getValue())));
+        Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", 
calendar);
+        Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics);
         MailAddress recipient = MailAddressFixture.ANY_AT_JAMES2;
         Mail mail = FakeMail.builder()
             .name("mail")
@@ -359,9 +360,9 @@ public class ICALToJsonAttributeTest {
             .isPresent()
             .hasValueSatisfying(jsons -> {
                 assertThat(jsons).hasSize(1);
-                assertThatJson(new String(jsons.values().iterator().next(), 
StandardCharsets.UTF_8))
+                assertThatJson(new 
String(jsons.values().iterator().next().getValue(), StandardCharsets.UTF_8))
                     .isEqualTo("{" +
-                        "\"ical\": \"" + toJsonValue(ics) + "\"," +
+                        "\"ical\": \"" + toJsonValue(ics.getValue()) + "\"," +
                         "\"sender\": \"" + SENDER.asString() + "\"," +
                         "\"replyTo\": \"" + SENDER.asString() + "\"," +
                         "\"recipient\": \"" + recipient.asString() + "\"," +
@@ -377,11 +378,10 @@ public class ICALToJsonAttributeTest {
     @Test
     void serviceShouldAttachJsonForSeveralRecipient() throws Exception {
         testee.init(FakeMailetConfig.builder().build());
-
-        byte[] ics = 
ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics");
-        Calendar calendar = new CalendarBuilder().build(new 
ByteArrayInputStream(ics));
-        ImmutableMap<String, Calendar> icals = ImmutableMap.of("key", 
calendar);
-        ImmutableMap<String, byte[]> rawIcals = ImmutableMap.of("key", ics);
+        AttributeValue<byte[]> ics = 
AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics"));
+        AttributeValue<Serializable> calendar = 
AttributeValue.ofSerializable(new CalendarBuilder().build(new 
ByteArrayInputStream(ics.getValue())));
+        Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", 
calendar);
+        Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics);
         Mail mail = FakeMail.builder()
             .name("mail")
             .sender(SENDER)
@@ -398,7 +398,7 @@ public class ICALToJsonAttributeTest {
                     List<String> actual = toSortedValueList(jsons);
 
                     assertThatJson(actual.get(0)).isEqualTo("{" +
-                        "\"ical\": \"" + toJsonValue(ics) + "\"," +
+                        "\"ical\": \"" + toJsonValue(ics.getValue()) + "\"," +
                         "\"sender\": \"" + SENDER.asString() + "\"," +
                         "\"recipient\": \"" + 
MailAddressFixture.ANY_AT_JAMES2.asString() + "\"," +
                         "\"replyTo\": \"" + SENDER.asString() + "\"," +
@@ -408,17 +408,6 @@ public class ICALToJsonAttributeTest {
                         "\"method\": \"REQUEST\"," +
                         "\"recurrence-id\": null" +
                         "}");
-                    assertThatJson(actual.get(1)).isEqualTo("{" +
-                        "\"ical\": \"" + toJsonValue(ics) + "\"," +
-                        "\"sender\": \"" + SENDER.asString() + "\"," +
-                        "\"recipient\": \"" + 
MailAddressFixture.OTHER_AT_JAMES.asString() + "\"," +
-                        "\"replyTo\": \"" + SENDER.asString() + "\"," +
-                        "\"uid\": 
\"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\","
 +
-                        "\"sequence\": \"0\"," +
-                        "\"dtstamp\": \"20170106T115036Z\"," +
-                        "\"method\": \"REQUEST\"," +
-                        "\"recurrence-id\": null" +
-                        "}");
                 });
     }
 
@@ -426,12 +415,12 @@ public class ICALToJsonAttributeTest {
     void serviceShouldAttachJsonForSeveralICALs() throws Exception {
         testee.init(FakeMailetConfig.builder().build());
 
-        byte[] ics = 
ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics");
-        byte[] ics2 = 
ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting_2.ics");
-        Calendar calendar = new CalendarBuilder().build(new 
ByteArrayInputStream(ics));
-        Calendar calendar2 = new CalendarBuilder().build(new 
ByteArrayInputStream(ics2));
-        ImmutableMap<String, Calendar> icals = ImmutableMap.of("key", 
calendar, "key2", calendar2);
-        ImmutableMap<String, byte[]> rawIcals = ImmutableMap.of("key", ics, 
"key2", ics2);
+        AttributeValue<byte[]> ics = 
AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics"));
+        AttributeValue<byte[]> ics2 = 
AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting_2.ics"));
+        AttributeValue<Serializable> calendar = 
AttributeValue.ofSerializable(new CalendarBuilder().build(new 
ByteArrayInputStream(ics.getValue())));
+        AttributeValue<Serializable> calendar2 = 
AttributeValue.ofSerializable(new CalendarBuilder().build(new 
ByteArrayInputStream(ics2.getValue())));
+        Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", 
calendar, "key2", calendar2);
+        Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics, 
"key2", ics2);
         MailAddress recipient = MailAddressFixture.OTHER_AT_JAMES;
         Mail mail = FakeMail.builder()
             .name("mail")
@@ -449,7 +438,7 @@ public class ICALToJsonAttributeTest {
                     List<String> actual = toSortedValueList(jsons);
 
                     assertThatJson(actual.get(0)).isEqualTo("{" +
-                        "\"ical\": \"" + toJsonValue(ics2) + "\"," +
+                        "\"ical\": \"" + toJsonValue(ics2.getValue()) + "\"," +
                         "\"sender\": \"" + SENDER.asString() + "\"," +
                         "\"recipient\": \"" + recipient.asString() + "\"," +
                         "\"replyTo\": \"" + SENDER.asString() + "\"," +
@@ -460,7 +449,7 @@ public class ICALToJsonAttributeTest {
                         "\"recurrence-id\": null" +
                         "}");
                     assertThatJson(actual.get(1)).isEqualTo("{" +
-                        "\"ical\": \"" + toJsonValue(ics) + "\"," +
+                        "\"ical\": \"" + toJsonValue(ics.getValue()) + "\"," +
                         "\"sender\": \"" + SENDER.asString() + "\"," +
                         "\"recipient\": \"" + recipient.asString() + "\"," +
                         "\"replyTo\": \"" + SENDER.asString() + "\"," +
@@ -477,18 +466,18 @@ public class ICALToJsonAttributeTest {
     void serviceShouldFilterInvalidICS() throws Exception {
         testee.init(FakeMailetConfig.builder().build());
 
-        byte[] ics = 
ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics");
-        byte[] ics2 = 
ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting_without_uid.ics");
-        Calendar calendar = new CalendarBuilder().build(new 
ByteArrayInputStream(ics));
-        Calendar calendar2 = new CalendarBuilder().build(new 
ByteArrayInputStream(ics2));
-        ImmutableMap<String, Calendar> icals = ImmutableMap.of("key", 
calendar, "key2", calendar2);
-        ImmutableMap<String, byte[]> rawIcals = ImmutableMap.of("key", ics, 
"key2", ics2);
+        AttributeValue<byte[]> ics = 
AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics"));
+        AttributeValue<byte[]> ics2 = 
AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting_without_uid.ics"));
+        AttributeValue<Serializable> calendar = 
AttributeValue.ofSerializable(new CalendarBuilder().build(new 
ByteArrayInputStream(ics.getValue())));
+        AttributeValue<Serializable> calendar2 = 
AttributeValue.ofSerializable(new CalendarBuilder().build(new 
ByteArrayInputStream(ics2.getValue())));
+        Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", 
calendar, "key2", calendar2);
+        Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics, 
"key2", ics2);
         MailAddress recipient = MailAddressFixture.OTHER_AT_JAMES;
         Mail mail = FakeMail.builder()
             .name("mail")
             .sender(SENDER)
             .recipient(recipient)
-            .attribute(new Attribute(ICALToJsonAttribute.DEFAULT_SOURCE, 
AttributeValue.ofAny(icals)))
+            .attribute(new Attribute(ICALToJsonAttribute.DEFAULT_SOURCE, 
AttributeValue.of(icals)))
             .attribute(new Attribute(ICALToJsonAttribute.DEFAULT_RAW_SOURCE, 
AttributeValue.ofAny(rawIcals)))
             .build();
         testee.service(mail);
@@ -500,7 +489,7 @@ public class ICALToJsonAttributeTest {
                     List<String> actual = toSortedValueList(jsons);
 
                     assertThatJson(actual.get(0)).isEqualTo("{" +
-                        "\"ical\": \"" + toJsonValue(ics) + "\"," +
+                        "\"ical\": \"" + toJsonValue(ics.getValue()) + "\"," +
                         "\"sender\": \"" + SENDER.asString() + "\"," +
                         "\"recipient\": \"" + recipient.asString() + "\"," +
                         "\"replyTo\": \"" + SENDER.asString() + "\"," +
@@ -517,12 +506,12 @@ public class ICALToJsonAttributeTest {
     void serviceShouldFilterNonExistingKeys() throws Exception {
         testee.init(FakeMailetConfig.builder().build());
 
-        byte[] ics = 
ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics");
-        byte[] ics2 = 
ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting_2.ics");
-        Calendar calendar = new CalendarBuilder().build(new 
ByteArrayInputStream(ics));
-        Calendar calendar2 = new CalendarBuilder().build(new 
ByteArrayInputStream(ics2));
-        ImmutableMap<String, Calendar> icals = ImmutableMap.of("key", 
calendar, "key2", calendar2);
-        ImmutableMap<String, byte[]> rawIcals = ImmutableMap.of("key", ics);
+        AttributeValue<byte[]> ics = 
AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics"));
+        AttributeValue<byte[]> ics2 = 
AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting_2.ics"));
+        AttributeValue<Serializable> calendar = 
AttributeValue.ofSerializable(new CalendarBuilder().build(new 
ByteArrayInputStream(ics.getValue())));
+        AttributeValue<Serializable> calendar2 = 
AttributeValue.ofSerializable(new CalendarBuilder().build(new 
ByteArrayInputStream(ics2.getValue())));
+        Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", 
calendar, "key2", calendar2);
+        Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics);
         MailAddress recipient = MailAddressFixture.OTHER_AT_JAMES;
         Mail mail = FakeMail.builder()
             .name("mail")
@@ -540,7 +529,7 @@ public class ICALToJsonAttributeTest {
                     List<String> actual = toSortedValueList(jsons);
 
                     assertThatJson(actual.get(0)).isEqualTo("{" +
-                        "\"ical\": \"" + toJsonValue(ics) + "\"," +
+                        "\"ical\": \"" + toJsonValue(ics.getValue()) + "\"," +
                         "\"sender\": \"" + SENDER.asString() + "\"," +
                         "\"replyTo\": \"" + SENDER.asString() + "\"," +
                         "\"recipient\": \"" + recipient.asString() + "\"," +
@@ -557,10 +546,10 @@ public class ICALToJsonAttributeTest {
     void serviceShouldUseFromWhenSpecified() throws Exception {
         testee.init(FakeMailetConfig.builder().build());
 
-        byte[] ics = 
ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics");
-        Calendar calendar = new CalendarBuilder().build(new 
ByteArrayInputStream(ics));
-        ImmutableMap<String, Calendar> icals = ImmutableMap.of("key", 
calendar);
-        ImmutableMap<String, byte[]> rawIcals = ImmutableMap.of("key", ics);
+        AttributeValue<byte[]> ics = 
AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics"));
+        AttributeValue<Serializable> calendar = 
AttributeValue.ofSerializable(new CalendarBuilder().build(new 
ByteArrayInputStream(ics.getValue())));
+        Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", 
calendar);
+        Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics);
         MailAddress recipient = MailAddressFixture.ANY_AT_JAMES2;
         String from = MailAddressFixture.OTHER_AT_JAMES.asString();
         Mail mail = FakeMail.builder()
@@ -578,9 +567,9 @@ public class ICALToJsonAttributeTest {
                 .isPresent()
                 .hasValueSatisfying(jsons -> {
                     assertThat(jsons).hasSize(1);
-                    assertThatJson(new 
String(jsons.values().iterator().next(), StandardCharsets.UTF_8))
+                    assertThatJson(new 
String(jsons.values().iterator().next().getValue(), StandardCharsets.UTF_8))
                         .isEqualTo("{" +
-                            "\"ical\": \"" + toJsonValue(ics) + "\"," +
+                            "\"ical\": \"" + toJsonValue(ics.getValue()) + 
"\"," +
                             "\"sender\": \"" + from + "\"," +
                             "\"recipient\": \"" + recipient.asString() + "\"," 
+
                             "\"replyTo\": \"" + from + "\"," +
@@ -597,10 +586,10 @@ public class ICALToJsonAttributeTest {
     void serviceShouldSupportMimeMessagesWithoutFromFields() throws Exception {
         testee.init(FakeMailetConfig.builder().build());
 
-        byte[] ics = 
ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics");
-        Calendar calendar = new CalendarBuilder().build(new 
ByteArrayInputStream(ics));
-        ImmutableMap<String, Calendar> icals = ImmutableMap.of("key", 
calendar);
-        ImmutableMap<String, byte[]> rawIcals = ImmutableMap.of("key", ics);
+        AttributeValue<byte[]> ics = 
AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics"));
+        AttributeValue<Serializable> calendar = 
AttributeValue.ofSerializable(new CalendarBuilder().build(new 
ByteArrayInputStream(ics.getValue())));
+        Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", 
calendar);
+        Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics);
         MailAddress recipient = MailAddressFixture.ANY_AT_JAMES2;
         Mail mail = FakeMail.builder()
             .name("mail")
@@ -616,9 +605,9 @@ public class ICALToJsonAttributeTest {
                 .isPresent()
                 .hasValueSatisfying(jsons -> {
                     assertThat(jsons).hasSize(1);
-                    assertThatJson(new 
String(jsons.values().iterator().next(), StandardCharsets.UTF_8))
+                    assertThatJson(new 
String(jsons.values().iterator().next().getValue(), StandardCharsets.UTF_8))
                         .isEqualTo("{" +
-                            "\"ical\": \"" + toJsonValue(ics) + "\"," +
+                            "\"ical\": \"" + toJsonValue(ics.getValue()) + 
"\"," +
                             "\"sender\": \"" + SENDER.asString() + "\"," +
                             "\"recipient\": \"" + recipient.asString() + "\"," 
+
                             "\"replyTo\": \"" + SENDER.asString() + "\"," +
@@ -635,10 +624,10 @@ public class ICALToJsonAttributeTest {
     void serviceShouldUseFromWhenSpecifiedAndNoSender() throws Exception {
         testee.init(FakeMailetConfig.builder().build());
 
-        byte[] ics = 
ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics");
-        Calendar calendar = new CalendarBuilder().build(new 
ByteArrayInputStream(ics));
-        ImmutableMap<String, Calendar> icals = ImmutableMap.of("key", 
calendar);
-        ImmutableMap<String, byte[]> rawIcals = ImmutableMap.of("key", ics);
+        AttributeValue<byte[]> ics = 
AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/meeting.ics"));
+        AttributeValue<Serializable> calendar = 
AttributeValue.ofSerializable(new CalendarBuilder().build(new 
ByteArrayInputStream(ics.getValue())));
+        Map<String, AttributeValue<?>> icals = ImmutableMap.of("key", 
calendar);
+        Map<String, AttributeValue<?>> rawIcals = ImmutableMap.of("key", ics);
         MailAddress recipient = MailAddressFixture.ANY_AT_JAMES2;
         String from = MailAddressFixture.OTHER_AT_JAMES.asString();
         Mail mail = FakeMail.builder()
@@ -655,9 +644,9 @@ public class ICALToJsonAttributeTest {
                 .isPresent()
                 .hasValueSatisfying(jsons -> {
                     assertThat(jsons).hasSize(1);
-                    assertThatJson(new 
String(jsons.values().iterator().next(), StandardCharsets.UTF_8))
+                    assertThatJson(new 
String(jsons.values().iterator().next().getValue(), StandardCharsets.UTF_8))
                         .isEqualTo("{" +
-                            "\"ical\": \"" + toJsonValue(ics) + "\"," +
+                            "\"ical\": \"" + toJsonValue(ics.getValue()) + 
"\"," +
                             "\"sender\": \"" + from + "\"," +
                             "\"recipient\": \"" + recipient.asString() + "\"," 
+
                             "\"replyTo\": \"" + from + "\"," +
@@ -670,10 +659,10 @@ public class ICALToJsonAttributeTest {
                 });
     }
 
-    private List<String> toSortedValueList(Map<String, byte[]> jsons) {
+    private List<String> toSortedValueList(Map<String, AttributeValue<byte[]>> 
jsons) {
         return jsons.values()
                 .stream()
-                .map(bytes -> new String(bytes, StandardCharsets.UTF_8))
+                .map(bytes -> new String(bytes.getValue(), 
StandardCharsets.UTF_8))
                 .sorted()
                 .collect(Collectors.toList());
     }
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 1718d892f0..88ea0f2ebf 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
@@ -56,7 +56,7 @@ class ICalendarParserTest {
 
     static final String WRONG_ICAL_VALUE = "anyValue";
     @SuppressWarnings("unchecked")
-    static final Class<Map<String, Calendar>> MAP_STRING_CALENDAR_CLASS = 
(Class<Map<String, Calendar>>) (Object) Map.class;
+    static final Class<Map<String, AttributeValue<Serializable>>> 
MAP_STRING_CALENDAR_CLASS = (Class<Map<String, AttributeValue<Serializable>>>) 
(Object) Map.class;
 
     ICalendarParser mailet = new ICalendarParser();
 
@@ -189,8 +189,8 @@ class ICalendarParserTest {
 
         mailet.init(mailetConfiguration);
 
-        Map<String, byte[]> attachments = ImmutableMap.<String, 
byte[]>builder()
-            .put("key", RIGHT_ICAL_VALUE.getBytes())
+        Map<String, AttributeValue<byte[]>> attachments = 
ImmutableMap.<String, AttributeValue<byte[]>>builder()
+            .put("key", AttributeValue.of(RIGHT_ICAL_VALUE.getBytes()))
             .build();
 
         Mail mail = FakeMail.builder()
@@ -218,9 +218,9 @@ class ICalendarParserTest {
 
         mailet.init(mailetConfiguration);
 
-        Map<String, byte[]> attachments = ImmutableMap.<String, 
byte[]>builder()
-            .put("key1", WRONG_ICAL_VALUE.getBytes())
-            .put("key2", RIGHT_ICAL_VALUE.getBytes())
+        Map<String, AttributeValue<byte[]>> attachments = 
ImmutableMap.<String, AttributeValue<byte[]>>builder()
+            .put("key1", AttributeValue.of(WRONG_ICAL_VALUE.getBytes()))
+            .put("key2", AttributeValue.of(RIGHT_ICAL_VALUE.getBytes()))
             .build();
         Mail mail = FakeMail.builder()
             .name("mail")
@@ -229,8 +229,8 @@ class ICalendarParserTest {
 
         mailet.service(mail);
 
-        Optional<Map<String, Calendar>> expectedCalendars = 
AttributeUtils.getValueAndCastFromMail(mail, DESTINATION_CUSTOM_ATTRIBUTE_NAME, 
MAP_STRING_CALENDAR_CLASS);
-        Map.Entry<String, Calendar> expectedCalendar = 
Maps.immutableEntry("key2", new Calendar());
+        Optional<Map<String, AttributeValue<Serializable>>> expectedCalendars 
= AttributeUtils.getValueAndCastFromMail(mail, 
DESTINATION_CUSTOM_ATTRIBUTE_NAME, MAP_STRING_CALENDAR_CLASS);
+        Map.Entry<String, AttributeValue<Serializable>> expectedCalendar = 
Maps.immutableEntry("key2", AttributeValue.ofSerializable(new Calendar()));
 
         assertThat(expectedCalendars).hasValueSatisfying(calendars ->
             assertThat(calendars)
@@ -253,8 +253,8 @@ class ICalendarParserTest {
 
         mailet.init(mailetConfiguration);
 
-        Map<String, byte[]> attachments = ImmutableMap.<String, 
byte[]>builder()
-            .put("key", 
ClassLoaderUtils.getSystemResourceAsByteArray("ics/ics_with_error.ics"))
+        Map<String, AttributeValue<byte[]>> attachments = 
ImmutableMap.<String, AttributeValue<byte[]>>builder()
+            .put("key", 
AttributeValue.of(ClassLoaderUtils.getSystemResourceAsByteArray("ics/ics_with_error.ics")))
             .build();
 
         Mail mail = FakeMail.builder()
@@ -264,7 +264,7 @@ class ICalendarParserTest {
 
         mailet.service(mail);
 
-        Optional<Map<String, Calendar>> expectedCalendars = 
AttributeUtils.getValueAndCastFromMail(mail, DESTINATION_CUSTOM_ATTRIBUTE_NAME, 
MAP_STRING_CALENDAR_CLASS);
+        Optional<Map<String, AttributeValue<Serializable>>> expectedCalendars 
= AttributeUtils.getValueAndCastFromMail(mail, 
DESTINATION_CUSTOM_ATTRIBUTE_NAME, MAP_STRING_CALENDAR_CLASS);
         assertThat(expectedCalendars).hasValueSatisfying(calendars ->
                 assertThat(calendars)
                         .hasSize(1));
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/mailets/MailAttributesListToMimeHeaders.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/mailets/MailAttributesListToMimeHeaders.java
index a253e08688..e9a1db1390 100644
--- 
a/mailet/standard/src/main/java/org/apache/james/transport/mailets/MailAttributesListToMimeHeaders.java
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/mailets/MailAttributesListToMimeHeaders.java
@@ -19,17 +19,16 @@
 
 package org.apache.james.transport.mailets;
 
-import java.io.Serializable;
 import java.util.Collection;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.Optional;
 
 import javax.mail.MessagingException;
 import javax.mail.internet.MimeMessage;
 
 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.GenericMailet;
 import org.slf4j.Logger;
@@ -85,20 +84,15 @@ public class MailAttributesListToMimeHeaders extends 
GenericMailet {
             .ifPresent(attribute -> {
                 if (attribute instanceof Collection) {
                     @SuppressWarnings("unchecked")
-                    Optional<Collection<Serializable>> values = 
Optional.of((Collection<Serializable>) attribute);
-                    addCollectionToHeader(message, entry.getValue(), values);
+                    Collection<AttributeValue<?>> values = 
(Collection<AttributeValue<?>>) attribute;
+                    values.forEach(
+                        value -> addValueToHeader(message, entry.getValue(), 
value.getValue()));
                 } else {
                     LOGGER.warn("Can not add {} to headers. Expecting class 
Collection but got {}.", attribute, attribute.getClass());
                 }
             });
     }
 
-    private void addCollectionToHeader(MimeMessage message, String headerName, 
Optional<Collection<Serializable>> values) {
-        values.ifPresent(collection ->
-            collection.forEach(
-                value -> addValueToHeader(message, headerName, value)));
-    }
-
     private void addValueToHeader(MimeMessage message, String headerName, 
Object value) {
         try {
             if (value instanceof String) {
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/mailets/MimeDecodingMailet.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/mailets/MimeDecodingMailet.java
index 80a1d12db1..8a2e1fa712 100644
--- 
a/mailet/standard/src/main/java/org/apache/james/transport/mailets/MimeDecodingMailet.java
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/mailets/MimeDecodingMailet.java
@@ -79,32 +79,32 @@ public class MimeDecodingMailet extends GenericMailet {
     }
 
     private void setAttribute(Mail mail, Attribute attribute) {
-        Function<Map.Entry<String, byte[]>, Stream<Pair<String, byte[]>>> 
convertToMapContent =
+        Function<Map.Entry<String, AttributeValue<byte[]>>, 
Stream<Pair<String, byte[]>>> convertToMapContent =
             Throwing
-                .<Map.Entry<String, byte[]>, Stream<Pair<String, 
byte[]>>>function(entry ->
-                    extractContent(entry.getValue())
+                .<Map.Entry<String, AttributeValue<byte[]>>, 
Stream<Pair<String, byte[]>>>function(entry ->
+                    extractContent(entry.getValue().getValue())
                         .stream()
                         .map(content -> Pair.of(entry.getKey(), content)))
                 .sneakyThrow();
 
-        ImmutableMap<String, byte[]> extractedMimeContentByName = 
getAttributeContent(attribute)
+        Map<String, AttributeValue<?>> extractedMimeContentByName = 
getAttributeContent(attribute)
                 .entrySet()
                 .stream()
                 .flatMap(convertToMapContent)
-                .collect(ImmutableMap.toImmutableMap(Pair::getKey, 
Pair::getValue));
+                .collect(ImmutableMap.toImmutableMap(Pair::getKey, pair -> 
AttributeValue.of(pair.getValue())));
 
-        mail.setAttribute(new Attribute(attributeName, 
AttributeValue.ofAny(extractedMimeContentByName)));
+        mail.setAttribute(new Attribute(attributeName, 
AttributeValue.of(extractedMimeContentByName)));
     }
 
     @SuppressWarnings("unchecked")
-    private Map<String, byte[]> getAttributeContent(Attribute attribute) {
+    private Map<String, AttributeValue<byte[]>> getAttributeContent(Attribute 
attribute) {
         Object attributeValue = attribute.getValue().value();
         if (! (attributeValue instanceof Map)) {
             LOGGER.debug("Invalid attribute found into attribute {} class Map 
expected but {} found.",
                     attribute, attributeValue.getClass());
             return ImmutableMap.of();
         }
-        return (Map<String, byte[]>) attributeValue;
+        return (Map<String, AttributeValue<byte[]>>) attributeValue;
     }
 
     private Optional<byte[]> extractContent(Object rawMime) throws 
MessagingException {
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/mailets/RecoverAttachment.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/mailets/RecoverAttachment.java
index 172b76689a..89d84e8c05 100644
--- 
a/mailet/standard/src/main/java/org/apache/james/transport/mailets/RecoverAttachment.java
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/mailets/RecoverAttachment.java
@@ -33,6 +33,7 @@ import javax.mail.internet.MimeMultipart;
 
 import org.apache.mailet.AttributeName;
 import org.apache.mailet.AttributeUtils;
+import org.apache.mailet.AttributeValue;
 import org.apache.mailet.Experimental;
 import org.apache.mailet.Mail;
 import org.apache.mailet.MailetException;
@@ -66,7 +67,7 @@ import com.github.fge.lambdas.Throwing;
 public class RecoverAttachment extends GenericMailet {
     private static final Logger LOGGER = 
LoggerFactory.getLogger(RecoverAttachment.class);
     @SuppressWarnings("unchecked")
-    private static final Class<Map<String, byte[]>> MAP_STRING_BYTES_CLASS = 
(Class<Map<String, byte[]>>) (Object) Map.class;
+    private static final Class<Map<String, AttributeValue<?>>> 
MAP_STRING_BYTES_CLASS = (Class<Map<String, AttributeValue<?>>>) (Object) 
Map.class;
 
     private static final String ATTRIBUTE_PARAMETER_NAME = "attribute";
 
@@ -98,11 +99,11 @@ public class RecoverAttachment extends GenericMailet {
     public void service(Mail mail) throws MailetException {
         AttributeUtils
             .getValueAndCastFromMail(mail, attributeName, 
MAP_STRING_BYTES_CLASS)
-            .ifPresent(Throwing.<Map<String, byte[]>>consumer(attachments ->
+            .ifPresent(Throwing.<Map<String, 
AttributeValue<?>>>consumer(attachments ->
                     processAttachment(mail, attachments)).sneakyThrow());
     }
 
-    private void processAttachment(Mail mail, Map<String, byte[]> attachments) 
throws MailetException {
+    private void processAttachment(Mail mail, Map<String,  AttributeValue<?>> 
attachments) throws MailetException {
         MimeMessage message;
         try {
             message = mail.getMessage();
@@ -111,10 +112,13 @@ public class RecoverAttachment extends GenericMailet {
                     "Could not retrieve message from Mail object", e);
         }
 
-        Iterator<byte[]> i = attachments.values().iterator();
+        Iterator<AttributeValue<?>> i = attachments.values().iterator();
         try {
             while (i.hasNext()) {
-                byte[] bytes = i.next();
+                if (!(i.next().getValue() instanceof byte[])) {
+                    continue;
+                }
+                byte[] bytes = (byte[]) i.next().getValue();
                 InputStream is = new BufferedInputStream(
                         new ByteArrayInputStream(bytes));
                 MimeBodyPart p = new MimeBodyPart(is);
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/mailets/StripAttachment.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/mailets/StripAttachment.java
index 63c3ddff2f..bd04f95ba2 100644
--- 
a/mailet/standard/src/main/java/org/apache/james/transport/mailets/StripAttachment.java
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/mailets/StripAttachment.java
@@ -93,7 +93,7 @@ import com.google.common.collect.ImmutableMap;
 public class StripAttachment extends GenericMailet {
     private static final Logger LOGGER = 
LoggerFactory.getLogger(StripAttachment.class);
     @SuppressWarnings("unchecked")
-    private static final Class<Map<String, byte[]>> MAP_STRING_BYTES_CLASS = 
(Class<Map<String, byte[]>>) (Object) Map.class;
+    private static final Class<Map<String, AttributeValue<byte[]>>> 
MAP_STRING_BYTES_CLASS = (Class<Map<String, AttributeValue<byte[]>>>) (Object) 
Map.class;
 
     @SuppressWarnings("unchecked")
     private static final Class<List<AttributeValue<String>>> LIST_OF_STRINGS = 
(Class<List<AttributeValue<String>>>)(Object) List.class;
@@ -354,15 +354,17 @@ public class StripAttachment extends GenericMailet {
     }
 
     private void addPartContent(BodyPart bodyPart, Mail mail, String fileName, 
AttributeName attributeName) throws IOException, MessagingException {
-        ImmutableMap.Builder<String, byte[]> fileNamesToPartContent = 
AttributeUtils
+        ImmutableMap.Builder<String, AttributeValue<?>> fileNamesToPartContent 
= AttributeUtils
             .getValueAndCastFromMail(mail, attributeName, 
MAP_STRING_BYTES_CLASS)
-            .map(ImmutableMap.<String, byte[]>builder()::putAll)
+            .map(ImmutableMap.<String, AttributeValue<?>>builder()::putAll)
             .orElse(ImmutableMap.builder());
 
         UnsynchronizedByteArrayOutputStream byteArrayOutputStream = new 
UnsynchronizedByteArrayOutputStream();
         bodyPart.writeTo(byteArrayOutputStream);
-        fileNamesToPartContent.put(fileName, 
byteArrayOutputStream.toByteArray());
-        mail.setAttribute(new Attribute(attributeName, 
AttributeValue.ofAny(fileNamesToPartContent.build())));
+        fileNamesToPartContent.put(fileName, 
AttributeValue.of(byteArrayOutputStream.toByteArray()));
+
+        Map<String, AttributeValue<?>> build = fileNamesToPartContent.build();
+        mail.setAttribute(new Attribute(attributeName, 
AttributeValue.of(build)));
     }
 
     private void storeFileNameAsAttribute(Mail mail, AttributeValue<String> 
fileName, boolean hasToBeStored) {
diff --git 
a/mailet/standard/src/test/java/org/apache/james/transport/mailets/MailAttributesListToMimeHeadersTest.java
 
b/mailet/standard/src/test/java/org/apache/james/transport/mailets/MailAttributesListToMimeHeadersTest.java
index 2380666164..f359927e9b 100644
--- 
a/mailet/standard/src/test/java/org/apache/james/transport/mailets/MailAttributesListToMimeHeadersTest.java
+++ 
b/mailet/standard/src/test/java/org/apache/james/transport/mailets/MailAttributesListToMimeHeadersTest.java
@@ -28,6 +28,7 @@ import javax.mail.MessagingException;
 
 import org.apache.james.core.builder.MimeMessageBuilder;
 import org.apache.mailet.Attribute;
+import org.apache.mailet.AttributeValue;
 import org.apache.mailet.Mailet;
 import org.apache.mailet.base.test.FakeMail;
 import org.apache.mailet.base.test.FakeMailetConfig;
@@ -43,8 +44,8 @@ class MailAttributesListToMimeHeadersTest {
     private static final String VALUE_1_2 = "test1.2";
     private static final String VALUE_2_1 = "test2.1";
     private static final String VALUE_2_2 = "test2.2";
-    private static final ImmutableList<String> MAIL_ATTRIBUTE_VALUE1 = 
ImmutableList.of(VALUE_1_1, VALUE_1_2);
-    private static final ImmutableList<String> MAIL_ATTRIBUTE_VALUE2 = 
ImmutableList.of(VALUE_2_1, VALUE_2_2);
+    private static final ImmutableList<AttributeValue<String>> 
MAIL_ATTRIBUTE_VALUE1 = ImmutableList.of(AttributeValue.of(VALUE_1_1), 
AttributeValue.of(VALUE_1_2));
+    private static final ImmutableList<AttributeValue<String>> 
MAIL_ATTRIBUTE_VALUE2 = ImmutableList.of(AttributeValue.of(VALUE_2_1), 
AttributeValue.of(VALUE_2_2));
 
     private static final String MAIL_ATTRIBUTE_NAME1 = "org.apache.james.test";
     private static final String MAIL_ATTRIBUTE_NAME2 = 
"org.apache.james.test2";
@@ -127,32 +128,6 @@ class MailAttributesListToMimeHeadersTest {
             .containsExactly(VALUE_1_1, VALUE_1_2);
     }
 
-    @Test
-    void shouldIgnoreNullValueInsideList() throws MessagingException {
-        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
-            .mailetName("Test")
-            .setProperty("simplemapping",
-                MAIL_ATTRIBUTE_NAME1 + "; " + HEADER_NAME1)
-            .build();
-
-        mailet.init(mailetConfig);
-
-        ArrayList<String> listWithNull = new ArrayList<>();
-        listWithNull.add("1");
-        listWithNull.add(null);
-        listWithNull.add("2");
-        FakeMail mail = FakeMail.builder()
-            .name("mail")
-            .mimeMessage(MailUtil.createMimeMessage())
-            .attribute(Attribute.convertToAttribute(MAIL_ATTRIBUTE_NAME1, 
listWithNull))
-            .build();
-
-        mailet.service(mail);
-
-        assertThat(mail.getMessage().getHeader(HEADER_NAME1))
-            .containsExactly("1", "2");
-    }
-
     @Test
     void shouldPutAttributesIntoHeadersWhenMappingDefined() throws 
MessagingException {
         FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
@@ -175,10 +150,14 @@ class MailAttributesListToMimeHeadersTest {
         mailet.service(mail);
 
         assertThat(mail.getMessage().getHeader(HEADER_NAME1))
-            .containsExactlyElementsOf(MAIL_ATTRIBUTE_VALUE1);
+            .containsExactlyElementsOf(MAIL_ATTRIBUTE_VALUE1.stream()
+                .map(AttributeValue::getValue)
+                .collect(ImmutableList.toImmutableList()));
 
         assertThat(mail.getMessage().getHeader(HEADER_NAME2))
-            .containsExactlyElementsOf(MAIL_ATTRIBUTE_VALUE2);
+            .containsExactlyElementsOf(MAIL_ATTRIBUTE_VALUE2.stream()
+                .map(AttributeValue::getValue)
+                .collect(ImmutableList.toImmutableList()));
     }
 
     @Test
@@ -224,7 +203,9 @@ class MailAttributesListToMimeHeadersTest {
 
         assertThat(mail.getMessage().getHeader(HEADER_NAME1)).isNull();
         assertThat(mail.getMessage().getHeader(HEADER_NAME2))
-            .containsExactlyElementsOf(MAIL_ATTRIBUTE_VALUE2);
+            .containsExactlyElementsOf(MAIL_ATTRIBUTE_VALUE2.stream()
+                .map(AttributeValue::getValue)
+                .collect(ImmutableList.toImmutableList()));
     }
 
 
@@ -240,7 +221,7 @@ class MailAttributesListToMimeHeadersTest {
         FakeMail mail = FakeMail.builder()
             .name("mail")
             .mimeMessage(MimeMessageBuilder.mimeMessageBuilder())
-            .attribute(Attribute.convertToAttribute(MAIL_ATTRIBUTE_NAME1, 
ImmutableList.of(3L, value)))
+            .attribute(Attribute.convertToAttribute(MAIL_ATTRIBUTE_NAME1, 
ImmutableList.of(AttributeValue.of(3L), AttributeValue.of(value))))
             .build();
 
         mailet.service(mail);
diff --git 
a/mailet/standard/src/test/java/org/apache/james/transport/mailets/MimeDecodingMailetTest.java
 
b/mailet/standard/src/test/java/org/apache/james/transport/mailets/MimeDecodingMailetTest.java
index 455c3a2ed6..a2efee348c 100644
--- 
a/mailet/standard/src/test/java/org/apache/james/transport/mailets/MimeDecodingMailetTest.java
+++ 
b/mailet/standard/src/test/java/org/apache/james/transport/mailets/MimeDecodingMailetTest.java
@@ -37,7 +37,6 @@ import org.apache.mailet.MailetException;
 import org.apache.mailet.base.test.FakeMail;
 import org.apache.mailet.base.test.FakeMailContext;
 import org.apache.mailet.base.test.FakeMailetConfig;
-import org.assertj.core.data.MapEntry;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.slf4j.Logger;
@@ -49,7 +48,7 @@ class MimeDecodingMailetTest {
 
     private static final AttributeName MAIL_ATTRIBUTE = 
AttributeName.of("mime.attachments");
     @SuppressWarnings("unchecked")
-    private static final Class<Map<String, byte[]>> MAP_STRING_BYTES_CLASS = 
(Class<Map<String, byte[]>>) (Object) Map.class;
+    private static final Class<Map<String, AttributeValue<byte[]>>> 
MAP_STRING_BYTES_CLASS = (Class<Map<String, AttributeValue<byte[]>>>) (Object) 
Map.class;
 
     private MailetContext mailetContext;
     private MimeDecodingMailet testee;
@@ -145,15 +144,15 @@ class MimeDecodingMailetTest {
                 + "Content-Type: application/octet-stream; 
charset=utf-8\r\n\r\n"
                 + text;
         String expectedKey = "mimePart1";
-        AttributeValue<?> value = 
AttributeValue.ofAny(ImmutableMap.of(expectedKey, 
content.getBytes(StandardCharsets.UTF_8)));
+        AttributeValue<?> value = 
AttributeValue.of(ImmutableMap.of(expectedKey, 
AttributeValue.of(content.getBytes(StandardCharsets.UTF_8))));
         mail.setAttribute(new Attribute(MAIL_ATTRIBUTE, value));
 
-        byte[] expectedValue = text.getBytes(StandardCharsets.UTF_8);
+        AttributeValue<byte[]> expectedValue = 
AttributeValue.of(text.getBytes(StandardCharsets.UTF_8));
         testee.service(mail);
 
-        Optional<Map<String, byte[]>> processedAttribute = 
AttributeUtils.getValueAndCastFromMail(mail, MAIL_ATTRIBUTE, 
MAP_STRING_BYTES_CLASS);
+        Optional<Map<String, AttributeValue<byte[]>>> processedAttribute = 
AttributeUtils.getValueAndCastFromMail(mail, MAIL_ATTRIBUTE, 
MAP_STRING_BYTES_CLASS);
         assertThat(processedAttribute).hasValueSatisfying(map ->
-            assertThat(map)
-                .containsExactly(MapEntry.entry(expectedKey, expectedValue)));
+            assertThat(map.values().stream().findFirst().get().getValue())
+                .contains(expectedValue.value()));
     }
 }
diff --git 
a/mailet/standard/src/test/java/org/apache/james/transport/mailets/StripAttachmentTest.java
 
b/mailet/standard/src/test/java/org/apache/james/transport/mailets/StripAttachmentTest.java
index 4eb7979466..3e47283a73 100644
--- 
a/mailet/standard/src/test/java/org/apache/james/transport/mailets/StripAttachmentTest.java
+++ 
b/mailet/standard/src/test/java/org/apache/james/transport/mailets/StripAttachmentTest.java
@@ -65,7 +65,7 @@ class StripAttachmentTest {
     @SuppressWarnings("unchecked")
     private static Class<Collection<AttributeValue<String>>> 
COLLECTION_STRING_CLASS = (Class<Collection<AttributeValue<String>>>) (Object) 
Collection.class;
     @SuppressWarnings("unchecked")
-    private static Class<Map<String, byte[]>> MAP_STRING_BYTES_CLASS = 
(Class<Map<String, byte[]>>) (Object) Map.class;
+    private static Class<Map<String, AttributeValue<?>>> 
MAP_STRING_BYTES_CLASS = (Class<Map<String, AttributeValue<?>>>) (Object) 
Map.class;
 
     private static final String EXPECTED_ATTACHMENT_CONTENT = "#¤ãàé";
     private static final Optional<String> ABSENT_MIME_TYPE = Optional.empty();
@@ -283,13 +283,13 @@ class StripAttachmentTest {
 
         mailet.service(mail);
 
-        Optional<Map<String, byte[]>> savedValue = 
AttributeUtils.getValueAndCastFromMail(mail, AttributeName.of(customAttribute), 
MAP_STRING_BYTES_CLASS);
-        ConsumerChainer<Map<String, byte[]>> assertValue = 
Throwing.consumer(saved -> {
+        Optional<Map<String, AttributeValue<?>>> savedValue = 
AttributeUtils.getValueAndCastFromMail(mail, AttributeName.of(customAttribute), 
MAP_STRING_BYTES_CLASS);
+        ConsumerChainer<Map<String, AttributeValue<?>>> assertValue = 
Throwing.consumer(saved -> {
             assertThat(saved)
                     .hasSize(1)
                     .containsKeys(expectedKey);
 
-            MimeBodyPart savedBodyPart = new MimeBodyPart(new 
ByteArrayInputStream(saved.get(expectedKey)));
+            MimeBodyPart savedBodyPart = new MimeBodyPart(new 
ByteArrayInputStream((byte[]) saved.get(expectedKey).getValue()));
             String content = IOUtils.toString(savedBodyPart.getInputStream(), 
StandardCharsets.UTF_8);
             assertThat(content).isEqualTo(EXPECTED_ATTACHMENT_CONTENT);
         });
@@ -321,13 +321,13 @@ class StripAttachmentTest {
 
         mailet.service(mail);
 
-        Optional<Map<String, byte[]>> savedValue = 
AttributeUtils.getValueAndCastFromMail(mail, AttributeName.of(customAttribute), 
MAP_STRING_BYTES_CLASS);
-        ConsumerChainer<Map<String, byte[]>> assertValue = 
Throwing.consumer(saved -> {
+        Optional<Map<String, AttributeValue<?>>> savedValue = 
AttributeUtils.getValueAndCastFromMail(mail, AttributeName.of(customAttribute), 
MAP_STRING_BYTES_CLASS);
+        ConsumerChainer<Map<String, AttributeValue<?>>> assertValue = 
Throwing.consumer(saved -> {
             assertThat(saved)
                     .hasSize(1)
                     .containsKeys(expectedKey);
 
-            MimeBodyPart savedBodyPart = new MimeBodyPart(new 
ByteArrayInputStream(saved.get(expectedKey)));
+            MimeBodyPart savedBodyPart = new MimeBodyPart(new 
ByteArrayInputStream((byte[]) saved.get(expectedKey).getValue()));
             String content = IOUtils.toString(savedBodyPart.getInputStream(), 
StandardCharsets.UTF_8);
             assertThat(content).isEqualTo(EXPECTED_ATTACHMENT_CONTENT);
         });
@@ -655,7 +655,7 @@ class StripAttachmentTest {
         
         //Then
         assertThat(actual).isTrue();
-        Optional<Map<String, byte[]>> savedValue = 
AttributeUtils.getValueAndCastFromMail(mail, AttributeName.of(customAttribute), 
MAP_STRING_BYTES_CLASS);
+        Optional<Map<String,  AttributeValue<?>>> savedValue = 
AttributeUtils.getValueAndCastFromMail(mail, AttributeName.of(customAttribute), 
MAP_STRING_BYTES_CLASS);
         assertThat(savedValue)
                 .isPresent()
                 .hasValueSatisfying(saved ->


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscr...@james.apache.org
For additional commands, e-mail: notifications-h...@james.apache.org

Reply via email to