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

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


The following commit(s) were added to refs/heads/master by this push:
     new 5b961b36c9 JAMES-4060: Fix UID FETCH command failing on empty mailbox 
(#2386)
5b961b36c9 is described below

commit 5b961b36c9892f5ec5a781da06f10c52706b99b6
Author: Wojtek <[email protected]>
AuthorDate: Wed Aug 28 05:42:00 2024 +0200

    JAMES-4060: Fix UID FETCH command failing on empty mailbox (#2386)
---
 .../store/streaming/InputStreamContent.java        |  9 +++++
 .../apache/james/mpt/imapmailbox/suite/Fetch.java  |  7 ++++
 .../james/imap/scripts/FetchAllEmptyMailbox.test   | 45 ++++++++++++++++++++++
 .../org/apache/james/imap/scripts/Uid.test         | 34 ++++++++++++++++
 .../main/java/org/apache/james/imap/api/Tag.java   |  5 +--
 .../james/imap/decode/main/DefaultImapDecoder.java |  9 ++++-
 .../james/imap/decode/parser/UidCommandParser.java |  1 -
 .../imap/message/request/AbstractImapRequest.java  |  7 ++++
 .../message/response/ImmutableStatusResponse.java  | 32 ++++++++++++---
 .../response/UnpooledStatusResponseFactory.java    |  4 ++
 .../imap/processor/AbstractMailboxProcessor.java   | 12 +++---
 .../imap/processor/fetch/ContentBodyElement.java   |  8 ++++
 .../james/imap/processor/fetch/FetchProcessor.java |  7 ++--
 .../netty/ChannelImapResponseWriter.java           | 20 ++++++++++
 .../netty/ImapChannelUpstreamHandler.java          | 11 +++---
 15 files changed, 182 insertions(+), 29 deletions(-)

diff --git 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/streaming/InputStreamContent.java
 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/streaming/InputStreamContent.java
index 92be0a277d..ad66c3e2d7 100644
--- 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/streaming/InputStreamContent.java
+++ 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/streaming/InputStreamContent.java
@@ -86,4 +86,13 @@ public final class InputStreamContent implements Content {
                 return m.getBodyContentReactive();
         }
     }
+
+    @Override
+    public String toString() {
+        final StringBuffer sb = new StringBuffer("InputStreamContent{");
+        sb.append("m=").append(m);
+        sb.append(", type=").append(type);
+        sb.append('}');
+        return sb.toString();
+    }
 }
diff --git 
a/mpt/impl/imap-mailbox/core/src/main/java/org/apache/james/mpt/imapmailbox/suite/Fetch.java
 
b/mpt/impl/imap-mailbox/core/src/main/java/org/apache/james/mpt/imapmailbox/suite/Fetch.java
index 6bbc2da361..d80e51d081 100644
--- 
a/mpt/impl/imap-mailbox/core/src/main/java/org/apache/james/mpt/imapmailbox/suite/Fetch.java
+++ 
b/mpt/impl/imap-mailbox/core/src/main/java/org/apache/james/mpt/imapmailbox/suite/Fetch.java
@@ -46,6 +46,13 @@ public abstract class Fetch implements ImapTestConstants {
         BasicImapCommands.prepareMailbox(simpleScriptedTestProtocol);
     }
     
+    @Test
+    public void testFetchAllEmptyMailboxUS() throws Exception {
+        simpleScriptedTestProtocol
+            .withLocale(Locale.US)
+            .run("FetchAllEmptyMailbox");
+    }
+
     @Test
     public void testFetchEnvelopeUS() throws Exception {
         simpleScriptedTestProtocol
diff --git 
a/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/FetchAllEmptyMailbox.test
 
b/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/FetchAllEmptyMailbox.test
new file mode 100644
index 0000000000..5c0a5b0e1b
--- /dev/null
+++ 
b/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/FetchAllEmptyMailbox.test
@@ -0,0 +1,45 @@
+################################################################
+# 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.                                           #
+################################################################
+# Fetch All messages from empty mailbox
+
+C: b1 CREATE box
+S: b1 OK \[MAILBOXID \(.*\)\] CREATE completed.
+
+C: b2 SELECT box
+S: \* OK \[MAILBOXID \(.+\)\] Ok
+S: \* FLAGS \(\\Answered \\Deleted \\Draft \\Flagged \\Seen\)
+S: \* 0 EXISTS
+S: \* 0 RECENT
+S: \* OK \[UIDVALIDITY \d+\].*
+S: \* OK \[PERMANENTFLAGS \(\\Answered \\Deleted \\Draft \\Flagged \\\Seen( 
\\\*)?\)\].*
+S: \* OK \[HIGHESTMODSEQ \d+\].*
+S: \* OK \[UIDNEXT 1\].*
+S: b2 OK \[READ-WRITE\] SELECT completed.
+
+C: b3 FETCH 1:* (UID)
+S: b3 OK FETCH completed.
+
+C: b4 FETCH *:* (UID)
+S: b4 OK FETCH completed.
+
+C: b5 FETCH * (UID)
+S: b5 OK FETCH completed.
+
+
+
diff --git 
a/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/Uid.test
 
b/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/Uid.test
index c20dd048d1..ab53c42037 100644
--- 
a/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/Uid.test
+++ 
b/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/Uid.test
@@ -32,6 +32,20 @@ S: \* 2 FETCH \(UID 3\)
 S: \* 3 FETCH \(UID 4\)
 S: a OK FETCH completed.
 
+C: a2 FETCH 1:* (UID)
+S: \* 1 FETCH \(UID 2\)
+S: \* 2 FETCH \(UID 3\)
+S: \* 3 FETCH \(UID 4\)
+S: a2 OK FETCH completed.
+
+C: a21 FETCH * (UID)
+S: \* 3 FETCH \(UID 4\)
+S: a21 OK FETCH completed.
+
+C: a22 FETCH *:* (UID)
+S: \* 3 FETCH \(UID 4\)
+S: a22 OK FETCH completed.
+
 #UID fetch
 C: a UID FETCH 2:3 (INTERNALDATE)
 S: \* 1 FETCH \(INTERNALDATE "[^"]*" UID 2\)
@@ -78,5 +92,25 @@ S: a OK SEARCH completed.
 C: a1 DELETE copied
 S: a1 OK DELETE completed.
 
+C: b1 CREATE box
+S: b1 OK \[MAILBOXID \(.*\)\] CREATE completed.
+
+C: b2 SELECT box
+S: \* OK \[MAILBOXID \(.+\)\] Ok
+S: \* FLAGS \(\\Answered \\Deleted \\Draft \\Flagged \\Seen\)
+S: \* 0 EXISTS
+S: \* 0 RECENT
+S: \* OK \[UIDVALIDITY \d+\].*
+S: \* OK \[PERMANENTFLAGS \(\\Answered \\Deleted \\Draft \\Flagged \\\Seen( 
\\\*)?\)\].*
+S: \* OK \[HIGHESTMODSEQ \d+\].*
+S: \* OK \[UIDNEXT 1\].*
+S: b2 OK \[READ-WRITE\] SELECT completed.
+
+C: b3 UID FETCH 1:* (UID)
+S: b3 OK FETCH completed.
 
+C: b4 UID FETCH *:* (UID)
+S: b4 OK FETCH completed.
 
+C: b5 UID FETCH * (UID)
+S: b5 OK FETCH completed.
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/api/Tag.java 
b/protocols/imap/src/main/java/org/apache/james/imap/api/Tag.java
index b11238fa86..b5a5ab5419 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/api/Tag.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/api/Tag.java
@@ -21,7 +21,6 @@ package org.apache.james.imap.api;
 
 import java.util.Objects;
 
-import com.google.common.base.MoreObjects;
 import com.google.common.base.Preconditions;
 
 public class Tag {
@@ -53,8 +52,6 @@ public class Tag {
 
     @Override
     public String toString() {
-        return MoreObjects.toStringHelper(this)
-            .add("value", value)
-            .toString();
+        return value;
     }
 }
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/decode/main/DefaultImapDecoder.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/decode/main/DefaultImapDecoder.java
index b8d93d5caa..7f3efdba0b 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/decode/main/DefaultImapDecoder.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/decode/main/DefaultImapDecoder.java
@@ -31,6 +31,7 @@ import org.apache.james.imap.decode.ImapCommandParser;
 import org.apache.james.imap.decode.ImapCommandParserFactory;
 import org.apache.james.imap.decode.ImapDecoder;
 import org.apache.james.imap.decode.ImapRequestLineReader;
+import org.apache.james.util.MDCStructuredLogger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -75,7 +76,6 @@ public class DefaultImapDecoder implements ImapDecoder {
     }
 
     private ImapMessage decodeCommandTagged(ImapRequestLineReader request, Tag 
tag, ImapSession session) {
-        LOGGER.debug("Got <tag>: {}", tag);
         try {
             String commandName = request.atom();
             return decodeCommandNamed(request, tag, commandName, session);
@@ -110,7 +110,6 @@ public class DefaultImapDecoder implements ImapDecoder {
     }
 
     private ImapMessage decodeCommandNamed(ImapRequestLineReader request, Tag 
tag, String commandName, ImapSession session) {
-        LOGGER.debug("Got <command>: {}", commandName);
         ImapCommandParser command = imapCommands.getParser(commandName);
         if (command == null) {
             LOGGER.info("Missing command implementation for commmand {}", 
commandName);
@@ -121,6 +120,12 @@ public class DefaultImapDecoder implements ImapDecoder {
         if (count == null || (int) count > 0) {
             session.setAttribute(INVALID_COMMAND_COUNT, 0);
         }
+        // Avoid cost of initializing MDC locally
+        if (LOGGER.isTraceEnabled()) {
+            new MDCStructuredLogger(LOGGER)
+                    .field("username", String.valueOf(session.getUserName()))
+                    .log(logger -> logger.trace("Processing {} {} {} ", tag, 
commandName, message));
+        }
         return message;
     }
 }
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/UidCommandParser.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/UidCommandParser.java
index 3a71c74145..4475f327c3 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/UidCommandParser.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/UidCommandParser.java
@@ -61,7 +61,6 @@ public class UidCommandParser extends 
AbstractImapCommandParser {
         if (!(helperCommand instanceof AbstractUidCommandParser)) {
             throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, 
"Invalid UID command: '" + commandName + "'");
         }
-        LOGGER.debug("Got <command>: UID {}", commandName);
         final AbstractUidCommandParser uidEnabled = (AbstractUidCommandParser) 
helperCommand;
         return uidEnabled.decode(request, tag, true, session);
     }
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/message/request/AbstractImapRequest.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/message/request/AbstractImapRequest.java
index cff01235be..c156856a06 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/message/request/AbstractImapRequest.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/message/request/AbstractImapRequest.java
@@ -52,4 +52,11 @@ public abstract class AbstractImapRequest implements 
ImapRequest {
         return tag;
     }
 
+    @Override
+    public String toString() {
+        return "AbstractImapRequest{" +
+                "tag=" + getTag() +
+                ", command=" + getCommand() +
+                '}';
+    }
 }
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/message/response/ImmutableStatusResponse.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/message/response/ImmutableStatusResponse.java
index df67936f12..1778c2af6d 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/message/response/ImmutableStatusResponse.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/message/response/ImmutableStatusResponse.java
@@ -70,14 +70,34 @@ public class ImmutableStatusResponse implements 
StatusResponse {
         return command;
     }
 
+    public String asString() {
+        final StringBuilder sb = new StringBuilder();
+        if (getResponseCode() != null) {
+            sb.append(' ').append(getResponseCode());
+        }
+        if (getServerResponseType() != null) {
+            sb.append(' ').append(getServerResponseType());
+        }
+        if (getTag() != null) {
+            sb.append(' ').append(getTag());
+        }
+        if (getTextKey() != null) {
+            sb.append(' ').append(getTextKey());
+        }
+        if (getCommand() != null) {
+            sb.append(' ').append(getCommand());
+        }
+        return sb.toString();
+    }
+
     @Override
     public String toString() {
         return MoreObjects.toStringHelper(this)
-            .add("responseCode", responseCode)
-            .add("serverResponseType", serverResponseType)
-            .add("tag", tag)
-            .add("textKey", textKey)
-            .add("command", command)
-            .toString();
+                .add("responseCode", responseCode)
+                .add("serverResponseType", serverResponseType)
+                .add("tag", tag)
+                .add("textKey", textKey)
+                .add("command", command)
+                .toString();
     }
 }
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/message/response/UnpooledStatusResponseFactory.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/message/response/UnpooledStatusResponseFactory.java
index 25e2566f95..189848e9dc 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/message/response/UnpooledStatusResponseFactory.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/message/response/UnpooledStatusResponseFactory.java
@@ -26,9 +26,13 @@ import 
org.apache.james.imap.api.message.response.StatusResponse;
 import org.apache.james.imap.api.message.response.StatusResponse.ResponseCode;
 import org.apache.james.imap.api.message.response.StatusResponse.Type;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class UnpooledStatusResponseFactory extends 
AbstractStatusResponseFactory implements StatusResponseFactory {
 
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(UnpooledStatusResponseFactory.class);
+
     @Override
     protected StatusResponse createResponse(Type type, Tag tag, ImapCommand 
command, HumanReadableText displayTextKey, ResponseCode code) {
         return new ImmutableStatusResponse(type, tag, command, displayTextKey, 
code);
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java
index bacc935d46..42278c4645 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java
@@ -444,14 +444,12 @@ public abstract class AbstractMailboxProcessor<R extends 
ImapRequest> extends Ab
 
     private MessageRange msnRangeToMessageRange(SelectedMailbox selected, long 
lowVal, long highVal)
             throws MessageRangeException {
-        // Take care of "*" and "*:*" values by return the last message in
-        // the mailbox. See IMAP-289
         if (lowVal == Long.MAX_VALUE && highVal == Long.MAX_VALUE) {
-            Optional<MessageUid> last = selected.getLastUid();
-            if (!last.isPresent()) {
-                throw new MessageRangeException("Mailbox is empty");
-            }
-            return last.get().toRange();
+            // Take care of "*" and "*:*" values by returning the last message 
in the mailbox. See IMAP-289
+            return 
selected.getLastUid().map(MessageRange::one).orElseGet(MessageRange::all);
+        } else if (lowVal == 1 && highVal == Long.MAX_VALUE) {
+            // Take care of "1:*" values by returning all messages in the 
mailbox. See IMAP-289
+            return MessageRange.all();
         }
 
         MessageUid lowUid = msnlowValToUid(selected, lowVal);
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/ContentBodyElement.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/ContentBodyElement.java
index 1aef078f8f..9aaa465170 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/ContentBodyElement.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/ContentBodyElement.java
@@ -62,4 +62,12 @@ class ContentBodyElement implements BodyElement {
     public InputStream getInputStream() throws IOException {
         return content.getInputStream();
     }
+
+    @Override
+    public String toString() {
+        return "ContentBodyElement{" +
+                "name='" + getName() + '\'' +
+                ", content=" + content +
+                '}';
+    }
 }
\ No newline at end of file
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java
index 800c036e14..ca5baf9183 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java
@@ -201,10 +201,9 @@ public class FetchProcessor extends 
AbstractMailboxProcessor<FetchRequest> {
         List<MessageRange> ranges = new ArrayList<>();
 
         for (IdRange range : request.getIdSet()) {
-            MessageRange messageSet = messageRange(session.getSelected(), 
range, request.isUseUids())
-                .orElseThrow(() -> new 
MessageRangeException(range.getFormattedString() + " is an invalid range"));
-            if (messageSet != null) {
-                MessageRange normalizedMessageSet = 
normalizeMessageRange(selected, messageSet);
+            Optional<MessageRange> messageSet = 
messageRange(session.getSelected(), range, request.isUseUids());
+            if (messageSet.isPresent()) {
+                MessageRange normalizedMessageSet = 
normalizeMessageRange(selected, messageSet.orElse(null));
                 MessageRange batchedMessageSet = 
MessageRange.range(normalizedMessageSet.getUidFrom(), 
normalizedMessageSet.getUidTo());
                 ranges.add(batchedMessageSet);
             }
diff --git 
a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ChannelImapResponseWriter.java
 
b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ChannelImapResponseWriter.java
index 55734944b8..3ab11de936 100644
--- 
a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ChannelImapResponseWriter.java
+++ 
b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ChannelImapResponseWriter.java
@@ -19,13 +19,19 @@
 
 package org.apache.james.imapserver.netty;
 
+import static 
org.apache.james.imapserver.netty.ImapChannelUpstreamHandler.retrieveUsername;
+
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.channels.FileChannel;
 
+import org.apache.james.imap.api.process.ImapSession;
 import org.apache.james.imap.encode.ImapResponseWriter;
 import org.apache.james.imap.message.Literal;
+import org.apache.james.util.MDCStructuredLogger;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import io.netty.buffer.Unpooled;
 import io.netty.channel.Channel;
@@ -46,9 +52,16 @@ public class ChannelImapResponseWriter implements 
ImapResponseWriter {
         void run() throws IOException;
     }
 
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(ChannelImapResponseWriter.class);
     private final Channel channel;
     private final boolean zeroCopy;
     private FlushCallback flushCallback;
+    private ImapSession imapSession = null;
+
+    public ChannelImapResponseWriter(Channel channel, ImapSession imapSession) 
{
+        this(channel);
+        this.imapSession = imapSession;
+    }
 
     public ChannelImapResponseWriter(Channel channel) {
         this(channel, true);
@@ -68,6 +81,13 @@ public class ChannelImapResponseWriter implements 
ImapResponseWriter {
 
     @Override
     public void write(byte[] buffer) {
+        if (LOGGER.isTraceEnabled()) {
+            if (imapSession != null) {
+                new MDCStructuredLogger(LOGGER)
+                        .field("username", retrieveUsername(imapSession))
+                        .log(logger -> logger.trace("Writing IMAP response: 
{}", new String(buffer)));
+            }
+        }
         if (channel.isActive()) {
             channel.writeAndFlush(Unpooled.wrappedBuffer(buffer));
         }
diff --git 
a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java
 
b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java
index d6110a4f1f..72a879205c 100644
--- 
a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java
+++ 
b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java
@@ -220,7 +220,7 @@ public class ImapChannelUpstreamHandler extends 
ChannelInboundHandlerAdapter imp
             LOGGER.info("Connection established from {}", 
address.getAddress().getHostAddress());
             imapConnectionsMetric.increment();
 
-            ChannelImapResponseWriter writer = new 
ChannelImapResponseWriter(ctx.channel());
+            ChannelImapResponseWriter writer = new 
ChannelImapResponseWriter(ctx.channel(), imapsession);
             ImapResponseComposerImpl response = new 
ImapResponseComposerImpl(writer);
             // write hello to client
             response.untagged().message("OK").message(hello).end();
@@ -286,7 +286,7 @@ public class ImapChannelUpstreamHandler extends 
ChannelInboundHandlerAdapter imp
         }
     }
 
-    private static String retrieveUsername(ImapSession imapSession) {
+    static String retrieveUsername(ImapSession imapSession) {
         return Optional.ofNullable(imapSession)
             .flatMap(session -> Optional.ofNullable(session.getUserName()))
             .map(Username::asString)
@@ -324,7 +324,7 @@ public class ImapChannelUpstreamHandler extends 
ChannelInboundHandlerAdapter imp
                 // command length."
                 //
                 // See also JAMES-1190
-                ChannelImapResponseWriter writer = new 
ChannelImapResponseWriter(ctx.channel());
+                ChannelImapResponseWriter writer = new 
ChannelImapResponseWriter(ctx.channel(), imapSession);
                 ImapResponseComposerImpl response = new 
ImapResponseComposerImpl(writer);
                 response.untaggedResponse(ImapConstants.BAD + " failed. 
Maximum command line length exceeded");
                 response.flush();
@@ -349,8 +349,9 @@ public class ImapChannelUpstreamHandler extends 
ChannelInboundHandlerAdapter imp
 
     private void manageRejectedException(ChannelHandlerContext ctx, 
ReactiveThrottler.RejectedException cause) throws IOException {
         if (cause.getImapMessage() instanceof AbstractImapRequest) {
+            ImapSession imapSession = 
ctx.channel().attr(IMAP_SESSION_ATTRIBUTE_KEY).get();
             AbstractImapRequest req = (AbstractImapRequest) 
cause.getImapMessage();
-            ChannelImapResponseWriter writer = new 
ChannelImapResponseWriter(ctx.channel());
+            ChannelImapResponseWriter writer = new 
ChannelImapResponseWriter(ctx.channel(), imapSession);
             ImapResponseComposerImpl response = new 
ImapResponseComposerImpl(writer);
             new ResponseEncoder(encoder, response)
                 .respond(new ImmutableStatusResponse(StatusResponse.Type.NO, 
req.getTag(), req.getCommand(),
@@ -404,7 +405,7 @@ public class ImapChannelUpstreamHandler extends 
ChannelInboundHandlerAdapter imp
             linearalizer.isExecutingRequest.set(true);
         }
 
-        ChannelImapResponseWriter writer = new 
ChannelImapResponseWriter(ctx.channel());
+        ChannelImapResponseWriter writer = new 
ChannelImapResponseWriter(ctx.channel(), session);
         ImapResponseComposerImpl response = new 
ImapResponseComposerImpl(writer);
         writer.setFlushCallback(response::flush);
         ImapMessage message = (ImapMessage) msg;


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

Reply via email to