JAMES-1691 After sending a mail, move it from OUTBOX to SENT

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

Branch: refs/heads/master
Commit: a7d660195fc4bb3ac47337bf6c2cde65deafc284
Parents: 6d7e683
Author: Raphael Ouazana <[email protected]>
Authored: Mon Feb 22 17:08:55 2016 +0100
Committer: Raphael Ouazana <[email protected]>
Committed: Tue Mar 1 14:44:59 2016 +0100

----------------------------------------------------------------------
 .../modules/server/ActiveMQQueueModule.java     |  23 +-
 .../apache/james/jmap/send/MailMetadata.java    |  64 +++++
 .../org/apache/james/jmap/send/MailSpool.java   |   4 +-
 .../james/jmap/send/PostDequeueDecorator.java   | 159 ++++++++++++
 .../jmap/send/PostDequeueDecoratorFactory.java  |  51 ++++
 .../MailShouldBeInOutboxException.java          |  30 +++
 .../exception/MailboxRoleNotFoundException.java |  30 +++
 .../exception/MessageIdNotFoundException.java   |  30 +++
 .../james/jmap/send/MailMetadataTest.java       |  38 +++
 .../apache/james/jmap/send/MailSpoolTest.java   |   3 +-
 .../jmap/send/PostDequeueDecoratorTest.java     | 257 +++++++++++++++++++
 11 files changed, 674 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/a7d66019/server/container/cassandra-guice/src/main/java/org/apache/james/modules/server/ActiveMQQueueModule.java
----------------------------------------------------------------------
diff --git 
a/server/container/cassandra-guice/src/main/java/org/apache/james/modules/server/ActiveMQQueueModule.java
 
b/server/container/cassandra-guice/src/main/java/org/apache/james/modules/server/ActiveMQQueueModule.java
index 92d972c..e7602bb 100644
--- 
a/server/container/cassandra-guice/src/main/java/org/apache/james/modules/server/ActiveMQQueueModule.java
+++ 
b/server/container/cassandra-guice/src/main/java/org/apache/james/modules/server/ActiveMQQueueModule.java
@@ -19,16 +19,20 @@
 
 package org.apache.james.modules.server;
 
-import com.google.inject.AbstractModule;
-import com.google.inject.Provides;
-import com.google.inject.Singleton;
+import javax.jms.ConnectionFactory;
+
+import org.apache.james.jmap.send.PostDequeueDecoratorFactory;
+import org.apache.james.mailbox.cassandra.CassandraId;
 import org.apache.james.queue.activemq.ActiveMQMailQueueFactory;
-import org.apache.james.queue.api.MailQueueItemDecoratorFactory;
 import org.apache.james.queue.api.MailQueueFactory;
+import org.apache.james.queue.api.MailQueueItemDecoratorFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.jms.ConnectionFactory;
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+import com.google.inject.Singleton;
+import com.google.inject.TypeLiteral;
 
 public class ActiveMQQueueModule extends AbstractModule {
 
@@ -36,7 +40,7 @@ public class ActiveMQQueueModule extends AbstractModule {
 
     @Override
     protected void configure() {
-
+        bind(MailQueueItemDecoratorFactory.class).to(new 
TypeLiteral<PostDequeueDecoratorFactory<CassandraId>>(){}).in(Singleton.class);
     }
 
     @Provides
@@ -53,11 +57,4 @@ public class ActiveMQQueueModule extends AbstractModule {
         activeMQMailQueueFactory.init();
         return activeMQMailQueueFactory;
     }
-    
-    @Provides
-    @Singleton
-    public MailQueueItemDecoratorFactory 
defaultMailQueueItemDecoratorFactory() {
-        return MailQueueItemDecoratorFactory.RAW_FACTORY;
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/a7d66019/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/MailMetadata.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/MailMetadata.java
 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/MailMetadata.java
new file mode 100644
index 0000000..319ba21
--- /dev/null
+++ 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/MailMetadata.java
@@ -0,0 +1,64 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.jmap.send;
+
+import java.util.Objects;
+
+import org.apache.james.jmap.model.MessageId;
+
+import com.google.common.base.Preconditions;
+
+public class MailMetadata {
+    public static final String MAIL_METADATA_MESSAGE_ID_ATTRIBUTE = 
"org.apache.james.jmap.send.MailMetaData.messageId";
+    public static final String MAIL_METADATA_USERNAME_ATTRIBUTE = 
"org.apache.james.jmap.send.MailMetaData.username";
+
+    private final MessageId messageId;
+    private final String username;
+
+    public MailMetadata(MessageId messageId, String username) {
+        Preconditions.checkNotNull(messageId);
+        Preconditions.checkNotNull(username);
+        this.messageId = messageId;
+        this.username = username;
+    }
+
+    public MessageId getMessageId() {
+        return messageId;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof MailMetadata) {
+            MailMetadata other = (MailMetadata) obj;
+            return Objects.equals(this.messageId, other.messageId)
+                && Objects.equals(this.username, other.username);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(messageId, username);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/a7d66019/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/MailSpool.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/MailSpool.java 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/MailSpool.java
index 6267890..a5b686d 100644
--- 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/MailSpool.java
+++ 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/MailSpool.java
@@ -37,7 +37,9 @@ public class MailSpool {
         queue = queueFactory.getQueue(MailQueueFactory.SPOOL);
     }
 
-    public void send(Mail mail) throws MailQueueException {
+    public void send(Mail mail, MailMetadata metadata) throws 
MailQueueException {
+        mail.setAttribute(MailMetadata.MAIL_METADATA_MESSAGE_ID_ATTRIBUTE, 
metadata.getMessageId().serialize());
+        mail.setAttribute(MailMetadata.MAIL_METADATA_USERNAME_ATTRIBUTE, 
metadata.getUsername());
         queue.enQueue(mail);
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/a7d66019/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/PostDequeueDecorator.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/PostDequeueDecorator.java
 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/PostDequeueDecorator.java
new file mode 100644
index 0000000..6722ef7
--- /dev/null
+++ 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/PostDequeueDecorator.java
@@ -0,0 +1,159 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+package org.apache.james.jmap.send;
+
+import java.io.Serializable;
+import java.util.Iterator;
+
+import org.apache.james.jmap.model.MessageId;
+import org.apache.james.jmap.model.mailbox.Role;
+import org.apache.james.jmap.send.exception.MailShouldBeInOutboxException;
+import org.apache.james.jmap.send.exception.MailboxRoleNotFoundException;
+import org.apache.james.jmap.send.exception.MessageIdNotFoundException;
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MailboxMetaData;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.MailboxQuery;
+import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.store.mail.MailboxMapperFactory;
+import org.apache.james.mailbox.store.mail.MessageMapper;
+import org.apache.james.mailbox.store.mail.MessageMapperFactory;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+import org.apache.james.mailbox.store.mail.model.MailboxId;
+import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.queue.api.MailQueue.MailQueueException;
+import org.apache.james.queue.api.MailQueue.MailQueueItem;
+import 
org.apache.james.queue.api.MailQueueItemDecoratorFactory.MailQueueItemDecorator;
+import org.apache.mailet.Mail;
+import org.javatuples.Pair;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PostDequeueDecorator<Id extends MailboxId> extends 
MailQueueItemDecorator {
+    private static final Logger LOG = 
LoggerFactory.getLogger(PostDequeueDecorator.class);
+
+    private final MailboxManager mailboxManager;
+    private final MessageMapperFactory<Id> messageMapperFactory;
+    private final MailboxMapperFactory<Id> mailboxMapperFactory;
+
+    public PostDequeueDecorator(MailQueueItem mailQueueItem,
+            MailboxManager mailboxManager,
+            MessageMapperFactory<Id> messageMapperFactory,
+            MailboxMapperFactory<Id> mailboxMapperFactory) {
+        super(mailQueueItem);
+        this.mailboxManager = mailboxManager;
+        this.messageMapperFactory = messageMapperFactory;
+        this.mailboxMapperFactory = mailboxMapperFactory;
+    }
+
+    @Override
+    public Mail getMail() {
+        return mailQueueItem.getMail();
+    }
+
+    @Override
+    public void done(boolean success) throws MailQueueException {
+        mailQueueItem.done(success);
+        if (success && mandatoryJmapMetaDataIsPresent()) {
+            MessageId messageId = MessageId.of((String) 
getMail().getAttribute(MailMetadata.MAIL_METADATA_MESSAGE_ID_ATTRIBUTE));
+            String username = (String) 
getMail().getAttribute(MailMetadata.MAIL_METADATA_USERNAME_ATTRIBUTE);
+            try {
+                MailboxSession mailboxSession = 
mailboxManager.createSystemSession(username, LOG);
+                Pair<MailboxMessage<Id>, MailboxPath> 
mailboxMessageAndMailboxPath = getMailboxMessageAndMailboxPath(messageId, 
mailboxSession);
+                moveFromOutboxToSent(mailboxMessageAndMailboxPath, 
mailboxSession);
+            } catch (MailboxException e) {
+                throw new MailQueueException(e.getMessage(), e);
+            }
+        }
+    }
+
+    private boolean mandatoryJmapMetaDataIsPresent() {
+        return checkMessageIdAttribute()
+            && checkUsernameAttribute();
+    }
+
+    private boolean checkMessageIdAttribute() {
+        Serializable messageId = 
getMail().getAttribute(MailMetadata.MAIL_METADATA_MESSAGE_ID_ATTRIBUTE);
+        if (messageId == null || ! (messageId instanceof String)) {
+            return false;
+        }
+        try {
+            MessageId.of((String) messageId);
+        } catch (Exception e) {
+            LOG.error("Invalid messageId: " + (String) messageId);
+            return false;
+        }
+        return true;
+    }
+
+    private boolean checkUsernameAttribute() {
+        Serializable username = 
getMail().getAttribute(MailMetadata.MAIL_METADATA_USERNAME_ATTRIBUTE);
+        return (username != null && username instanceof String);
+    }
+
+    public Pair<MailboxMessage<Id>, MailboxPath> 
getMailboxMessageAndMailboxPath(MessageId messageId, MailboxSession 
mailboxSession) throws MailQueueException, MailboxException {
+        MailboxPath mailboxPath = messageId.getMailboxPath();
+        MessageMapper<Id> messageMapper = 
messageMapperFactory.getMessageMapper(mailboxSession);
+        Mailbox<Id> mailbox = 
mailboxMapperFactory.getMailboxMapper(mailboxSession).findMailboxByPath(mailboxPath);
+        Iterator<MailboxMessage<Id>> resultIterator = 
messageMapper.findInMailbox(mailbox, MessageRange.one(messageId.getUid()), 
MessageMapper.FetchType.Full, 1);
+        if (resultIterator.hasNext()) {
+            return Pair.with(resultIterator.next(), mailboxPath);
+        } else {
+            throw new MessageIdNotFoundException(messageId);
+        }
+    }
+
+    private void moveFromOutboxToSent(Pair<MailboxMessage<Id>, MailboxPath> 
mailboxMessageAndMailboxPath, MailboxSession mailboxSession) throws 
MailQueueException, MailboxException {
+        MailboxMessage<Id> mailboxMessage = 
mailboxMessageAndMailboxPath.getValue0();
+        MailboxPath outboxMailboxPath = 
mailboxMessageAndMailboxPath.getValue1();
+        ensureMailboxPathIsOutbox(outboxMailboxPath);
+        MailboxPath sentMailboxPath = getSentMailboxPath(mailboxSession);
+        
+        // MOVE is not implemented, so COPY and DELETE
+        mailboxManager.copyMessages(MessageRange.one(mailboxMessage.getUid()), 
outboxMailboxPath, sentMailboxPath, mailboxSession);
+        Mailbox<Id> outboxMailbox = 
mailboxMapperFactory.getMailboxMapper(mailboxSession).findMailboxByPath(outboxMailboxPath);
+        
messageMapperFactory.getMessageMapper(mailboxSession).delete(outboxMailbox, 
mailboxMessage);
+    }
+
+    private void ensureMailboxPathIsOutbox(MailboxPath outboxMailboxPath) 
throws MailShouldBeInOutboxException {
+        if (!hasRole(outboxMailboxPath, Role.OUTBOX)) {
+            throw new MailShouldBeInOutboxException(outboxMailboxPath);
+        }
+    }
+
+    private MailboxPath getSentMailboxPath(MailboxSession session) throws 
MailboxRoleNotFoundException, MailboxException {
+        MailboxQuery allUserMailboxesQuery = MailboxQuery.builder(session)
+            .privateUserMailboxes()
+            .build();
+        return mailboxManager.search(allUserMailboxesQuery, session)
+                .stream()
+                .map(MailboxMetaData::getPath)
+                .filter(path -> hasRole(path, Role.SENT))
+                .findFirst()
+                .orElseThrow(() -> new 
MailboxRoleNotFoundException(Role.SENT));
+    }
+    
+    private boolean hasRole(MailboxPath mailBoxPath, Role role) {
+        return Role.from(mailBoxPath.getName())
+                .map(role::equals)
+                .orElse(false);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/a7d66019/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/PostDequeueDecoratorFactory.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/PostDequeueDecoratorFactory.java
 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/PostDequeueDecoratorFactory.java
new file mode 100644
index 0000000..24797fc
--- /dev/null
+++ 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/PostDequeueDecoratorFactory.java
@@ -0,0 +1,51 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.jmap.send;
+
+import org.apache.james.queue.api.MailQueue.MailQueueItem;
+
+import javax.inject.Inject;
+
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.store.mail.MailboxMapperFactory;
+import org.apache.james.mailbox.store.mail.MessageMapperFactory;
+import org.apache.james.mailbox.store.mail.model.MailboxId;
+import org.apache.james.queue.api.MailQueueItemDecoratorFactory;
+
+public class PostDequeueDecoratorFactory<Id extends MailboxId> implements 
MailQueueItemDecoratorFactory {
+    private final MailboxManager mailboxManager;
+    private final MessageMapperFactory<Id> messageMapperFactory;
+    private final MailboxMapperFactory<Id> mailboxMapperFactory;
+
+    @Inject
+    public PostDequeueDecoratorFactory(MailboxManager mailboxManager,
+            MessageMapperFactory<Id> messageMapperFactory,
+            MailboxMapperFactory<Id> mailboxMapperFactory) {
+                this.mailboxManager = mailboxManager;
+                this.messageMapperFactory = messageMapperFactory;
+                this.mailboxMapperFactory = mailboxMapperFactory;
+    }
+
+    @Override
+    public MailQueueItemDecorator decorate(MailQueueItem mailQueueItem) {
+        return new PostDequeueDecorator<Id>(mailQueueItem, mailboxManager, 
messageMapperFactory, mailboxMapperFactory);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/a7d66019/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/exception/MailShouldBeInOutboxException.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/exception/MailShouldBeInOutboxException.java
 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/exception/MailShouldBeInOutboxException.java
new file mode 100644
index 0000000..f0e781b
--- /dev/null
+++ 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/exception/MailShouldBeInOutboxException.java
@@ -0,0 +1,30 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+package org.apache.james.jmap.send.exception;
+
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.queue.api.MailQueue.MailQueueException;
+
+public class MailShouldBeInOutboxException extends MailQueueException {
+
+    public MailShouldBeInOutboxException(MailboxPath mailboxPath) {
+        super("Mail to be sent should be in OUTBOX but is in " + 
mailboxPath.getName());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/a7d66019/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/exception/MailboxRoleNotFoundException.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/exception/MailboxRoleNotFoundException.java
 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/exception/MailboxRoleNotFoundException.java
new file mode 100644
index 0000000..39d73e1
--- /dev/null
+++ 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/exception/MailboxRoleNotFoundException.java
@@ -0,0 +1,30 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+package org.apache.james.jmap.send.exception;
+
+import org.apache.james.jmap.model.mailbox.Role;
+import org.apache.james.queue.api.MailQueue.MailQueueException;
+
+public class MailboxRoleNotFoundException extends MailQueueException {
+
+    public MailboxRoleNotFoundException(Role role) {
+        super("Unable to find a mailbox with role " + role.name());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/a7d66019/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/exception/MessageIdNotFoundException.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/exception/MessageIdNotFoundException.java
 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/exception/MessageIdNotFoundException.java
new file mode 100644
index 0000000..0db7817
--- /dev/null
+++ 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/send/exception/MessageIdNotFoundException.java
@@ -0,0 +1,30 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+package org.apache.james.jmap.send.exception;
+
+import org.apache.james.jmap.model.MessageId;
+import org.apache.james.queue.api.MailQueue.MailQueueException;
+
+public class MessageIdNotFoundException extends MailQueueException {
+
+    public MessageIdNotFoundException(MessageId messageId) {
+        super("Unable to find a Mailbox Message matching: " + 
messageId.serialize());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/a7d66019/server/protocols/jmap/src/test/java/org/apache/james/jmap/send/MailMetadataTest.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap/src/test/java/org/apache/james/jmap/send/MailMetadataTest.java
 
b/server/protocols/jmap/src/test/java/org/apache/james/jmap/send/MailMetadataTest.java
new file mode 100644
index 0000000..b080077
--- /dev/null
+++ 
b/server/protocols/jmap/src/test/java/org/apache/james/jmap/send/MailMetadataTest.java
@@ -0,0 +1,38 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+package org.apache.james.jmap.send;
+
+import org.apache.james.jmap.model.MessageId;
+import org.junit.Test;
+
+public class MailMetadataTest {
+
+    private static final MessageId MESSAGE_ID = 
MessageId.of("username|path|0");
+    private static final String USERNAME = "username";
+
+    @Test(expected=NullPointerException.class)
+    public void constructorShouldThrowWhenNullMessageId() {
+        new MailMetadata(null, USERNAME);
+    }
+
+    @Test(expected=NullPointerException.class)
+    public void constructorShouldThrowWhenNullUsername() {
+        new MailMetadata(MESSAGE_ID, null);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/a7d66019/server/protocols/jmap/src/test/java/org/apache/james/jmap/send/MailSpoolTest.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap/src/test/java/org/apache/james/jmap/send/MailSpoolTest.java
 
b/server/protocols/jmap/src/test/java/org/apache/james/jmap/send/MailSpoolTest.java
index 3687138..667e0ee 100644
--- 
a/server/protocols/jmap/src/test/java/org/apache/james/jmap/send/MailSpoolTest.java
+++ 
b/server/protocols/jmap/src/test/java/org/apache/james/jmap/send/MailSpoolTest.java
@@ -24,6 +24,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.TimeUnit;
 
+import org.apache.james.jmap.model.MessageId;
 import org.apache.james.queue.api.MailQueue;
 import org.apache.james.queue.api.MailQueue.MailQueueException;
 import org.apache.james.queue.api.MailQueue.MailQueueItem;
@@ -55,7 +56,7 @@ public class MailSpoolTest {
     public void sendShouldEnQueueTheMail() throws Exception {
         FakeMail mail = new FakeMail();
 
-        mailSpool.send(mail);
+        mailSpool.send(mail, new MailMetadata(MessageId.of("a|b|1"), "user"));
 
         assertThat(myQueue.deQueue())
             .isNotNull()

http://git-wip-us.apache.org/repos/asf/james-project/blob/a7d66019/server/protocols/jmap/src/test/java/org/apache/james/jmap/send/PostDequeueDecoratorTest.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap/src/test/java/org/apache/james/jmap/send/PostDequeueDecoratorTest.java
 
b/server/protocols/jmap/src/test/java/org/apache/james/jmap/send/PostDequeueDecoratorTest.java
new file mode 100644
index 0000000..fff82f1
--- /dev/null
+++ 
b/server/protocols/jmap/src/test/java/org/apache/james/jmap/send/PostDequeueDecoratorTest.java
@@ -0,0 +1,257 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+package org.apache.james.jmap.send;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayInputStream;
+import java.util.Date;
+import java.util.Iterator;
+
+import javax.mail.Flags;
+
+import org.apache.james.jmap.model.MessageId;
+import org.apache.james.jmap.send.exception.MailShouldBeInOutboxException;
+import org.apache.james.jmap.send.exception.MailboxRoleNotFoundException;
+import org.apache.james.jmap.send.exception.MessageIdNotFoundException;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageManager;
+import org.apache.james.mailbox.acl.GroupMembershipResolver;
+import org.apache.james.mailbox.acl.MailboxACLResolver;
+import org.apache.james.mailbox.acl.SimpleGroupMembershipResolver;
+import org.apache.james.mailbox.acl.UnionMailboxACLResolver;
+import org.apache.james.mailbox.inmemory.InMemoryId;
+import org.apache.james.mailbox.inmemory.InMemoryMailboxSessionMapperFactory;
+import org.apache.james.mailbox.model.MailboxConstants;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.store.MockAuthenticator;
+import org.apache.james.mailbox.store.StoreMailboxManager;
+import org.apache.james.mailbox.store.mail.MessageMapper;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.queue.api.MailQueue.MailQueueItem;
+import org.apache.mailet.Mail;
+import org.apache.mailet.base.test.FakeMail;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PostDequeueDecoratorTest {
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(PostDequeueDecoratorTest.class);
+    private static final String OUTBOX = "OUTBOX";
+    private static final String SENT = "SENT";
+    private static final String USERNAME = "[email protected]";
+    private static final long UID = 1;
+    private static final MailboxPath OUTBOX_MAILBOX_PATH = new 
MailboxPath(MailboxConstants.USER_NAMESPACE, USERNAME, OUTBOX);
+    private static final MailboxPath SENT_MAILBOX_PATH = new 
MailboxPath(MailboxConstants.USER_NAMESPACE, USERNAME, SENT);
+    private static final String MESSAGE_ID = USERNAME + "|" + 
OUTBOX_MAILBOX_PATH.getName() + "|" + UID;
+    
+    private InMemoryMailboxSessionMapperFactory mailboxSessionMapperFactory;
+    private StoreMailboxManager<InMemoryId> mailboxManager;
+    private MailQueueItem mockedMailQueueItem;
+    private Mail mail;
+    private PostDequeueDecorator<InMemoryId> testee;
+
+    @Before
+    public void init() throws Exception {
+        mailboxSessionMapperFactory = new 
InMemoryMailboxSessionMapperFactory();
+        MailboxACLResolver aclResolver = new UnionMailboxACLResolver();
+        GroupMembershipResolver groupMembershipResolver = new 
SimpleGroupMembershipResolver();
+        mailboxManager = new 
StoreMailboxManager<>(mailboxSessionMapperFactory, new MockAuthenticator(), 
aclResolver, groupMembershipResolver);
+        mailboxManager.init();
+
+        mockedMailQueueItem = mock(MailQueueItem.class);
+        mail = new FakeMail();
+        when(mockedMailQueueItem.getMail()).thenReturn(mail);
+        testee = new PostDequeueDecorator<InMemoryId>(mockedMailQueueItem, 
mailboxManager, mailboxSessionMapperFactory, mailboxSessionMapperFactory);
+    }
+    
+    @Test
+    public void doneShouldCallDecoratedDone() throws Exception {
+        try {
+            testee.done(true);
+        } catch (Exception e) {
+            //Ignore
+        }
+
+        verify(mockedMailQueueItem).done(true);
+    }
+    
+    @Test(expected=MessageIdNotFoundException.class)
+    public void doneShouldThrowWhenMetadataHasNotAnExistingMessageId() throws 
Exception {
+        MailboxSession mailboxSession = 
mailboxManager.createSystemSession(USERNAME, LOGGER);
+        mailboxManager.createMailbox(OUTBOX_MAILBOX_PATH, mailboxSession);
+        mail.setAttribute(MailMetadata.MAIL_METADATA_MESSAGE_ID_ATTRIBUTE, 
MESSAGE_ID);
+        mail.setAttribute(MailMetadata.MAIL_METADATA_USERNAME_ATTRIBUTE, 
USERNAME);
+
+        testee.done(true);
+    }
+    
+    @Test(expected=MailShouldBeInOutboxException.class)
+    public void doneShouldThrowWhenMessageIsNotInOutbox() throws Exception {
+        MailboxSession mailboxSession = 
mailboxManager.createSystemSession(USERNAME, LOGGER);
+        mailboxManager.createMailbox(SENT_MAILBOX_PATH, mailboxSession);
+        MessageManager messageManager = 
mailboxManager.getMailbox(SENT_MAILBOX_PATH, mailboxSession);
+        messageManager.appendMessage(new ByteArrayInputStream("Subject: 
test\r\n\r\ntestmail".getBytes()), new Date(), mailboxSession, false, new 
Flags());
+        MessageId inSentMessageId = MessageId.of(USERNAME + "|" + 
SENT_MAILBOX_PATH.getName() + "|" + UID);
+        mail.setAttribute(MailMetadata.MAIL_METADATA_MESSAGE_ID_ATTRIBUTE, 
inSentMessageId.serialize());
+        mail.setAttribute(MailMetadata.MAIL_METADATA_USERNAME_ATTRIBUTE, 
USERNAME);
+        
+        testee.done(true);
+    }
+    
+    @Test(expected=MailboxRoleNotFoundException.class)
+    public void doneShouldThrowWhenSentDoesNotExist() throws Exception {
+        MailboxSession mailboxSession = 
mailboxManager.createSystemSession(USERNAME, LOGGER);
+        mailboxManager.createMailbox(OUTBOX_MAILBOX_PATH, mailboxSession);
+        MessageManager messageManager = 
mailboxManager.getMailbox(OUTBOX_MAILBOX_PATH, mailboxSession);
+        messageManager.appendMessage(new ByteArrayInputStream("Subject: 
test\r\n\r\ntestmail".getBytes()), new Date(), mailboxSession, false, new 
Flags());
+        mail.setAttribute(MailMetadata.MAIL_METADATA_MESSAGE_ID_ATTRIBUTE, 
MESSAGE_ID);
+        mail.setAttribute(MailMetadata.MAIL_METADATA_USERNAME_ATTRIBUTE, 
USERNAME);
+
+        testee.done(true);
+    }
+    
+    @Test
+    public void doneShouldCopyMailFromOutboxToSentWhenSuccess() throws 
Exception {
+        MailboxSession mailboxSession = 
mailboxManager.createSystemSession(USERNAME, LOGGER);
+        mailboxManager.createMailbox(OUTBOX_MAILBOX_PATH, mailboxSession);
+        mailboxManager.createMailbox(SENT_MAILBOX_PATH, mailboxSession);
+        MessageManager messageManager = 
mailboxManager.getMailbox(OUTBOX_MAILBOX_PATH, mailboxSession);
+        messageManager.appendMessage(new ByteArrayInputStream("Subject: 
test\r\n\r\ntestmail".getBytes()), new Date(), mailboxSession, false, new 
Flags());
+        mail.setAttribute(MailMetadata.MAIL_METADATA_MESSAGE_ID_ATTRIBUTE, 
MESSAGE_ID);
+        mail.setAttribute(MailMetadata.MAIL_METADATA_USERNAME_ATTRIBUTE, 
USERNAME);
+        
+        testee.done(true);
+        
+        Mailbox<InMemoryId> sentMailbox = 
mailboxSessionMapperFactory.getMailboxMapper(mailboxSession).findMailboxByPath(SENT_MAILBOX_PATH);
+        MessageMapper<InMemoryId> messageMapper = 
mailboxSessionMapperFactory.getMessageMapper(mailboxSession);
+        Iterator<MailboxMessage<InMemoryId>> resultIterator = 
messageMapper.findInMailbox(sentMailbox, MessageRange.one(UID), 
MessageMapper.FetchType.Full, 1);
+        assertThat(resultIterator).hasSize(1);
+    }
+    
+    @Test
+    public void doneShouldDeleteMailFromOutboxWhenSuccess() throws Exception {
+        MailboxSession mailboxSession = 
mailboxManager.createSystemSession(USERNAME, LOGGER);
+        mailboxManager.createMailbox(OUTBOX_MAILBOX_PATH, mailboxSession);
+        mailboxManager.createMailbox(SENT_MAILBOX_PATH, mailboxSession);
+        MessageManager messageManager = 
mailboxManager.getMailbox(OUTBOX_MAILBOX_PATH, mailboxSession);
+        messageManager.appendMessage(new ByteArrayInputStream("Subject: 
test\r\n\r\ntestmail".getBytes()), new Date(), mailboxSession, false, new 
Flags());
+        mail.setAttribute(MailMetadata.MAIL_METADATA_MESSAGE_ID_ATTRIBUTE, 
MESSAGE_ID);
+        mail.setAttribute(MailMetadata.MAIL_METADATA_USERNAME_ATTRIBUTE, 
USERNAME);
+        
+        testee.done(true);
+        
+        Mailbox<InMemoryId> mailbox = 
mailboxSessionMapperFactory.getMailboxMapper(mailboxSession).findMailboxByPath(OUTBOX_MAILBOX_PATH);
+        MessageMapper<InMemoryId> messageMapper = 
mailboxSessionMapperFactory.getMessageMapper(mailboxSession);
+        Iterator<MailboxMessage<InMemoryId>> resultIterator = 
messageMapper.findInMailbox(mailbox, MessageRange.one(UID), 
MessageMapper.FetchType.Full, 1);
+        assertThat(resultIterator).hasSize(0);
+    }
+    
+    @Test
+    public void doneShouldNotMoveMailFromOutboxToSentWhenSuccessIsFalse() 
throws Exception {
+        MailboxSession mailboxSession = 
mailboxManager.createSystemSession(USERNAME, LOGGER);
+        mailboxManager.createMailbox(OUTBOX_MAILBOX_PATH, mailboxSession);
+        mailboxManager.createMailbox(SENT_MAILBOX_PATH, mailboxSession);
+        MessageManager messageManager = 
mailboxManager.getMailbox(OUTBOX_MAILBOX_PATH, mailboxSession);
+        messageManager.appendMessage(new ByteArrayInputStream("Subject: 
test\r\n\r\ntestmail".getBytes()), new Date(), mailboxSession, false, new 
Flags());
+        mail.setAttribute(MailMetadata.MAIL_METADATA_MESSAGE_ID_ATTRIBUTE, 
MESSAGE_ID);
+        mail.setAttribute(MailMetadata.MAIL_METADATA_USERNAME_ATTRIBUTE, 
USERNAME);
+        
+        testee.done(false);
+        
+        Mailbox<InMemoryId> mailbox = 
mailboxSessionMapperFactory.getMailboxMapper(mailboxSession).findMailboxByPath(OUTBOX_MAILBOX_PATH);
+        MessageMapper<InMemoryId> messageMapper = 
mailboxSessionMapperFactory.getMessageMapper(mailboxSession);
+        Iterator<MailboxMessage<InMemoryId>> resultIterator = 
messageMapper.findInMailbox(mailbox, MessageRange.one(UID), 
MessageMapper.FetchType.Full, 1);
+        assertThat(resultIterator).hasSize(1);
+    }
+    
+    @Test
+    public void doneShouldNotMoveMailFromOutboxToSentWhenNoMetadataProvided() 
throws Exception {
+        MailboxSession mailboxSession = 
mailboxManager.createSystemSession(USERNAME, LOGGER);
+        mailboxManager.createMailbox(OUTBOX_MAILBOX_PATH, mailboxSession);
+        mailboxManager.createMailbox(SENT_MAILBOX_PATH, mailboxSession);
+        MessageManager messageManager = 
mailboxManager.getMailbox(OUTBOX_MAILBOX_PATH, mailboxSession);
+        messageManager.appendMessage(new ByteArrayInputStream("Subject: 
test\r\n\r\ntestmail".getBytes()), new Date(), mailboxSession, false, new 
Flags());
+        
+        testee.done(true);
+        
+        Mailbox<InMemoryId> mailbox = 
mailboxSessionMapperFactory.getMailboxMapper(mailboxSession).findMailboxByPath(OUTBOX_MAILBOX_PATH);
+        MessageMapper<InMemoryId> messageMapper = 
mailboxSessionMapperFactory.getMessageMapper(mailboxSession);
+        Iterator<MailboxMessage<InMemoryId>> resultIterator = 
messageMapper.findInMailbox(mailbox, MessageRange.one(UID), 
MessageMapper.FetchType.Full, 1);
+        assertThat(resultIterator).hasSize(1);
+    }
+    
+    @Test
+    public void doneShouldNotMoveMailFromOutboxToSentWhenUsernameNotProvided() 
throws Exception {
+        MailboxSession mailboxSession = 
mailboxManager.createSystemSession(USERNAME, LOGGER);
+        mailboxManager.createMailbox(OUTBOX_MAILBOX_PATH, mailboxSession);
+        mailboxManager.createMailbox(SENT_MAILBOX_PATH, mailboxSession);
+        MessageManager messageManager = 
mailboxManager.getMailbox(OUTBOX_MAILBOX_PATH, mailboxSession);
+        messageManager.appendMessage(new ByteArrayInputStream("Subject: 
test\r\n\r\ntestmail".getBytes()), new Date(), mailboxSession, false, new 
Flags());
+        mail.setAttribute(MailMetadata.MAIL_METADATA_MESSAGE_ID_ATTRIBUTE, 
MESSAGE_ID);
+        
+        testee.done(true);
+        
+        Mailbox<InMemoryId> mailbox = 
mailboxSessionMapperFactory.getMailboxMapper(mailboxSession).findMailboxByPath(OUTBOX_MAILBOX_PATH);
+        MessageMapper<InMemoryId> messageMapper = 
mailboxSessionMapperFactory.getMessageMapper(mailboxSession);
+        Iterator<MailboxMessage<InMemoryId>> resultIterator = 
messageMapper.findInMailbox(mailbox, MessageRange.one(UID), 
MessageMapper.FetchType.Full, 1);
+        assertThat(resultIterator).hasSize(1);
+    }
+    
+    @Test
+    public void 
doneShouldNotMoveMailFromOutboxToSentWhenMessageIdNotProvided() throws 
Exception {
+        MailboxSession mailboxSession = 
mailboxManager.createSystemSession(USERNAME, LOGGER);
+        mailboxManager.createMailbox(OUTBOX_MAILBOX_PATH, mailboxSession);
+        mailboxManager.createMailbox(SENT_MAILBOX_PATH, mailboxSession);
+        MessageManager messageManager = 
mailboxManager.getMailbox(OUTBOX_MAILBOX_PATH, mailboxSession);
+        messageManager.appendMessage(new ByteArrayInputStream("Subject: 
test\r\n\r\ntestmail".getBytes()), new Date(), mailboxSession, false, new 
Flags());
+        mail.setAttribute(MailMetadata.MAIL_METADATA_USERNAME_ATTRIBUTE, 
USERNAME);
+        
+        testee.done(true);
+        
+        Mailbox<InMemoryId> mailbox = 
mailboxSessionMapperFactory.getMailboxMapper(mailboxSession).findMailboxByPath(OUTBOX_MAILBOX_PATH);
+        MessageMapper<InMemoryId> messageMapper = 
mailboxSessionMapperFactory.getMessageMapper(mailboxSession);
+        Iterator<MailboxMessage<InMemoryId>> resultIterator = 
messageMapper.findInMailbox(mailbox, MessageRange.one(UID), 
MessageMapper.FetchType.Full, 1);
+        assertThat(resultIterator).hasSize(1);
+    }
+    
+    @Test
+    public void 
doneShouldNotMoveMailFromOutboxToSentWhenInvalidMessageIdProvided() throws 
Exception {
+        MailboxSession mailboxSession = 
mailboxManager.createSystemSession(USERNAME, LOGGER);
+        mailboxManager.createMailbox(OUTBOX_MAILBOX_PATH, mailboxSession);
+        mailboxManager.createMailbox(SENT_MAILBOX_PATH, mailboxSession);
+        MessageManager messageManager = 
mailboxManager.getMailbox(OUTBOX_MAILBOX_PATH, mailboxSession);
+        messageManager.appendMessage(new ByteArrayInputStream("Subject: 
test\r\n\r\ntestmail".getBytes()), new Date(), mailboxSession, false, new 
Flags());
+        mail.setAttribute(MailMetadata.MAIL_METADATA_USERNAME_ATTRIBUTE, 
USERNAME);
+        mail.setAttribute(MailMetadata.MAIL_METADATA_MESSAGE_ID_ATTRIBUTE, 
"invalid");
+        
+        testee.done(true);
+        
+        Mailbox<InMemoryId> mailbox = 
mailboxSessionMapperFactory.getMailboxMapper(mailboxSession).findMailboxByPath(OUTBOX_MAILBOX_PATH);
+        MessageMapper<InMemoryId> messageMapper = 
mailboxSessionMapperFactory.getMessageMapper(mailboxSession);
+        Iterator<MailboxMessage<InMemoryId>> resultIterator = 
messageMapper.findInMailbox(mailbox, MessageRange.one(UID), 
MessageMapper.FetchType.Full, 1);
+        assertThat(resultIterator).hasSize(1);
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to