http://git-wip-us.apache.org/repos/asf/james-project/blob/3dddd7c5/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMail.java
----------------------------------------------------------------------
diff --git 
a/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMail.java 
b/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMail.java
new file mode 100644
index 0000000..6791a1f
--- /dev/null
+++ b/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMail.java
@@ -0,0 +1,464 @@
+/****************************************************************
+ * 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.mailet.base.test;
+
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.AddressException;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.james.core.MailAddress;
+import org.apache.james.core.builder.MimeMessageBuilder;
+import org.apache.james.util.MimeMessageUtil;
+import org.apache.mailet.Mail;
+import org.apache.mailet.PerRecipientHeaders;
+import org.apache.mailet.PerRecipientHeaders.Header;
+
+import com.github.fge.lambdas.Throwing;
+import com.github.steveash.guavate.Guavate;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+public class FakeMail implements Mail, Serializable {
+
+    private static final String DEFAULT_REMOTE_HOST = "111.222.333.444";
+    public static final String DEFAULT_REMOTE_ADDRESS = "127.0.0.1";
+
+    public static FakeMail fromMessage(MimeMessageBuilder message) throws 
MessagingException {
+        return FakeMail.builder()
+            .mimeMessage(message)
+            .build();
+    }
+
+    public static FakeMail fromMime(String text, String javaEncodingCharset, 
String javamailDefaultEncodingCharset) throws MessagingException, 
UnsupportedEncodingException {
+        Properties javamailProperties = new Properties();
+        javamailProperties.setProperty("mail.mime.charset", 
javamailDefaultEncodingCharset);
+        return FakeMail.builder()
+                
.mimeMessage(MimeMessageUtil.mimeMessageFromBytes((text.getBytes(javaEncodingCharset))))
+                .build();
+    }
+
+    public static FakeMail fromMail(Mail mail) throws MessagingException {
+        return new FakeMail(mail.getMessage(),
+            Lists.newArrayList(mail.getRecipients()),
+            mail.getName(),
+            mail.getSender(),
+            mail.getState(),
+            mail.getErrorMessage(),
+            mail.getLastUpdated(),
+            attributes(mail),
+            mail.getMessageSize(),
+            mail.getRemoteAddr(),
+            mail.getRemoteHost(),
+            mail.getPerRecipientSpecificHeaders());
+    }
+
+    public static FakeMail from(MimeMessage message) throws MessagingException 
{
+        return builder()
+                .mimeMessage(message)
+                .build();
+    }
+
+    public static FakeMail from(MimeMessageBuilder message) throws 
MessagingException {
+        return from(message.build());
+    }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static class Builder {
+
+        private Optional<String> fileName;
+        private Optional<MimeMessage> mimeMessage;
+        private List<MailAddress> recipients;
+        private Optional<String> name;
+        private Optional<MailAddress> sender;
+        private Optional<String> state;
+        private Optional<String> errorMessage;
+        private Optional<Date> lastUpdated;
+        private Map<String, Serializable> attributes;
+        private Optional<Long> size;
+        private Optional<String> remoteAddr;
+        private Optional<String> remoteHost;
+        private PerRecipientHeaders perRecipientHeaders;
+
+        private Builder() {
+            fileName = Optional.empty();
+            mimeMessage = Optional.empty();
+            recipients = Lists.newArrayList();
+            name = Optional.empty();
+            sender = Optional.empty();
+            state = Optional.empty();
+            errorMessage = Optional.empty();
+            lastUpdated = Optional.empty();
+            attributes = Maps.newHashMap();
+            size = Optional.empty();
+            remoteAddr = Optional.empty();
+            remoteHost = Optional.empty();
+            perRecipientHeaders = new PerRecipientHeaders();
+        }
+
+        public Builder size(long size) {
+            this.size = Optional.of(size);
+            return this;
+        }
+
+        public Builder fileName(String fileName) {
+            this.fileName = Optional.of(fileName);
+            return this;
+        }
+
+        public Builder mimeMessage(MimeMessage mimeMessage) {
+            this.mimeMessage = Optional.of(mimeMessage);
+            return this;
+        }
+
+        public Builder mimeMessage(MimeMessageBuilder mimeMessage) throws 
MessagingException {
+            this.mimeMessage = Optional.of(mimeMessage.build());
+            return this;
+        }
+
+        public Builder recipients() {
+            return this;
+        }
+
+        public Builder recipients(List<MailAddress> recipients) {
+            this.recipients.addAll(recipients);
+            return this;
+        }
+
+        public Builder recipients(MailAddress... recipients) {
+            return recipients(ImmutableList.copyOf(recipients));
+        }
+
+        public Builder recipients(String... recipients) {
+            return recipients(Arrays.stream(recipients)
+                .map(Throwing.function(MailAddress::new))
+                .collect(Guavate.toImmutableList()));
+        }
+
+        public Builder recipient(MailAddress recipient) {
+            return recipients(recipient);
+        }
+
+        public Builder recipient(String recipient) throws AddressException {
+            return recipients(recipient);
+        }
+
+        public Builder name(String name) {
+            this.name = Optional.of(name);
+            return this;
+        }
+
+        public Builder sender(MailAddress sender) {
+            this.sender = Optional.of(sender);
+            return this;
+        }
+
+        public Builder sender(String sender) throws AddressException {
+            return sender(new MailAddress(sender));
+        }
+
+        public Builder state(String state) {
+            this.state = Optional.of(state);
+            return this;
+        }
+
+        public Builder errorMessage(String errorMessage) {
+            this.errorMessage = Optional.of(errorMessage);
+            return this;
+        }
+
+        public Builder lastUpdated(Date lastUpdated) {
+            this.lastUpdated = Optional.of(lastUpdated);
+            return this;
+        }
+
+        public Builder attribute(String name, Serializable object) {
+            this.attributes.put(name, object);
+            return this;
+        }
+
+        public Builder attributes(Map<String, Serializable> attributes) {
+            this.attributes.putAll(attributes);
+            return this;
+        }
+
+        public Builder remoteAddr(String remoteAddr) {
+            this.remoteAddr = Optional.of(remoteAddr);
+            return this;
+        }
+
+        public Builder remoteHost(String remoteHost) {
+            this.remoteHost = Optional.of(remoteHost);
+            return this;
+        }
+
+        public Builder addHeaderForRecipient(Header header, MailAddress 
recipient) {
+            this.perRecipientHeaders.addHeaderForRecipient(header, recipient);
+            return this;
+        }
+
+        public FakeMail build() throws MessagingException {
+            return new FakeMail(getMimeMessage(), recipients, 
name.orElse(null), sender.orElse(null), state.orElse(null), 
errorMessage.orElse(null), lastUpdated.orElse(null),
+                attributes, size.orElse(0L), 
remoteAddr.orElse(DEFAULT_REMOTE_ADDRESS), 
remoteHost.orElse(DEFAULT_REMOTE_HOST), perRecipientHeaders);
+        }
+
+        private MimeMessage getMimeMessage() throws MessagingException {
+            Preconditions.checkState(!(fileName.isPresent() && 
mimeMessage.isPresent()), "You can not specify a MimeMessage object when you 
alredy set Content from a file");
+            if (fileName.isPresent()) {
+                return 
MimeMessageUtil.mimeMessageFromStream(ClassLoader.getSystemResourceAsStream(fileName.get()));
+            }
+            return mimeMessage.orElse(null);
+        }
+    }
+
+    public static FakeMail defaultFakeMail() throws MessagingException {
+        return FakeMail.builder().build();
+    }
+
+    private static Map<String, Serializable> attributes(Mail mail) {
+        ImmutableMap.Builder<String, Serializable> builder = 
ImmutableMap.builder();
+        for (String attributeName: 
ImmutableList.copyOf(mail.getAttributeNames())) {
+            builder.put(attributeName, mail.getAttribute(attributeName));
+        }
+        return builder.build();
+    }
+
+    private transient MimeMessage msg;
+    private Collection<MailAddress> recipients;
+    private String name;
+    private MailAddress sender;
+    private String state;
+    private String errorMessage;
+    private Date lastUpdated;
+    private Map<String, Serializable> attributes;
+    private long size;
+    private String remoteAddr;
+    private String remoteHost;
+    private PerRecipientHeaders perRecipientHeaders;
+    
+    public FakeMail(MimeMessage msg, List<MailAddress> recipients, String 
name, MailAddress sender, String state, String errorMessage, Date lastUpdated,
+            Map<String, Serializable> attributes, long size, String 
remoteAddr, String remoteHost, PerRecipientHeaders perRecipientHeaders) {
+        this.msg = msg;
+        this.recipients = recipients;
+        this.name = name;
+        this.sender = sender;
+        this.state = state;
+        this.errorMessage = errorMessage;
+        this.lastUpdated = lastUpdated;
+        this.attributes = attributes;
+        this.size = size;
+        this.remoteAddr = remoteAddr;
+        this.perRecipientHeaders = perRecipientHeaders;
+        this.remoteHost = remoteHost;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public void setName(String newName) {
+        this.name = newName;
+    }
+
+    @Override
+    public MimeMessage getMessage() throws MessagingException {
+        return msg;
+    }
+
+    @Override
+    public Collection<MailAddress> getRecipients() {
+        return recipients;
+    }
+
+    @Override
+    public void setRecipients(Collection<MailAddress> recipients) {
+        this.recipients = recipients;
+    }
+
+    @Override
+    public MailAddress getSender() {
+        return sender;
+    }
+
+    @Override
+    public String getState() {
+        return state;
+    }
+
+    @Override
+    public String getRemoteHost() {
+        return remoteHost;
+    }
+
+    @Override
+    public String getRemoteAddr() {
+        return remoteAddr;
+    }
+
+    @Override
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+
+    @Override
+    public void setErrorMessage(String msg) {
+        this.errorMessage = msg;
+    }
+
+    @Override
+    public void setMessage(MimeMessage message) {
+        this.msg = message;
+        try {
+            if (message != null && message.getSender() != null) {
+                this.sender = new MailAddress((InternetAddress) 
message.getSender());
+            }
+        } catch (MessagingException e) {
+            throw new RuntimeException("Exception caught", e);
+        }
+    }
+
+    @Override
+    public void setState(String state) {
+        this.state = state;
+    }
+
+    @Override
+    public Serializable getAttribute(String name) {
+        return attributes.get(name);
+    }
+
+    @Override
+    public Iterator<String> getAttributeNames() {
+        return attributes.keySet().iterator();
+    }
+
+    @Override
+    public boolean hasAttributes() {
+        return !attributes.isEmpty();
+    }
+
+    @Override
+    public Serializable removeAttribute(String name) {
+        return attributes.remove(name);
+
+    }
+
+    @Override
+    public void removeAllAttributes() {
+        attributes.clear();
+    }
+
+    @Override
+    public Serializable setAttribute(String name, Serializable object) {
+        return attributes.put(name, object);
+    }
+
+    @Override
+    public long getMessageSize() throws MessagingException {
+        return size;
+    }
+
+    @Override
+    public Date getLastUpdated() {
+        return lastUpdated;
+    }
+
+    @Override
+    public void setLastUpdated(Date lastUpdated) {
+        this.lastUpdated = lastUpdated;
+    }
+
+    public void setMessageSize(long size) {
+        this.size = size;
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof FakeMail) {
+            FakeMail that = (FakeMail) o;
+
+            return Objects.equal(this.size, that.size)
+                && Objects.equal(this.recipients, that.recipients)
+                && Objects.equal(this.name, that.name)
+                && Objects.equal(this.sender, that.sender)
+                && Objects.equal(this.state, that.state)
+                && Objects.equal(this.errorMessage, that.errorMessage)
+                && Objects.equal(this.lastUpdated, that.lastUpdated)
+                && Objects.equal(this.attributes, that.attributes)
+                && Objects.equal(this.remoteHost, that.remoteHost)
+                && Objects.equal(this.perRecipientHeaders, 
that.perRecipientHeaders)
+                && Objects.equal(this.remoteAddr, that.remoteAddr);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hashCode(name, sender, recipients, state, errorMessage, 
lastUpdated, attributes, size, remoteAddr, remoteHost, perRecipientHeaders);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+            .add("msg", msg)
+            .add("recipients", recipients)
+            .add("name", name)
+            .add("sender", sender)
+            .add("state", state)
+            .add("errorMessage", errorMessage)
+            .add("lastUpdated", lastUpdated)
+            .add("attributes", attributes)
+            .add("size", size)
+            .add("remoteAddr", remoteAddr)
+            .toString();
+    }
+
+    @Override
+    public PerRecipientHeaders getPerRecipientSpecificHeaders() {
+        return perRecipientHeaders;
+    }
+
+    @Override
+    public void addSpecificHeaderForRecipient(Header header, MailAddress 
recipient) {
+        perRecipientHeaders.addHeaderForRecipient(header, recipient);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3dddd7c5/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMailContext.java
----------------------------------------------------------------------
diff --git 
a/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMailContext.java 
b/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMailContext.java
new file mode 100644
index 0000000..eff41c9
--- /dev/null
+++ b/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMailContext.java
@@ -0,0 +1,608 @@
+/****************************************************************
+ * 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.mailet.base.test;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.TimeUnit;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.AddressException;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.james.core.Domain;
+import org.apache.james.core.MailAddress;
+import org.apache.james.core.builder.MimeMessageWrapper;
+import org.apache.mailet.HostAddress;
+import org.apache.mailet.LookupException;
+import org.apache.mailet.Mail;
+import org.apache.mailet.MailetContext;
+import org.slf4j.Logger;
+
+import com.github.fge.lambdas.Throwing;
+import com.github.fge.lambdas.functions.ThrowingFunction;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+
+@SuppressWarnings("deprecation")
+public class FakeMailContext implements MailetContext {
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static SentMail.Builder sentMailBuilder() {
+        return new SentMail.Builder();
+    }
+
+    public static SentMail.Builder fromMail(Mail mail) throws 
MessagingException {
+        return sentMailBuilder()
+            .sender(mail.getSender())
+            .recipients(mail.getRecipients())
+            .message(mail.getMessage())
+            .state(mail.getState())
+            .attributes(buildAttributesMap(mail))
+            .fromMailet();
+    }
+
+    private static ImmutableMap<String, Serializable> buildAttributesMap(Mail 
mail) {
+        Map<String, Serializable> result = new HashMap<>();
+        List<String> attributesNames = 
Lists.newArrayList(mail.getAttributeNames());
+        for (String attributeName: attributesNames) {
+            result.put(attributeName, mail.getAttribute(attributeName));
+        }
+        return ImmutableMap.copyOf(result);
+    }
+
+    public static FakeMailContext defaultContext() {
+        return builder().build();
+    }
+
+    public static class Builder {
+
+        private Logger logger;
+        private Optional<MailAddress> postmaster;
+
+        private Builder() {
+            postmaster = Optional.empty();
+        }
+
+        public Builder logger(Logger logger) {
+            this.logger = logger;
+            return this;
+        }
+
+        public Builder postmaster(MailAddress postmaster) {
+            this.postmaster = Optional.of(postmaster);
+            return this;
+        }
+
+        public FakeMailContext build() {
+            return new FakeMailContext(Optional.ofNullable(logger), 
postmaster.orElse(null));
+        }
+    }
+
+    public static class SentMail {
+
+        private static MimeMessage tryCopyMimeMessage(MimeMessage msg) throws 
MessagingException {
+            ThrowingFunction<MimeMessage, MimeMessage> throwingFunction = 
MimeMessageWrapper::wrap;
+
+            return Optional.ofNullable(msg)
+                .map(Throwing.function(throwingFunction).sneakyThrow())
+                .orElse(null);
+        }
+
+        public static class Builder {
+            private MailAddress sender;
+            private Optional<Collection<MailAddress>> recipients = 
Optional.empty();
+            private MimeMessage msg;
+            private Map<String, Serializable> attributes = new HashMap<>();
+            private Optional<String> state = Optional.empty();
+            private Optional<Boolean> fromMailet = Optional.empty();
+            private Optional<Delay> delay = Optional.empty();
+
+            public Builder sender(MailAddress sender) {
+                this.sender = sender;
+                return this;
+            }
+
+            public Builder sender(String sender) throws AddressException {
+                return sender(new MailAddress(sender));
+            }
+
+            public Builder recipients(Collection<MailAddress> recipients) {
+                this.recipients = Optional.of(recipients);
+                return this;
+            }
+
+            public Builder fromMailet() {
+                this.fromMailet = Optional.of(true);
+                return this;
+            }
+
+            public Builder recipients(MailAddress... recipients) {
+                this.recipients = 
Optional.<Collection<MailAddress>>of(ImmutableList.copyOf(recipients));
+                return this;
+            }
+
+            public Builder recipient(MailAddress recipient) {
+                Preconditions.checkNotNull(recipient);
+                return recipients(ImmutableList.of(recipient));
+            }
+
+            public Builder recipient(String recipient) throws AddressException 
{
+                Preconditions.checkNotNull(recipient);
+                return recipients(new MailAddress(recipient));
+            }
+
+            public Builder message(MimeMessage mimeMessage) {
+                this.msg = mimeMessage;
+                return this;
+            }
+
+            public Builder attributes(Map<String, Serializable> attributes) {
+                this.attributes.putAll(attributes);
+                return this;
+            }
+
+            public Builder attribute(String key, Serializable value) {
+                this.attributes.put(key, value);
+                return this;
+            }
+
+            public Builder state(String state) {
+                this.state = Optional.of(state);
+                return this;
+            }
+
+            public Builder delay(Delay delay) {
+                this.delay = Optional.of(delay);
+                return this;
+            }
+
+            public SentMail build() throws MessagingException {
+                if (fromMailet.orElse(false)) {
+                    this.attribute(Mail.SENT_BY_MAILET, "true");
+                }
+                return new SentMail(sender, 
recipients.orElse(ImmutableList.<MailAddress>of()), msg,
+                    ImmutableMap.copyOf(attributes), 
state.orElse(Mail.DEFAULT), delay);
+            }
+        }
+
+        private final MailAddress sender;
+        private final Collection<MailAddress> recipients;
+        private final MimeMessage msg;
+        private final Optional<String> subject;
+        private final Map<String, Serializable> attributes;
+        private final String state;
+        private final Optional<Delay> delay;
+
+        private SentMail(MailAddress sender, Collection<MailAddress> 
recipients, MimeMessage msg, Map<String, Serializable> attributes, String 
state, Optional<Delay> delay) throws MessagingException {
+            this.sender = sender;
+            this.recipients = ImmutableList.copyOf(recipients);
+            this.msg = tryCopyMimeMessage(msg);
+            this.subject = getSubject(msg);
+            this.attributes = ImmutableMap.copyOf(attributes);
+            this.state = state;
+            this.delay = delay;
+        }
+
+        private Optional<String> getSubject(MimeMessage msg) {
+            try {
+                return Optional.ofNullable(msg.getSubject());
+            } catch (Exception e) {
+                return Optional.empty();
+            }
+        }
+
+        public MailAddress getSender() {
+            return sender;
+        }
+
+        public Collection<MailAddress> getRecipients() {
+            return recipients;
+        }
+
+        public MimeMessage getMsg() {
+            return msg;
+        }
+
+        public String getState() {
+            return state;
+        }
+
+        public Optional<String> getSubject() {
+            return subject;
+        }
+
+
+        public Optional<Delay> getDelay() {
+            return delay;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (!(o instanceof SentMail)) {
+                return false;
+            }
+
+            SentMail sentMail = (SentMail) o;
+
+            return Objects.equals(this.sender, sentMail.sender)
+                && Objects.equals(this.recipients, sentMail.recipients)
+                && Objects.equals(this.attributes, sentMail.attributes)
+                && Objects.equals(this.state, sentMail.state);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(sender, recipients, attributes, state);
+        }
+
+        @Override
+        public String toString() {
+            return MoreObjects.toStringHelper(this)
+                .add("recipients", recipients)
+                .add("sender", sender)
+                .add("attributeNames", attributes)
+                .add("state", state)
+                .toString();
+        }
+    }
+
+    public static class Delay {
+        private final long duration;
+        private final TimeUnit timeUnit;
+
+        public Delay(long duration, TimeUnit timeUnit) {
+            this.duration = duration;
+            this.timeUnit = timeUnit;
+        }
+
+        public long getDuration() {
+            return duration;
+        }
+
+        public TimeUnit getTimeUnit() {
+            return timeUnit;
+        }
+
+        @Override
+        public final boolean equals(Object o) {
+            if (o instanceof Delay) {
+                Delay delay = (Delay) o;
+
+                return Objects.equals(this.duration, delay.duration)
+                    && Objects.equals(this.timeUnit, delay.timeUnit);
+            }
+            return false;
+        }
+
+        @Override
+        public final int hashCode() {
+            return Objects.hash(duration, timeUnit);
+        }
+    }
+
+    public static class BouncedMail {
+        private final SentMail sentMail;
+        private final String message;
+        private final Optional<MailAddress> bouncer;
+
+        public BouncedMail(SentMail sentMail, String message, 
Optional<MailAddress> bouncer) {
+            this.sentMail = sentMail;
+            this.message = message;
+            this.bouncer = bouncer;
+        }
+
+        public BouncedMail(SentMail.Builder sentMail, String message, 
Optional<MailAddress> bouncer) throws MessagingException {
+            this(sentMail.build(), message, bouncer);
+        }
+
+        public SentMail getSentMail() {
+            return sentMail;
+        }
+
+        public String getMessage() {
+            return message;
+        }
+
+        public Optional<MailAddress> getBouncer() {
+            return bouncer;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (o instanceof BouncedMail) {
+                BouncedMail that = (BouncedMail) o;
+                return Objects.equals(this.sentMail, that.sentMail)
+                    && Objects.equals(this.message, that.message)
+                    && Objects.equals(this.bouncer, that.bouncer);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(sentMail, message, bouncer);
+        }
+
+        @Override
+        public String toString() {
+            return MoreObjects.toStringHelper(this)
+                .add("sentMail", sentMail)
+                .add("message", message)
+                .add("bouncer", bouncer)
+                .toString();
+        }
+    }
+
+    private final HashMap<String, Object> attributes;
+    private final Collection<SentMail> sentMails;
+    private final Collection<BouncedMail> bouncedMails;
+    private final Optional<Logger> logger;
+    private final MailAddress postmaster;
+
+    private FakeMailContext(Optional<Logger> logger, MailAddress postmaster) {
+        attributes = new HashMap<>();
+        sentMails = new ConcurrentLinkedQueue<>();
+        bouncedMails = new ConcurrentLinkedQueue<>();
+        this.logger = logger;
+        this.postmaster = postmaster;
+    }
+
+    @Override
+    public void bounce(Mail mail, String message) throws MessagingException {
+        bouncedMails.add(new BouncedMail(fromMail(mail), message, 
Optional.empty()));
+    }
+
+    @Override
+    public void bounce(Mail mail, String message, MailAddress bouncer) throws 
MessagingException {
+        bouncedMails.add(new BouncedMail(fromMail(mail), message, 
Optional.ofNullable(bouncer)));
+    }
+
+    /**
+     * @deprecated use the generic dnsLookup method
+     */
+    @Override
+    public Collection<String> getMailServers(Domain host) {
+        return null;  // trivial implementation
+    }
+
+    @Override
+    public MailAddress getPostmaster() {
+        return postmaster;
+    }
+
+    @Override
+    public Object getAttribute(String name) {
+        return attributes.get(name);
+    }
+
+    @Override
+    public Iterator<String> getAttributeNames() {
+        return attributes.keySet().iterator();
+    }
+
+    @Override
+    public int getMajorVersion() {
+        return 0;  // trivial implementation
+    }
+
+    @Override
+    public int getMinorVersion() {
+        return 0;  // trivial implementation
+    }
+
+    @Override
+    public String getServerInfo() {
+        return "Mock Server";
+    }
+
+    @Override
+    public boolean isLocalServer(Domain domain) {
+        return domain.equals(Domain.LOCALHOST);
+    }
+
+    /**
+     * @deprecated use {@link #isLocalEmail(MailAddress)} instead 
+     */
+    @Override
+    public boolean isLocalUser(String userAccount) {
+        return false;  // trivial implementation
+    }
+
+    @Override
+    public boolean isLocalEmail(MailAddress mailAddress) {
+        return false;  // trivial implementation
+    }
+
+    /**
+     * @deprecated use {@link #log(LogLevel level, String message)}
+     */
+    @Override
+    public void log(String message) {
+        System.out.println(message);
+    }
+
+    /**
+     * @deprecated use {@link #log(LogLevel level, String message, Throwable 
t)}
+     */
+    @Override
+    public void log(String message, Throwable t) {
+        System.out.println(message);
+        t.printStackTrace(System.out);
+    }
+
+    @Override
+    public void removeAttribute(String name) {
+        // trivial implementation
+    }
+
+    @Override
+    public void sendMail(MimeMessage mimemessage) throws MessagingException {
+        sentMails.add(sentMailBuilder()
+            .message(mimemessage)
+            .fromMailet()
+            .build());
+    }
+
+    @Override
+    public void sendMail(MailAddress sender, Collection<MailAddress> 
recipients, MimeMessage msg) throws MessagingException {
+        sentMails.add(sentMailBuilder()
+            .recipients(recipients)
+            .sender(sender)
+            .message(msg)
+            .fromMailet()
+            .build());
+    }
+
+    @Override
+    public void sendMail(MailAddress sender, Collection<MailAddress> 
recipients, MimeMessage msg, String state) throws MessagingException {
+        sentMails.add(sentMailBuilder()
+            .recipients(recipients)
+            .message(msg)
+            .state(state)
+            .sender(sender)
+            .fromMailet()
+            .build());
+    }
+
+    @Override
+    public void sendMail(Mail mail) throws MessagingException {
+        sendMail(mail, Mail.DEFAULT);
+    }
+
+    @Override
+    public void sendMail(Mail mail, long delay, TimeUnit unit) throws 
MessagingException {
+        sendMail(mail, Mail.DEFAULT, delay, unit);
+    }
+
+    @Override
+    public void sendMail(Mail mail, String state) throws MessagingException {
+        mail.setState(state);
+        sentMails.add(fromMail(mail).build());
+    }
+
+    @Override
+    public void sendMail(Mail mail, String state, long delay, TimeUnit unit) 
throws MessagingException {
+        mail.setState(state);
+        sentMails.add(
+            fromMail(mail)
+                .delay(new Delay(delay, unit))
+                .build());
+    }
+
+    public void setAttribute(String name, Serializable object) {
+        attributes.put(name,object);
+    }
+
+    public void storeMail(MailAddress sender, MailAddress recipient, 
MimeMessage msg) throws MessagingException {
+        // trivial implementation
+    }
+
+    /**
+     * @deprecated use the generic dnsLookup method
+     */
+    @Override
+    public Iterator<HostAddress> getSMTPHostAddresses(Domain domainName) {
+        return null;  // trivial implementation
+    }
+
+    @Override
+    public void setAttribute(String name, Object value) {
+        throw new UnsupportedOperationException("MOCKed method");
+    }
+
+    @Override
+    public void log(LogLevel level, String message) {
+        if (logger.isPresent()) {
+            switch (level) {
+            case INFO:
+                logger.get().info(message);
+                break;
+            case WARN:
+                logger.get().warn(message);
+                break;
+            case ERROR:
+                logger.get().error(message);
+                break;
+            default:
+                logger.get().debug(message);
+            }
+        } else {
+            System.out.println("[" + level + "]" + message);
+        }
+    }
+
+    @Override
+    public void log(LogLevel level, String message, Throwable t) {
+        if (logger.isPresent()) {
+            switch (level) {
+            case INFO:
+                logger.get().info(message, t);
+                break;
+            case WARN:
+                logger.get().warn(message, t);
+                break;
+            case ERROR:
+                logger.get().error(message, t);
+                break;
+            default:
+                logger.get().debug(message, t);
+            }
+        } else {
+            System.out.println("[" + level + "]" + message);
+            t.printStackTrace(System.out);
+        }
+    }
+
+    @Override
+    public List<String> dnsLookup(String name, RecordType type) throws 
LookupException {
+        return null;   // trivial implementation
+    }
+
+    public List<SentMail> getSentMails() {
+        return ImmutableList.copyOf(sentMails);
+    }
+
+    public void resetSentMails() {
+        sentMails.clear();
+    }
+
+    public List<BouncedMail> getBouncedMails() {
+        return ImmutableList.copyOf(bouncedMails);
+    }
+
+    @Override
+    public Logger getLogger() {
+        return logger.orElse(null);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3dddd7c5/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMailetConfig.java
----------------------------------------------------------------------
diff --git 
a/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMailetConfig.java 
b/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMailetConfig.java
new file mode 100644
index 0000000..73289d7
--- /dev/null
+++ 
b/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMailetConfig.java
@@ -0,0 +1,106 @@
+/****************************************************************
+ * 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.mailet.base.test;
+
+import java.util.Iterator;
+import java.util.Optional;
+import java.util.Properties;
+
+import org.apache.mailet.MailetConfig;
+import org.apache.mailet.MailetContext;
+
+/**
+ * MailetConfig over Properties
+ */
+public class FakeMailetConfig implements MailetConfig {
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static class Builder {
+
+        private static final String DEFAULT_MAILET_NAME = "A Mailet";
+        private Optional<String> mailetName;
+        private Optional<MailetContext> mailetContext;
+        private Properties properties;
+
+        private Builder() {
+            mailetName = Optional.empty();
+            mailetContext = Optional.empty();
+            properties = new Properties();
+        }
+
+        public Builder mailetName(String mailetName) {
+            this.mailetName = Optional.ofNullable(mailetName);
+            return this;
+        }
+
+        public Builder mailetContext(MailetContext mailetContext) {
+            this.mailetContext = Optional.ofNullable(mailetContext);
+            return this;
+        }
+
+        public Builder mailetContext(FakeMailContext.Builder mailetContext) {
+            return mailetContext(mailetContext.build());
+        }
+
+        public Builder setProperty(String key, String value) {
+            this.properties.setProperty(key, value);
+            return this;
+        }
+
+        public FakeMailetConfig build() {
+            return new FakeMailetConfig(mailetName.orElse(DEFAULT_MAILET_NAME),
+                    mailetContext.orElse(FakeMailContext.defaultContext()),
+                    properties);
+        }
+    }
+
+    private final String mailetName;
+    private final MailetContext mailetContext;
+    private final Properties properties;
+
+    private FakeMailetConfig(String mailetName, MailetContext mailetContext, 
Properties properties) {
+        this.mailetName = mailetName;
+        this.mailetContext = mailetContext;
+        this.properties = properties;
+    }
+
+    @Override
+    public String getInitParameter(String name) {
+        return properties.getProperty(name);
+    }
+
+    @Override
+    public Iterator<String> getInitParameterNames() {
+        return properties.stringPropertyNames().iterator();
+    }
+
+    @Override
+    public MailetContext getMailetContext() {
+        return mailetContext;
+    }
+
+    @Override
+    public String getMailetName() {
+        return mailetName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3dddd7c5/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMatcherConfig.java
----------------------------------------------------------------------
diff --git 
a/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMatcherConfig.java 
b/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMatcherConfig.java
new file mode 100644
index 0000000..1917c3d
--- /dev/null
+++ 
b/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMatcherConfig.java
@@ -0,0 +1,95 @@
+/****************************************************************
+ * 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.mailet.base.test;
+
+import java.util.Optional;
+
+import org.apache.mailet.MailetContext;
+import org.apache.mailet.MatcherConfig;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * MatcherConfig
+ */
+public class FakeMatcherConfig implements MatcherConfig {
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static class Builder {
+
+        private String matcherName;
+        private Optional<MailetContext> mailetContext;
+        private Optional<String> condition;
+
+        private Builder() {
+            condition = Optional.empty();
+            mailetContext = Optional.empty();
+        }
+
+        public Builder matcherName(String matcherName) {
+            this.matcherName = matcherName;
+            return this;
+        }
+
+        public Builder mailetContext(MailetContext mailetContext) {
+            Preconditions.checkNotNull(mailetContext);
+            this.mailetContext = Optional.of(mailetContext);
+            return this;
+        }
+
+        public Builder condition(String condition) {
+            this.condition = Optional.ofNullable(condition);
+            return this;
+        }
+
+        public FakeMatcherConfig build() {
+            Preconditions.checkNotNull(matcherName, "'matcherName' is 
mandatory");
+            return new FakeMatcherConfig(matcherName, 
mailetContext.orElse(FakeMailContext.defaultContext()), condition);
+        }
+    }
+
+    private final String matcherName;
+    private final MailetContext mailetContext;
+    private final Optional<String> condition;
+
+    private FakeMatcherConfig(String matcherName, MailetContext mailetContext, 
Optional<String> condition) {
+        this.matcherName = matcherName;
+        this.mailetContext = mailetContext;
+        this.condition = condition;
+    }
+
+    @Override
+    public String getMatcherName() {
+        return matcherName;
+    }
+
+    @Override
+    public MailetContext getMailetContext() {
+        return mailetContext;
+    }
+
+    @Override
+    public String getCondition() {
+        return condition.orElse(null);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/3dddd7c5/mailet/test/src/main/java/org/apache/mailet/base/test/MailUtil.java
----------------------------------------------------------------------
diff --git 
a/mailet/test/src/main/java/org/apache/mailet/base/test/MailUtil.java 
b/mailet/test/src/main/java/org/apache/mailet/base/test/MailUtil.java
new file mode 100644
index 0000000..ecbee4f
--- /dev/null
+++ b/mailet/test/src/main/java/org/apache/mailet/base/test/MailUtil.java
@@ -0,0 +1,92 @@
+/****************************************************************
+ * 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.mailet.base.test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.james.core.MailAddress;
+import org.apache.james.core.builder.MimeMessageBuilder;
+import org.apache.mailet.Mail;
+
+/**
+ * some utilities for James unit testing
+ */
+public class MailUtil {
+
+    public static final String SENDER = "t...@james.apache.org";
+    public static final String RECIPIENT = "te...@james.apache.org";
+    private static int m_counter = 0;
+
+    public static String newId() {
+        m_counter++;
+        return "MockMailUtil-ID-" + m_counter;
+    }
+
+    public static FakeMail createMockMail2Recipients() throws 
MessagingException {
+        return FakeMail.builder()
+                .name(newId())
+                .recipients(new MailAddress("t...@james.apache.org"), new 
MailAddress("te...@james.apache.org"))
+                .build();
+    }
+
+    public static FakeMail createMockMail2Recipients(MimeMessage message) 
throws MessagingException {
+        return FakeMail.builder()
+                .name(newId())
+                .mimeMessage(message)
+                .recipients(new MailAddress("t...@james.apache.org"), new 
MailAddress("te...@james.apache.org"))
+                .build();
+    }
+
+    public static MimeMessage createMimeMessage() throws MessagingException {
+        return createMimeMessage(null, null);
+    }
+    
+    public static MimeMessage createMimeMessageWithSubject(String subject) 
throws MessagingException {
+        return createMimeMessage(null, null, subject);
+    }
+
+    public static MimeMessage createMimeMessage(String headerName, String 
headerValue) throws MessagingException {
+        return createMimeMessage(headerName, headerValue, "testmail");
+    }
+    
+    private static MimeMessage createMimeMessage(String headerName, String 
headerValue, String subject) throws MessagingException {
+        MimeMessageBuilder mimeMessageBuilder = 
MimeMessageBuilder.mimeMessageBuilder()
+            .addToRecipient(RECIPIENT)
+            .addFrom(SENDER)
+            .setSubject(subject);
+        if (headerName != null) {
+            mimeMessageBuilder.addHeader(headerName, headerValue);
+        }
+        return mimeMessageBuilder.build();
+    }
+    
+    public static String toString(Mail mail, String charset) throws 
IOException, MessagingException {
+        ByteArrayOutputStream rawMessage = new ByteArrayOutputStream();
+        mail.getMessage().writeTo(
+                rawMessage,
+                new String[] { "Bcc", "Content-Length", "Message-ID" });
+        return rawMessage.toString(charset);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3dddd7c5/mailet/test/src/test/java/org/apache/mailet/base/test/FakeMailTest.java
----------------------------------------------------------------------
diff --git 
a/mailet/test/src/test/java/org/apache/mailet/base/test/FakeMailTest.java 
b/mailet/test/src/test/java/org/apache/mailet/base/test/FakeMailTest.java
new file mode 100644
index 0000000..fc0c03c
--- /dev/null
+++ b/mailet/test/src/test/java/org/apache/mailet/base/test/FakeMailTest.java
@@ -0,0 +1,41 @@
+/****************************************************************
+ * 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.mailet.base.test;
+
+import static org.mockito.Mockito.mock;
+
+import javax.mail.internet.MimeMessage;
+
+import org.junit.Test;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+import nl.jqno.equalsverifier.Warning;
+
+public class FakeMailTest {
+
+    @Test
+    public void beanShouldRespectBeanContract() {
+        EqualsVerifier.forClass(FakeMail.class)
+            .suppress(Warning.NONFINAL_FIELDS)
+            .withPrefabValues(MimeMessage.class, mock(MimeMessage.class), 
mock(MimeMessage.class))
+            .verify();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3dddd7c5/mpt/impl/imap-mailbox/core/pom.xml
----------------------------------------------------------------------
diff --git a/mpt/impl/imap-mailbox/core/pom.xml 
b/mpt/impl/imap-mailbox/core/pom.xml
index 83d17d4..b8075ff 100644
--- a/mpt/impl/imap-mailbox/core/pom.xml
+++ b/mpt/impl/imap-mailbox/core/pom.xml
@@ -85,11 +85,6 @@
             <artifactId>protocols-imap</artifactId>
         </dependency>
         <dependency>
-            <groupId>${james.protocols.groupId}</groupId>
-            <artifactId>protocols-imap</artifactId>
-            <type>test-jar</type>
-        </dependency>
-        <dependency>
             <groupId>org.jmock</groupId>
             <artifactId>jmock</artifactId>
         </dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/3dddd7c5/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 0164ebe..669d927 100644
--- a/pom.xml
+++ b/pom.xml
@@ -982,6 +982,11 @@
             </dependency>
             <dependency>
                 <groupId>${james.groupId}</groupId>
+                <artifactId>apache-mailet-test</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+             <dependency>
+                <groupId>${james.groupId}</groupId>
                 <artifactId>apache-mime4j-core</artifactId>
                 <version>${apache-mime4j.version}</version>
                 <exclusions>

http://git-wip-us.apache.org/repos/asf/james-project/blob/3dddd7c5/protocols/imap/src/main/java/org/apache/james/imap/decode/ImapRequestStreamLineReader.java
----------------------------------------------------------------------
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/decode/ImapRequestStreamLineReader.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/decode/ImapRequestStreamLineReader.java
new file mode 100644
index 0000000..4fedc02
--- /dev/null
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/decode/ImapRequestStreamLineReader.java
@@ -0,0 +1,105 @@
+/****************************************************************
+ * 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.imap.decode;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.james.imap.api.display.HumanReadableText;
+import org.apache.james.protocols.imap.DecodingException;
+import org.apache.james.protocols.imap.utils.EolInputStream;
+import org.apache.james.protocols.imap.utils.FixedLengthInputStream;
+
+/**
+ * {@link ImapRequestLineReader} which use normal IO Streaming
+ */
+public class ImapRequestStreamLineReader extends ImapRequestLineReader {
+    private final InputStream input;
+
+    private final OutputStream output;
+
+    public ImapRequestStreamLineReader(InputStream input, OutputStream output) 
{
+        this.input = input;
+        this.output = output;
+    }
+
+    /**
+     * Reads the next character in the current line. This method will continue
+     * to return the same character until the {@link #consume()} method is
+     * called.
+     * 
+     * @return The next character TODO: character encoding is variable and
+     *         cannot be determine at the token level; this char is not 
accurate
+     *         reported; should be an octet
+     * @throws DecodingException
+     *             If the end-of-stream is reached.
+     */
+    @Override
+    public char nextChar() throws DecodingException {
+        if (!nextSeen) {
+            int next = -1;
+
+            try {
+                next = input.read();
+            } catch (IOException e) {
+                throw new 
DecodingException(HumanReadableText.SOCKET_IO_FAILURE, "Error reading from 
stream.", e);
+            }
+            if (next == -1) {
+                throw new 
DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unexpected end of 
stream.");
+            }
+
+            nextSeen = true;
+            nextChar = (char) next;
+        }
+        return nextChar;
+    }
+
+    @Override
+    public InputStream read(int size, boolean extraCRLF) throws 
DecodingException {
+
+        // Unset the next char.
+        nextSeen = false;
+        nextChar = 0;
+        FixedLengthInputStream in = new FixedLengthInputStream(input, size);
+        if (extraCRLF) {
+            return new EolInputStream(this, in);
+        } else {
+            return in;
+        }
+    }
+
+    /**
+     * Sends a server command continuation request '+' back to the client,
+     * requesting more data to be sent.
+     */
+    @Override
+    protected void commandContinuationRequest() throws DecodingException {
+        try {
+            output.write('+');
+            output.write('\r');
+            output.write('\n');
+            output.flush();
+        } catch (IOException e) {
+            throw new DecodingException(HumanReadableText.SOCKET_IO_FAILURE, 
"Unexpected exception in sending command continuation request.", e);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3dddd7c5/protocols/imap/src/main/java/org/apache/james/imap/decode/main/ImapRequestStreamHandler.java
----------------------------------------------------------------------
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/decode/main/ImapRequestStreamHandler.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/decode/main/ImapRequestStreamHandler.java
new file mode 100644
index 0000000..f720a6a
--- /dev/null
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/decode/main/ImapRequestStreamHandler.java
@@ -0,0 +1,129 @@
+/****************************************************************
+ * 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.imap.decode.main;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.james.imap.api.ImapSessionState;
+import org.apache.james.imap.api.process.ImapProcessor;
+import org.apache.james.imap.api.process.ImapSession;
+import org.apache.james.imap.decode.ImapDecoder;
+import org.apache.james.imap.decode.ImapRequestLineReader;
+import org.apache.james.imap.decode.ImapRequestStreamLineReader;
+import org.apache.james.imap.encode.ImapEncoder;
+import org.apache.james.imap.encode.base.ImapResponseComposerImpl;
+import org.apache.james.imap.main.AbstractImapRequestHandler;
+import org.apache.james.imap.message.request.SystemMessage;
+import org.apache.james.protocols.imap.DecodingException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 
+ */
+public final class ImapRequestStreamHandler extends AbstractImapRequestHandler 
{
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(ImapRequestStreamHandler.class);
+
+    public ImapRequestStreamHandler(ImapDecoder decoder, ImapProcessor 
processor, ImapEncoder encoder) {
+        super(decoder, processor, encoder);
+    }
+
+    /**
+     * This method parses IMAP commands read off the wire in handleConnection.
+     * Actual processing of the command (possibly including additional back and
+     * forth communication with the client) is delegated to one of a number of
+     * command specific handler methods. The primary purpose of this method is
+     * to parse the raw command string to determine exactly which handler 
should
+     * be called. It returns true if expecting additional commands, false
+     * otherwise.
+     * 
+     * @return whether additional commands are expected.
+     */
+    public boolean handleRequest(InputStream input, OutputStream output, 
ImapSession session) {
+        final boolean result;
+        if (isSelectedMailboxDeleted(session)) {
+            writeSignoff(output, session);
+            result = false;
+        } else {
+            ImapRequestLineReader request = new 
ImapRequestStreamLineReader(input, output);
+
+            try {
+                request.nextChar();
+            } catch (DecodingException e) {
+                LOGGER.debug("Unexpected end of line. Cannot handle request: 
", e);
+                abandon(output, session);
+                return false;
+            }
+
+            ImapResponseComposerImpl response = new 
ImapResponseComposerImpl(new OutputStreamImapResponseWriter(output));
+
+            if (doProcessRequest(request, response, session)) {
+
+                try {
+                    // Consume the rest of the line, throwing away any extras.
+                    // This allows us to clean up after a protocol error.
+                    request.consumeLine();
+                } catch (DecodingException e) {
+                    // Cannot clean up. No recovery is therefore possible.
+                    // Abandon connection.
+                    LOGGER.info("Fault during clean up: {}", e.getMessage());
+                    LOGGER.debug("Abandoning after fault in clean up", e);
+                    abandon(output, session);
+                    return false;
+                }
+
+                result = !(ImapSessionState.LOGOUT == session.getState());
+            } else {
+                LOGGER.debug("Connection was abandoned after request 
processing failed.");
+                result = false;
+                abandon(output, session);
+            }
+        }
+        return result;
+    }
+
+    private void writeSignoff(OutputStream output, ImapSession session) {
+        try {
+            output.write(MAILBOX_DELETED_SIGNOFF);
+        } catch (IOException e) {
+            LOGGER.warn("Failed to write signoff");
+            LOGGER.debug("Failed to write signoff:", e);
+        }
+    }
+
+    private void abandon(OutputStream out, ImapSession session) {
+        if (session != null) {
+            try {
+                session.logout();
+            } catch (Throwable t) {
+                LOGGER.warn("Session logout failed. Resources may not be 
correctly recycled.");
+            }
+        }
+        try {
+            out.write(ABANDON_SIGNOFF);
+        } catch (Throwable t) {
+            LOGGER.debug("Failed to write ABANDON_SIGNOFF", t);
+        }
+        processor.process(SystemMessage.FORCE_LOGOUT, new SilentResponder(), 
session);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3dddd7c5/protocols/imap/src/main/java/org/apache/james/imap/decode/main/OutputStreamImapResponseWriter.java
----------------------------------------------------------------------
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/decode/main/OutputStreamImapResponseWriter.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/decode/main/OutputStreamImapResponseWriter.java
new file mode 100644
index 0000000..4ceaad6
--- /dev/null
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/decode/main/OutputStreamImapResponseWriter.java
@@ -0,0 +1,70 @@
+/****************************************************************
+ * 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.imap.decode.main;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.james.imap.encode.ImapResponseWriter;
+import org.apache.james.imap.message.response.Literal;
+
+/**
+ * Class providing methods to send response messages from the server to the
+ * client.
+ */
+public class OutputStreamImapResponseWriter implements ImapResponseWriter {
+
+    private final OutputStream output;
+
+    public OutputStreamImapResponseWriter(OutputStream output) {
+        this.output = output;
+    }
+
+    public void flush() throws IOException {
+        output.flush();
+    }
+
+
+
+    @Override
+    public void write(Literal literal) throws IOException {
+        InputStream in = null;
+        try {
+            in = literal.getInputStream();
+
+            byte[] buffer = new byte[1024];
+            for (int len; (len = in.read(buffer)) != -1;) {
+                output.write(buffer, 0, len);
+            }
+        } finally {
+            if (in != null) {
+                in.close();
+            }
+        }
+
+    }
+
+    @Override
+    public void write(byte[] buffer) throws IOException {
+        output.write(buffer);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3dddd7c5/protocols/imap/src/main/java/org/apache/james/imap/encode/FakeImapSession.java
----------------------------------------------------------------------
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/encode/FakeImapSession.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/encode/FakeImapSession.java
new file mode 100644
index 0000000..bd7d053
--- /dev/null
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/encode/FakeImapSession.java
@@ -0,0 +1,145 @@
+/****************************************************************
+ * 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.imap.encode;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.james.imap.api.ImapSessionState;
+import org.apache.james.imap.api.process.ImapLineHandler;
+import org.apache.james.imap.api.process.ImapSession;
+import org.apache.james.imap.api.process.SelectedMailbox;
+
+public class FakeImapSession implements ImapSession {
+
+    private ImapSessionState state = ImapSessionState.NON_AUTHENTICATED;
+
+    private SelectedMailbox selectedMailbox = null;
+
+    private final Map<String, Object> attributesByKey;
+
+    public FakeImapSession() {
+        this.attributesByKey = new ConcurrentHashMap<>();
+    }
+
+    @Override
+    public void logout() {
+        closeMailbox();
+        state = ImapSessionState.LOGOUT;
+    }
+
+    @Override
+    public void authenticated() {
+        this.state = ImapSessionState.AUTHENTICATED;
+    }
+
+    @Override
+    public void deselect() {
+        this.state = ImapSessionState.AUTHENTICATED;
+        closeMailbox();
+    }
+
+    @Override
+    public void selected(SelectedMailbox mailbox) {
+        this.state = ImapSessionState.SELECTED;
+        closeMailbox();
+        this.selectedMailbox = mailbox;
+    }
+
+    @Override
+    public SelectedMailbox getSelected() {
+        return this.selectedMailbox;
+    }
+
+    @Override
+    public ImapSessionState getState() {
+        return this.state;
+    }
+
+    public void closeMailbox() {
+        if (selectedMailbox != null) {
+            selectedMailbox.deselect();
+            selectedMailbox = null;
+        }
+    }
+
+    @Override
+    public Object getAttribute(String key) {
+        return attributesByKey.get(key);
+    }
+
+    @Override
+    public void setAttribute(String key, Object value) {
+        if (value == null) {
+            attributesByKey.remove(key);
+        } else {
+            attributesByKey.put(key, value);
+        }
+    }
+    
+    @Override
+    public boolean startTLS() {
+        return false;
+    }
+
+    @Override
+    public boolean supportStartTLS() {
+        return false;
+    }
+
+    @Override
+    public boolean isCompressionSupported() {
+        return false;
+    }
+
+    @Override
+    public boolean startCompression() {
+        return false;
+    }
+
+    @Override
+    public void pushLineHandler(ImapLineHandler lineHandler) {
+    }
+
+    @Override
+    public void popLineHandler() {
+        
+    }
+
+    @Override
+    public boolean isPlainAuthDisallowed() {
+        return false;
+    }
+
+    @Override
+    public boolean isTLSActive() {
+        return false;
+    }
+
+    @Override
+    public boolean supportMultipleNamespaces() {
+        return false;
+    }
+
+    @Override
+    public boolean isCompressionActive() {
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3dddd7c5/protocols/imap/src/test/java/org/apache/james/imap/decode/ImapRequestStreamLineReader.java
----------------------------------------------------------------------
diff --git 
a/protocols/imap/src/test/java/org/apache/james/imap/decode/ImapRequestStreamLineReader.java
 
b/protocols/imap/src/test/java/org/apache/james/imap/decode/ImapRequestStreamLineReader.java
deleted file mode 100644
index 4fedc02..0000000
--- 
a/protocols/imap/src/test/java/org/apache/james/imap/decode/ImapRequestStreamLineReader.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.imap.decode;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.apache.james.imap.api.display.HumanReadableText;
-import org.apache.james.protocols.imap.DecodingException;
-import org.apache.james.protocols.imap.utils.EolInputStream;
-import org.apache.james.protocols.imap.utils.FixedLengthInputStream;
-
-/**
- * {@link ImapRequestLineReader} which use normal IO Streaming
- */
-public class ImapRequestStreamLineReader extends ImapRequestLineReader {
-    private final InputStream input;
-
-    private final OutputStream output;
-
-    public ImapRequestStreamLineReader(InputStream input, OutputStream output) 
{
-        this.input = input;
-        this.output = output;
-    }
-
-    /**
-     * Reads the next character in the current line. This method will continue
-     * to return the same character until the {@link #consume()} method is
-     * called.
-     * 
-     * @return The next character TODO: character encoding is variable and
-     *         cannot be determine at the token level; this char is not 
accurate
-     *         reported; should be an octet
-     * @throws DecodingException
-     *             If the end-of-stream is reached.
-     */
-    @Override
-    public char nextChar() throws DecodingException {
-        if (!nextSeen) {
-            int next = -1;
-
-            try {
-                next = input.read();
-            } catch (IOException e) {
-                throw new 
DecodingException(HumanReadableText.SOCKET_IO_FAILURE, "Error reading from 
stream.", e);
-            }
-            if (next == -1) {
-                throw new 
DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unexpected end of 
stream.");
-            }
-
-            nextSeen = true;
-            nextChar = (char) next;
-        }
-        return nextChar;
-    }
-
-    @Override
-    public InputStream read(int size, boolean extraCRLF) throws 
DecodingException {
-
-        // Unset the next char.
-        nextSeen = false;
-        nextChar = 0;
-        FixedLengthInputStream in = new FixedLengthInputStream(input, size);
-        if (extraCRLF) {
-            return new EolInputStream(this, in);
-        } else {
-            return in;
-        }
-    }
-
-    /**
-     * Sends a server command continuation request '+' back to the client,
-     * requesting more data to be sent.
-     */
-    @Override
-    protected void commandContinuationRequest() throws DecodingException {
-        try {
-            output.write('+');
-            output.write('\r');
-            output.write('\n');
-            output.flush();
-        } catch (IOException e) {
-            throw new DecodingException(HumanReadableText.SOCKET_IO_FAILURE, 
"Unexpected exception in sending command continuation request.", e);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3dddd7c5/protocols/imap/src/test/java/org/apache/james/imap/decode/main/ImapRequestStreamHandler.java
----------------------------------------------------------------------
diff --git 
a/protocols/imap/src/test/java/org/apache/james/imap/decode/main/ImapRequestStreamHandler.java
 
b/protocols/imap/src/test/java/org/apache/james/imap/decode/main/ImapRequestStreamHandler.java
deleted file mode 100644
index f720a6a..0000000
--- 
a/protocols/imap/src/test/java/org/apache/james/imap/decode/main/ImapRequestStreamHandler.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.imap.decode.main;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.apache.james.imap.api.ImapSessionState;
-import org.apache.james.imap.api.process.ImapProcessor;
-import org.apache.james.imap.api.process.ImapSession;
-import org.apache.james.imap.decode.ImapDecoder;
-import org.apache.james.imap.decode.ImapRequestLineReader;
-import org.apache.james.imap.decode.ImapRequestStreamLineReader;
-import org.apache.james.imap.encode.ImapEncoder;
-import org.apache.james.imap.encode.base.ImapResponseComposerImpl;
-import org.apache.james.imap.main.AbstractImapRequestHandler;
-import org.apache.james.imap.message.request.SystemMessage;
-import org.apache.james.protocols.imap.DecodingException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * 
- */
-public final class ImapRequestStreamHandler extends AbstractImapRequestHandler 
{
-    private static final Logger LOGGER = 
LoggerFactory.getLogger(ImapRequestStreamHandler.class);
-
-    public ImapRequestStreamHandler(ImapDecoder decoder, ImapProcessor 
processor, ImapEncoder encoder) {
-        super(decoder, processor, encoder);
-    }
-
-    /**
-     * This method parses IMAP commands read off the wire in handleConnection.
-     * Actual processing of the command (possibly including additional back and
-     * forth communication with the client) is delegated to one of a number of
-     * command specific handler methods. The primary purpose of this method is
-     * to parse the raw command string to determine exactly which handler 
should
-     * be called. It returns true if expecting additional commands, false
-     * otherwise.
-     * 
-     * @return whether additional commands are expected.
-     */
-    public boolean handleRequest(InputStream input, OutputStream output, 
ImapSession session) {
-        final boolean result;
-        if (isSelectedMailboxDeleted(session)) {
-            writeSignoff(output, session);
-            result = false;
-        } else {
-            ImapRequestLineReader request = new 
ImapRequestStreamLineReader(input, output);
-
-            try {
-                request.nextChar();
-            } catch (DecodingException e) {
-                LOGGER.debug("Unexpected end of line. Cannot handle request: 
", e);
-                abandon(output, session);
-                return false;
-            }
-
-            ImapResponseComposerImpl response = new 
ImapResponseComposerImpl(new OutputStreamImapResponseWriter(output));
-
-            if (doProcessRequest(request, response, session)) {
-
-                try {
-                    // Consume the rest of the line, throwing away any extras.
-                    // This allows us to clean up after a protocol error.
-                    request.consumeLine();
-                } catch (DecodingException e) {
-                    // Cannot clean up. No recovery is therefore possible.
-                    // Abandon connection.
-                    LOGGER.info("Fault during clean up: {}", e.getMessage());
-                    LOGGER.debug("Abandoning after fault in clean up", e);
-                    abandon(output, session);
-                    return false;
-                }
-
-                result = !(ImapSessionState.LOGOUT == session.getState());
-            } else {
-                LOGGER.debug("Connection was abandoned after request 
processing failed.");
-                result = false;
-                abandon(output, session);
-            }
-        }
-        return result;
-    }
-
-    private void writeSignoff(OutputStream output, ImapSession session) {
-        try {
-            output.write(MAILBOX_DELETED_SIGNOFF);
-        } catch (IOException e) {
-            LOGGER.warn("Failed to write signoff");
-            LOGGER.debug("Failed to write signoff:", e);
-        }
-    }
-
-    private void abandon(OutputStream out, ImapSession session) {
-        if (session != null) {
-            try {
-                session.logout();
-            } catch (Throwable t) {
-                LOGGER.warn("Session logout failed. Resources may not be 
correctly recycled.");
-            }
-        }
-        try {
-            out.write(ABANDON_SIGNOFF);
-        } catch (Throwable t) {
-            LOGGER.debug("Failed to write ABANDON_SIGNOFF", t);
-        }
-        processor.process(SystemMessage.FORCE_LOGOUT, new SilentResponder(), 
session);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3dddd7c5/protocols/imap/src/test/java/org/apache/james/imap/decode/main/OutputStreamImapResponseWriter.java
----------------------------------------------------------------------
diff --git 
a/protocols/imap/src/test/java/org/apache/james/imap/decode/main/OutputStreamImapResponseWriter.java
 
b/protocols/imap/src/test/java/org/apache/james/imap/decode/main/OutputStreamImapResponseWriter.java
deleted file mode 100644
index 4ceaad6..0000000
--- 
a/protocols/imap/src/test/java/org/apache/james/imap/decode/main/OutputStreamImapResponseWriter.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.imap.decode.main;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.apache.james.imap.encode.ImapResponseWriter;
-import org.apache.james.imap.message.response.Literal;
-
-/**
- * Class providing methods to send response messages from the server to the
- * client.
- */
-public class OutputStreamImapResponseWriter implements ImapResponseWriter {
-
-    private final OutputStream output;
-
-    public OutputStreamImapResponseWriter(OutputStream output) {
-        this.output = output;
-    }
-
-    public void flush() throws IOException {
-        output.flush();
-    }
-
-
-
-    @Override
-    public void write(Literal literal) throws IOException {
-        InputStream in = null;
-        try {
-            in = literal.getInputStream();
-
-            byte[] buffer = new byte[1024];
-            for (int len; (len = in.read(buffer)) != -1;) {
-                output.write(buffer, 0, len);
-            }
-        } finally {
-            if (in != null) {
-                in.close();
-            }
-        }
-
-    }
-
-    @Override
-    public void write(byte[] buffer) throws IOException {
-        output.write(buffer);
-    }
-
-}


---------------------------------------------------------------------
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