MAILBOX-268 Add mandatory attributes to Attachment

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

Branch: refs/heads/master
Commit: dd4f7caaf13cf3e14a24357783414a8a75e2a954
Parents: 7b259d9
Author: Antoine Duprat <adup...@linagora.com>
Authored: Wed May 25 10:09:18 2016 +0200
Committer: Antoine Duprat <antdup...@gmail.com>
Committed: Fri May 27 10:02:02 2016 +0200

----------------------------------------------------------------------
 .../mailbox/store/mail/model/Attachment.java    | 109 ++++++++++++++++++-
 .../mailbox/store/mail/model/AttachmentId.java  |  53 ++++++++-
 .../store/mail/model/impl/MessageParser.java    |  22 +++-
 .../store/mail/model/AttachmentIdTest.java      |  56 ++++++++++
 .../store/mail/model/AttachmentTest.java        |  74 ++++++++++++-
 .../mail/model/impl/MessageParserTest.java      |  28 ++++-
 .../eml/oneAttachmentWithSimpleContentType.eml  |  38 +++++++
 7 files changed, 370 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/dd4f7caa/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Attachment.java
----------------------------------------------------------------------
diff --git 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Attachment.java
 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Attachment.java
index f422f12..5af2b28 100644
--- 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Attachment.java
+++ 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Attachment.java
@@ -22,16 +22,123 @@ package org.apache.james.mailbox.store.mail.model;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Arrays;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
 
 public class Attachment {
 
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static Attachment from(byte[] bytes, String type) {
+        return builder()
+                .attachmentId(AttachmentId.forPayload(bytes))
+                .bytes(bytes)
+                .type(type)
+                .size(bytes.length)
+                .build();
+    }
+
+    public static class Builder {
+
+        private AttachmentId attachmentId;
+        private byte[] bytes;
+        private String type;
+        private Long size;
+
+        private Builder() {
+        }
+
+        public Builder attachmentId(AttachmentId attachmentId) {
+            Preconditions.checkArgument(attachmentId != null);
+            this.attachmentId = attachmentId;
+            return this;
+        }
+
+        public Builder bytes(byte[] bytes) {
+            Preconditions.checkArgument(bytes != null);
+            this.bytes = bytes;
+            return this;
+        }
+
+        public Builder type(String type) {
+            Preconditions.checkArgument(!Strings.isNullOrEmpty(type));
+            this.type = type;
+            return this;
+        }
+
+        public Builder size(long size) {
+            this.size = size;
+            return this;
+        }
+
+        public Attachment build() {
+            Preconditions.checkState(attachmentId != null, "'attachmentId' is 
mandatory");
+            Preconditions.checkState(bytes != null, "'bytes' is mandatory");
+            Preconditions.checkState(type != null, "'type' is mandatory");
+            Preconditions.checkState(size != null, "'size' is mandatory");
+            return new Attachment(bytes, attachmentId, type, size);
+        }
+    }
+
     private final byte[] bytes;
+    private final AttachmentId attachmentId;
+    private final String type;
+    private final long size;
 
-    public Attachment(byte[] bytes) {
+    private Attachment(byte[] bytes, AttachmentId attachmentId, String type, 
long size) {
         this.bytes = bytes;
+        this.attachmentId = attachmentId;
+        this.type = type;
+        this.size = size;
+    }
+
+    public AttachmentId getAttachmentId() {
+        return attachmentId;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public long getSize() {
+        return size;
     }
 
     public InputStream getStream() throws IOException {
         return new ByteArrayInputStream(bytes);
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof Attachment) {
+            Attachment other = (Attachment) obj;
+            return Objects.equal(attachmentId, other.attachmentId)
+                && Arrays.equals(bytes, other.bytes)
+                && Objects.equal(type, other.type)
+                && Objects.equal(size, other.size);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(attachmentId, bytes, type, size);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects
+                .toStringHelper(this)
+                .add("attachmentId", attachmentId)
+                .add("bytes", bytes)
+                .add("type", type)
+                .add("size", size)
+                .toString();
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/dd4f7caa/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/AttachmentId.java
----------------------------------------------------------------------
diff --git 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/AttachmentId.java
 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/AttachmentId.java
index dc87bf1..344c84e 100644
--- 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/AttachmentId.java
+++ 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/AttachmentId.java
@@ -18,6 +18,55 @@
  ****************************************************************/
 package org.apache.james.mailbox.store.mail.model;
 
-public interface AttachmentId {
-    String serialize();
+
+import org.apache.commons.codec.digest.DigestUtils;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+
+public class AttachmentId {
+
+    public static AttachmentId forPayload(byte[] payload) {
+        Preconditions.checkArgument(payload != null);
+        return new AttachmentId(DigestUtils.sha1Hex(payload));
+    }
+
+    public static AttachmentId from(String id) {
+        Preconditions.checkArgument(!Strings.isNullOrEmpty(id));
+        return new AttachmentId(id);
+    }
+
+    private final String id;
+
+    private AttachmentId(String id) {
+        this.id = id;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof AttachmentId) {
+            AttachmentId other = (AttachmentId) obj;
+            return Objects.equal(id, other.id);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(id);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects
+                .toStringHelper(this)
+                .add("id", id)
+                .toString();
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/dd4f7caa/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
----------------------------------------------------------------------
diff --git 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
index 83987b3..bba6a13 100644
--- 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
+++ 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/MessageParser.java
@@ -33,11 +33,17 @@ import org.apache.james.mime4j.dom.Multipart;
 import org.apache.james.mime4j.dom.field.ContentDispositionField;
 import org.apache.james.mime4j.message.DefaultMessageBuilder;
 import org.apache.james.mime4j.message.DefaultMessageWriter;
+import org.apache.james.mime4j.stream.Field;
 
+import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
 
 public class MessageParser {
 
+    private static final String CONTENT_TYPE = "Content-Type";
+    private static final String HEADER_SEPARATOR = ";";
+
     public List<Attachment> retrieveAttachments(InputStream fullContent) 
throws MimeException, IOException {
         Body body = new DefaultMessageBuilder()
                 .parseMessage(fullContent)
@@ -58,19 +64,29 @@ public class MessageParser {
         MessageWriter messageWriter = new DefaultMessageWriter();
         for (Entity entity : multipart.getBodyParts()) {
             if (isAttachment(entity)) {
-                attachments.add(createAttachment(messageWriter, 
entity.getBody()));
+                attachments.add(createAttachment(messageWriter, 
entity.getBody(), 
+                        
contentType(entity.getHeader().getField(CONTENT_TYPE))));
             }
         }
         return attachments.build();
     }
 
+    private String contentType(Field contentType) {
+        String body = contentType.getBody();
+        if (body.contains(HEADER_SEPARATOR)) {
+            return Iterables.get(Splitter.on(HEADER_SEPARATOR).split(body), 0);
+        }
+        return body;
+    }
+
     private boolean isAttachment(Entity part) {
         return 
ContentDispositionField.DISPOSITION_TYPE_ATTACHMENT.equalsIgnoreCase(part.getDispositionType());
     }
 
-    private Attachment createAttachment(MessageWriter messageWriter, Body 
body) throws IOException {
+    private Attachment createAttachment(MessageWriter messageWriter, Body 
body, String contentType) throws IOException {
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         messageWriter.writeBody(body, out);
-        return new Attachment(out.toByteArray());
+        byte[] bytes = out.toByteArray();
+        return Attachment.from(bytes, contentType);
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/dd4f7caa/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentIdTest.java
----------------------------------------------------------------------
diff --git 
a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentIdTest.java
 
b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentIdTest.java
new file mode 100644
index 0000000..b95dc84
--- /dev/null
+++ 
b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentIdTest.java
@@ -0,0 +1,56 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.store.mail.model;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Test;
+
+public class AttachmentIdTest {
+
+    @Test
+    public void forPayloadShouldCalculateTheUnderlyingSha1() {
+        AttachmentId attachmentId = 
AttachmentId.forPayload("payload".getBytes());
+        String expectedId = "f07e5a815613c5abeddc4b682247a4c42d8a95df";
+        assertThat(attachmentId.getId()).isEqualTo(expectedId);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void forPayloadShouldThrowWhenPayloadIsNull() {
+        AttachmentId.forPayload(null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void fromShouldThrowWhenIdIsNull() {
+        AttachmentId.from(null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void fromShouldThrowWhenIdIsEmpty() {
+        AttachmentId.from("");
+    }
+
+    @Test
+    public void fromShouldWork() {
+        String expectedId = "f07e5a815613c5abeddc4b682247a4c42d8a95df";
+        AttachmentId attachmentId = AttachmentId.from(expectedId);
+        assertThat(attachmentId.getId()).isEqualTo(expectedId);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/dd4f7caa/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentTest.java
----------------------------------------------------------------------
diff --git 
a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentTest.java
 
b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentTest.java
index 9c91c93..5e96c7d 100644
--- 
a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentTest.java
+++ 
b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/AttachmentTest.java
@@ -32,7 +32,7 @@ public class AttachmentTest {
     @Test
     public void streamShouldBeConsumedOneTime() throws Exception {
         String input = "mystream";
-        Attachment attachment = new Attachment(input.getBytes());
+        Attachment attachment = Attachment.from(input.getBytes(), "content");
 
         InputStream stream = attachment.getStream();
         assertThat(stream).isNotNull();
@@ -42,11 +42,81 @@ public class AttachmentTest {
     @Test
     public void streamShouldBeConsumedMoreThanOneTime() throws Exception {
         String input = "mystream";
-        Attachment attachment = new Attachment(input.getBytes());
+        Attachment attachment = Attachment.from(input.getBytes(), "content");
 
         attachment.getStream();
         InputStream stream = attachment.getStream();
         assertThat(stream).isNotNull();
         assertThat(IOUtils.toString(stream)).isEqualTo(input);
     }
+
+    @Test (expected = IllegalArgumentException.class)
+    public void builderShouldThrowWhenAttachmentIdIsNull() {
+        Attachment.builder()
+            .attachmentId(null);
+    }
+
+    @Test (expected = IllegalArgumentException.class)
+    public void builderShouldThrowWhenBytesIsNull() {
+        Attachment.builder()
+            .bytes(null);
+    }
+
+    @Test (expected = IllegalArgumentException.class)
+    public void builderShouldThrowWhenTypeIsNull() {
+        Attachment.builder()
+            .type(null);
+    }
+
+    @Test (expected = IllegalArgumentException.class)
+    public void builderShouldThrowWhenTypeIsEmpty() {
+        Attachment.builder()
+            .type("");
+    }
+
+    @Test (expected = IllegalStateException.class)
+    public void buildShouldThrowWhenAttachmentIdIsNotProvided() {
+        Attachment.builder().build();
+    }
+
+    @Test (expected = IllegalStateException.class)
+    public void buildShouldThrowWhenBytesIsNotProvided() {
+        Attachment.builder()
+            .attachmentId(AttachmentId.forPayload("mystream".getBytes()))
+            .build();
+    }
+
+    @Test (expected = IllegalStateException.class)
+    public void buildShouldThrowWhenTypeIsNotProvided() {
+        Attachment.builder()
+            .attachmentId(AttachmentId.forPayload("mystream".getBytes()))
+            .bytes("mystream".getBytes())
+            .build();
+    }
+
+    @Test (expected = IllegalStateException.class)
+    public void buildShouldThrowWhenSizeIsNotProvided() {
+        Attachment.builder()
+            .attachmentId(AttachmentId.forPayload("mystream".getBytes()))
+            .bytes("mystream".getBytes())
+            .type("content")
+            .build();
+    }
+
+    @Test
+    public void fromShouldSetTheAttachmentId() throws Exception {
+        byte[] bytes = "mystream".getBytes();
+        Attachment attachment = Attachment.from(bytes, "content");
+        AttachmentId expected = AttachmentId.forPayload(bytes);
+
+        assertThat(attachment.getAttachmentId()).isEqualTo(expected);
+    }
+
+    @Test
+    public void fromShouldSetTheSize() throws Exception {
+        String input = "mystream";
+        Attachment attachment = Attachment.from(input.getBytes(), "content");
+
+        assertThat(attachment.getSize()).isEqualTo(input.getBytes().length);
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/dd4f7caa/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/MessageParserTest.java
----------------------------------------------------------------------
diff --git 
a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/MessageParserTest.java
 
b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/MessageParserTest.java
index 719ca77..de1137c 100644
--- 
a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/MessageParserTest.java
+++ 
b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/impl/MessageParserTest.java
@@ -37,20 +37,44 @@ public class MessageParserTest {
     }
 
     @Test
-    public void getAttachmentsShouldBeEmptyWhenNone() throws Exception {
+    public void getAttachmentsShouldBeEmptyWhenNoAttachment() throws Exception 
{
         List<Attachment> attachments = 
testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/noAttachment.eml"));
 
         assertThat(attachments).isEmpty();
     }
 
     @Test
-    public void getAttachmentsShouldRetrieveAttachmentsWhenOne() throws 
Exception {
+    public void getAttachmentsShouldRetrieveAttachmentsWhenOneAttachment() 
throws Exception {
         List<Attachment> attachments = 
testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeInlined.eml"));
 
         assertThat(attachments).hasSize(1);
     }
 
     @Test
+    public void 
getAttachmentsShouldRetrieveTheAttachmentContentTypeWhenOneAttachment() throws 
Exception {
+        List<Attachment> attachments = 
testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeInlined.eml"));
+
+        assertThat(attachments).hasSize(1);
+        
assertThat(attachments.get(0).getType()).isEqualTo("application/octet-stream");
+    }
+
+    @Test
+    public void 
getAttachmentsShouldRetrieveTheAttachmentContentTypeWhenOneAttachmentWithSimpleContentType()
 throws Exception {
+        List<Attachment> attachments = 
testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentWithSimpleContentType.eml"));
+
+        assertThat(attachments).hasSize(1);
+        
assertThat(attachments.get(0).getType()).isEqualTo("application/octet-stream");
+    }
+
+    @Test
+    public void 
getAttachmentsShouldRetrieveTheAttachmentSizeWhenOneAttachment() throws 
Exception {
+        List<Attachment> attachments = 
testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeInlined.eml"));
+
+        assertThat(attachments).hasSize(1);
+        assertThat(attachments.get(0).getSize()).isEqualTo(3071);
+    }
+
+    @Test
     public void getAttachmentsShouldReturnTheExpectedAttachment() throws 
Exception {
         List<Attachment> attachments = 
testee.retrieveAttachments(ClassLoader.getSystemResourceAsStream("eml/oneAttachmentAndSomeInlined.eml"));
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/dd4f7caa/mailbox/store/src/test/resources/eml/oneAttachmentWithSimpleContentType.eml
----------------------------------------------------------------------
diff --git 
a/mailbox/store/src/test/resources/eml/oneAttachmentWithSimpleContentType.eml 
b/mailbox/store/src/test/resources/eml/oneAttachmentWithSimpleContentType.eml
new file mode 100644
index 0000000..ca0abe7
--- /dev/null
+++ 
b/mailbox/store/src/test/resources/eml/oneAttachmentWithSimpleContentType.eml
@@ -0,0 +1,38 @@
+Mail content:
+To: "=?utf-8?B?UmFuaSBBc3NhZg==?=" <rani.as...@jri.obm.lng.org>
+Subject: =?utf-8?B?VHIuIDogUGhvdG9zICE=?=
+Importance: Normal
+MIME-Version: 1.0
+Content-Type: multipart/mixed;
+       boundary="----=_Part_0_1330682067197"
+
+------=_Part_0_1330682067197
+Content-Type: multipart/alternative;
+       boundary="----=_Part_2_1330682067197"
+
+------=_Part_2_1330682067197
+Content-Type: text/plain;
+       charset= utf-8
+Content-Transfer-Encoding: 8bit
+Content-Disposition: inline
+
+Content of part 1-1
+------=_Part_2_1330682067197
+Content-Type: text/html;
+       charset= utf-8
+Content-Transfer-Encoding: 8bit
+Content-Disposition: inline
+
+<b>Content of part 1-2</b>
+------=_Part_2_1330682067197--
+
+------=_Part_0_1330682067197
+Content-Type: application/octet-stream
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment;
+       filename="gimp.png"
+
+iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAALxklEQVR4Ae2Xe0xUZ97H5X4RiyAXEARURBSYCzNnLjMwwAx3huGOIBcUFJERAUVRq+KlwHABFdu+b9+0766x1W21ttnUtE3rul6aGNtm3XbdWncjaa3VXrZRK6IgfPd3Tp6wOGmyo0v/cOMknxwy5xzO7/P8LueZaWlpaU80TwWeCvy3CcRwXJlUqp39RApIOE4i5hQPxBz30hMpIJIrjktkseMimfzPUyoglilTf/XVl8u1Ik4xrOJEEMu4wSkVEMmVZ6VSTeivFXy0TDZfIlfc0qil0KpIQM59P6UCUk71lVShPD1t2jT7qQ4+Sq32prq/GhfHjSXFSxGvEfMCQ1MsoLzOadT3pArFwBQ3LSdRqK4mJyfcz0xRwaCLRVKcBDEybmxqBRTKH8uXpEOj0/1MD3wuMTHR8T9adY4LoOD3KuPj7xYVGlGYo0e6gUNKoowkpKBmHpXJZO5TKXCrpjwT5pWFSM1IvROrVH0hksujf+laAHYWi8XT+nsKyIlvVKlSeVSu0twtXpI/Yq4rR2lBKoxpamQmK5Gm55CcIAP1wxAvOWUCEk4xVLvchIaVedi8rgq1NSXjqnjdHcrGayK5yhStVPpbLLvE/Xt6Tnf3Wu529XSM9fZ13Wzbse2kJiGhK1ap/ETCqe5lGLNum+trxnZsbca6tcuwJM+AvKw4mNI1yEpVURYUSE2S8wJ3RSKN35QJUJPdM6/IQ8vaCmzdZMbObU2w7G7BhhbzeEFR4e2SsrIRChqnz5zE999/h9HREXz19SDefOt1dPW0Y8e2Frywtx0vDnRg57NrUVdTgJJ8PYpyEpBvjEdOhvahLIg55YOioiKHRxKgjwPBEaHEQzfz/3DH9mb07+nGsbeO4MjRw+jts8DS3or/GdiNnr4ufP6XC/jhh+9w587PuHdvGLdv38SNG9fwwYfvon9vN3Zvb0Td8
 
lxUlqSirCgZpSRQnJuIgmwdcikL2elqZKUwAbni0aaQvb19M3HT2dnlloODw5Cdnd0d+rKVRFz48xkm0+i+gX5cv34NP/30I86fP4ePPjqL3n4LOjq24O2338CVK1/i22+v4ssvL+HTTz+B2WzGqlUrcfr0HzCwvw9Na8pRXZaBqtI0VBSnYGmBgUooEYUmHYQyyhDKCClJCl7gus0C9DE5OjkNpefkoXvPPugzjIiMEcN9+vQ7JHKFzvs1tzTdO3P2lBD8wYMHce3aNVBTYk1DPXp62/HHUx/g0qXPSOIyBgcHwX/u37+PiMhIiCViHP7dAbRuqAc/CJbxAktIoJAXSEKRiZURCRhJwJCoAPXcRZsF7B0dL8cq1RgeHgb/+fziX6E1pPCjDJ5e3iOUmcHWzRvHz398ThAoKSnB5b/9HYbUdMwJmUPl04GTJ9/DhQvn8cYbh/D++++D/1y/cYOvZbi6uWHvvj48u7kRgsDSdEGgjARKSOChPiCBpAQFpBx3ymYBWuXR9Zu2gH0wPj6O7KISyNRxiBJLMeMZz/GcXOP4a4cOCAJ5eXmY5eMDL29v6PUJ6O7aQX1xGOfOncLx429h5syZMDc2I05vQJQ0Fq6uriTZifWNy60yYCXAMqDVcmMiTtlrswAZPMgtLsXY2Jgg8PXVb5CYngWpSoMFi6MRsTAS7rSKnZZdeP3IIarv89ixow21tTXoaN9KE6kefdQLJ04cx5kzH0Cp5OA9axYCgoIx08sLCQlxsHS3o646F9XlGSQwuQeSJveAICBTKm49yuaRb+Drco0W6zdTM75zHJW1dVAlGvjXOULDF2ABCQQFz4FcEomdbc3o7qGpQ+za3oQtzWXY3LwUHc9twfPP9+Gd40ephN5GW9tmJCXpsHnLBrq+HS1N1VhRkYnlZemooilUzk+hgokpNPEuyExWUdlx99lb2GaBV+eGh48kJKciVq0VSofqX1j9wDkhCA4Ng0gihb+vF5
 
pXF2K9uQgta4qxoWEJNq4l6LihoQRtW5vQRSu9d6AH//vSAI1cCzq7dmNdQxVWVmahhq3+RP3n/6t8cjO1yE5TQ59EDaxQsN8Ctk+hUH50JhqSESONFQKfF0GrToH7+AfAf3YQdIlJcHNzwdrafDTWFaCJRJqJdfVFAvzfTfR9c30xrfYytLbUotlchtXVOULwND6FICuXPLz61uWj1iruUePv4gvbZgGWhv2+fn5DesrCXCob34BAPniBoJBQJOj18KMM1NfkYM2KXGFL0VCbxwsJ0N/Cd2Y6x1+zmrYdq5YZJ1Z+OU2ejGTK6rwg4QX20Phkq59mUPLz/264SBRMAva2Sky8hWka/T4gMPBuVnY2OJUaIXPnYU7YXCQlJ0MsFkMaE05BZdPbNJtW1iRQTytMCH9T0MK5VVVC4ELN8ytPZSNsG6IjQ5C4wAkVWl+UZsYiP1sonYl9kIpWPzpW9gLFMp1wJhyYhM1bCUfqh5dp7A3J5PIHqWnpyDQaIZFKMMvbU3iD0hikwLKEAGt5KFhCWGUKlk2ZdGGrUEQlkqaXC+LBgV4ok7tik8Edr1fOwKbkGajXeaBcH4aclFik6hXC9sE7ICCK4vAhZhAutkj8UlMsopL6jZ2d/acOjo7fBAbPuW/Qax7QHkYoBZIQgqUjQ5guQm3nG3VCqeg0IsSKFmDRwlBERYZBHDUPxvhICvoZdGR54IudEfisg8Nva+aiQTcDpVq/B4qY8Ffo2QuIYCsJVk62C9gRTiyVPkFhYSqxnLuk0qqH83P0FGwmVi3PpbLJp2MeZSSbxGjlSa6yRJjxgsxSNmmWUCZo2gjjMj9LgwpDGMzxbji20h9Xu6JxpV+FI+aF4016z/u1atcPq/P1DTqdOoae7U24E46PI+DMVsCfCHN2do6OWBzdS9vqf3Bq1bAxM4FKJZMalqbQmkq00N6+eU0FGlaV0gurgErJiPLiNHpZJfN7fiqnJNawwrYZJoMYtfF
 
eVErT8fG6WbjaGYHBPg6v1EWNdXa2Yeuz6w75+PgEshicHkfAhXiGCCDmEosJGaELCgnpiJJIByUK5YjBED++tDANtctoGq0uw4amGmxaX0vHFSRUhfqVJVhRlYeK0iwSSSaBeCoxJTQablwk40aTYvwvrta6DL9c7DF6eYsPeixtOPjqAbzw4v6hrp7OC+XV5QsfV8CJ2fsRIUQkISXURCpR6enl1b1g0eLP+d8KsQrlqEqjGtHr48ezMmhMFmWiqsyEylIjivNSKPBEJBu0UKoVD0Qy+djC6Oir7h4eA/R/mvw87FdXK13PbsyPHOnt7aAtyQmBQ4dfHe3p7by187ntOXTdPCKDcLZVwIFwI7yIQGLepCxomUQ50Ui0UTD/5+Pr925waOifFi6OuiaKlQ1JOOUYMU6CozGx8uHIqJjr/kFBJ11cXJ6ne7YSZmIpkUJoWxqXv2fp2n133/49d44de1OQOHr0CAIC/Meio6MhkUhA110jNhL21gLWEvaTGtmbmM0kFk3KRCKRRZQR9cQGoo3oIHppJPfTsY/oJtqJbUQLUUeUshVNIJSExMvLK9rT03P+upbGVd09nZfo9/XPJlM2/P390dnZKRAWFsZL8JT+OwG7SRLuxEzCn5VTOBHFRJREPKEn0ggTUcRWtoJRyr4zscwlEXHsXinLbDgbn37sWW7bdm2L9/Pzu+nu7o6NGzeitbWVshEAlokvCPsJARskXFlPeDORYJaRCCYjZuWlYNnREFqGhlCxczJ27WJ279xJgXsRHmyAOLJnnyTAQxkVjvPnz4evry94eWuBX5RgOEwSmU54ErOYzGxiDhHGpMKJCCvC2bkwFvBsFrQ3m3bTWeBO7Fl2jPUErKFy44/p1gK2ijgSzkzGnfBgQcxkAfkwfBk+DG9iJrvWg93ryoJ2nBy41bMPWQvQ7pk/LrMSeCQRe8JhkpATk3JhQblZ4crOOVsFLGwTrAOfDLv3AAErWq0FHldm
 
ktQEDlbYM+yseYTnLSOGCDD6H1/ARilrpuD/LyYuMoFDVgJPBqx3/p84YS3wpInonmQBxlOBpwJPBf4JszXhha5WvGwAAAAASUVORK5CYII=
+
+------=_Part_0_1330682067197--
+


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

Reply via email to