You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2022/03/01 02:07:54 UTC

[james-project] branch master updated (a39fe45 -> c3087489)

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

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


    from a39fe45  [SONAR] Solve some minor warnings in server/data projects
     new d65b1a0  JAMES-3715 Adds tests for IMAP partial fetch over Netty transport
     new c3087489 JAMES-3715 PartialFetchBodyElement: use Optional to represent absence

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../imap/processor/fetch/FetchResponseBuilder.java |  3 +-
 .../processor/fetch/PartialFetchBodyElement.java   | 15 +++--
 .../fetch/PartialFetchBodyElementTest.java         | 50 +++++++++-----
 .../james/imapserver/netty/IMAPServerTest.java     | 77 ++++++++++++++++++++++
 .../org/apache/james/utils/TestIMAPClient.java     |  2 +-
 5 files changed, 120 insertions(+), 27 deletions(-)

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


[james-project] 02/02: JAMES-3715 PartialFetchBodyElement: use Optional to represent absence

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit c30874891307f077ea5060dac86988caafa30271
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Feb 24 09:25:05 2022 +0700

    JAMES-3715 PartialFetchBodyElement: use Optional to represent absence
    
    This makes the behaviour explicit and prevents mis-calculations down the
    line, and solves partial fetchs with only the offset (commons-net IMAP
    stack is happy...)
---
 .../imap/processor/fetch/FetchResponseBuilder.java |  3 +--
 .../processor/fetch/PartialFetchBodyElement.java   | 15 +++++++------
 .../fetch/PartialFetchBodyElementTest.java         | 25 +++++++++++-----------
 .../james/imapserver/netty/IMAPServerTest.java     |  2 --
 4 files changed, 21 insertions(+), 24 deletions(-)

diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchResponseBuilder.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchResponseBuilder.java
index fc26dd6..8182f5a 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchResponseBuilder.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchResponseBuilder.java
@@ -28,7 +28,6 @@ import java.util.Collection;
 import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Objects;
 import java.util.Optional;
 
 import javax.mail.Flags;
@@ -275,7 +274,7 @@ public final class FetchResponseBuilder {
         if (firstOctet == null) {
             return fullResult;
         }
-        final long numberOfOctetsAsLong = Objects.requireNonNullElse(numberOfOctets, Long.MAX_VALUE);
+        final Optional<Long> numberOfOctetsAsLong = Optional.ofNullable(numberOfOctets);
         final long firstOctetAsLong = firstOctet;
         return new PartialFetchBodyElement(fullResult, firstOctetAsLong, numberOfOctetsAsLong);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/PartialFetchBodyElement.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/PartialFetchBodyElement.java
index f2546cc..9d33e1f 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/PartialFetchBodyElement.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/PartialFetchBodyElement.java
@@ -22,6 +22,7 @@ package org.apache.james.imap.processor.fetch;
 import java.io.FilterInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Optional;
 
 import org.apache.james.imap.message.response.FetchResponse.BodyElement;
 
@@ -31,10 +32,10 @@ import org.apache.james.imap.message.response.FetchResponse.BodyElement;
 final class PartialFetchBodyElement implements BodyElement {
     private final BodyElement delegate;
     private final long firstOctet;
-    private final long numberOfOctets;
+    private final Optional<Long> numberOfOctets;
     private final String name;
 
-    public PartialFetchBodyElement(BodyElement delegate, long firstOctet, long numberOfOctets) {
+    public PartialFetchBodyElement(BodyElement delegate, long firstOctet, Optional<Long> numberOfOctets) {
         this.delegate = delegate;
         this.firstOctet = firstOctet;
         this.numberOfOctets = numberOfOctets;
@@ -49,14 +50,14 @@ final class PartialFetchBodyElement implements BodyElement {
     @Override
     public long size() throws IOException {
         final long size = delegate.size();
-        final long lastOctet = this.numberOfOctets + firstOctet;
+
         if (firstOctet > size) {
             return  0;
-        } else if (size > lastOctet) {
-            return numberOfOctets;
-        } else {
-            return size - firstOctet;
         }
+
+        return numberOfOctets
+            .map(requestedSize -> Math.min(requestedSize, size - firstOctet))
+            .orElse(size - firstOctet);
     }
 
     @Override
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/fetch/PartialFetchBodyElementTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/fetch/PartialFetchBodyElementTest.java
index a35226d..188d80b 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/fetch/PartialFetchBodyElementTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/fetch/PartialFetchBodyElementTest.java
@@ -23,9 +23,10 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import java.util.Optional;
+
 import org.apache.james.imap.message.response.FetchResponse.BodyElement;
 import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
 class PartialFetchBodyElementTest {
@@ -34,7 +35,7 @@ class PartialFetchBodyElementTest {
     BodyElement mockBodyElement;
 
     @BeforeEach
-    void setUp() throws Exception {
+    void setUp() {
         mockBodyElement = mock(BodyElement.class);
         when(mockBodyElement.getName()).thenReturn("Name");
     }
@@ -42,7 +43,7 @@ class PartialFetchBodyElementTest {
     @Test
     void testSizeShouldBeNumberOfOctetsWhenSizeMoreWhenStartIsZero() throws Exception {
         final long moreThanNumberOfOctets = NUMBER_OF_OCTETS + 1;
-        PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 0, NUMBER_OF_OCTETS);
+        PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 0, Optional.of(NUMBER_OF_OCTETS));
         when(mockBodyElement.size()).thenReturn(moreThanNumberOfOctets);
 
         assertThat(element.size()).describedAs("Size is more than number of octets so should be number of octets").isEqualTo(NUMBER_OF_OCTETS);
@@ -51,7 +52,7 @@ class PartialFetchBodyElementTest {
     @Test
     void testSizeShouldBeSizeWhenNumberOfOctetsMoreWhenStartIsZero() throws Exception {
         final long lessThanNumberOfOctets = NUMBER_OF_OCTETS - 1;
-        PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 0, NUMBER_OF_OCTETS);
+        PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 0, Optional.of(NUMBER_OF_OCTETS));
         when(mockBodyElement.size()).thenReturn(lessThanNumberOfOctets);
 
         assertThat(element.size()).describedAs("Size is less than number of octets so should be size").isEqualTo(lessThanNumberOfOctets);
@@ -60,7 +61,7 @@ class PartialFetchBodyElementTest {
     @Test
     void testWhenStartPlusNumberOfOctetsIsMoreThanSizeSizeShouldBeSizeMinusStart() throws Exception {
         final long size = 60;
-        PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 10, NUMBER_OF_OCTETS);
+        PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 10, Optional.of(NUMBER_OF_OCTETS));
         when(mockBodyElement.size()).thenReturn(size);
 
         assertThat(element.size()).describedAs("Size is less than number of octets so should be size").isEqualTo(50);
@@ -70,7 +71,7 @@ class PartialFetchBodyElementTest {
     void testWhenStartPlusNumberOfOctetsIsLessThanSizeSizeShouldBeNumberOfOctetsMinusStart()
         throws Exception {
         final long size = 100;
-        PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 10, NUMBER_OF_OCTETS);
+        PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 10, Optional.of(NUMBER_OF_OCTETS));
         when(mockBodyElement.size()).thenReturn(size);
 
         assertThat(element.size()).describedAs("Size is less than number of octets so should be size").isEqualTo(90);
@@ -79,16 +80,16 @@ class PartialFetchBodyElementTest {
     @Test
     void testSizeShouldBeZeroWhenStartIsMoreThanSize() throws Exception {
         final long size = 100;
-        PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 1000, NUMBER_OF_OCTETS);
+        PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 1000, Optional.of(NUMBER_OF_OCTETS));
         when(mockBodyElement.size()).thenReturn(size);
 
-        assertThat(element.size()).describedAs("Size is less than number of octets so should be size").isEqualTo(0);
+        assertThat(element.size()).describedAs("Size is less than number of octets so should be size").isZero();
     }
 
     @Test
     void testSizeShouldBeNumberOfOctetsWhenStartMoreThanOctets() throws Exception {
         final long size = 2000;
-        PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 1000, NUMBER_OF_OCTETS);
+        PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 1000, Optional.of(NUMBER_OF_OCTETS));
         when(mockBodyElement.size()).thenReturn(size);
 
         assertThat(element.size()).describedAs("Content size is less than start. Size should be zero.").isEqualTo(NUMBER_OF_OCTETS);
@@ -96,19 +97,17 @@ class PartialFetchBodyElementTest {
 
     @Test
     void testSizeShouldBeNumberOfOctetsWhenSizeMoreWhenStartIsZeroAndNoLimitSpecified() throws Exception {
-        PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 0, Long.MAX_VALUE);
+        PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 0, Optional.empty());
         when(mockBodyElement.size()).thenReturn(NUMBER_OF_OCTETS);
 
         assertThat(element.size()).describedAs("Size is more than number of octets so should be number of octets")
             .isEqualTo(NUMBER_OF_OCTETS);
     }
 
-    @Disabled("JAMES-3715 A bug due to usage of Long.MAX to represent a value that is absent prevents this" +
-        "from working decently. Returns 9223372036854775807L which cannot be parsed nor handled by IMAP clients.")
     @Test
     void testWhenStartPlusNumberOfOctetsIsMoreThanSizeSizeShouldBeSizeMinusStartAndNoLimitSpecified() throws Exception {
         final long size = 60;
-        PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 10, Long.MAX_VALUE);
+        PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 10, Optional.empty());
         when(mockBodyElement.size()).thenReturn(size);
 
         assertThat(element.size()).describedAs("Size is less than number of octets so should be size").isEqualTo(50);
diff --git a/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java b/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java
index 4094f8d..07f3bfa 100644
--- a/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java
+++ b/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java
@@ -204,8 +204,6 @@ class IMAPServerTest {
                 .contains("* 1 FETCH (FLAGS (\\Recent \\Seen) BODY[]<8> {12}\r\nvalue\r\n\r\nBOD)\r\n");
         }
 
-        @Disabled("JAMES-3715 A bug due to usage of Long.MAX to represent a value that is absent prevents this" +
-            "from working decently.")
         @Test
         void fetchShouldRetrieveMessageWhenOffsetAndNoLimitSpecified() throws Exception {
             testIMAPClient.connect("127.0.0.1", port)

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


[james-project] 01/02: JAMES-3715 Adds tests for IMAP partial fetch over Netty transport

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit d65b1a08178cbec530adfdeb3d6763e05518427a
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Feb 24 09:18:44 2022 +0700

    JAMES-3715 Adds tests for IMAP partial fetch over Netty transport
    
    Under some circumstances those broke with Netty4 and the little test
    suite introduced here reliably demonstrates this.
    
    Furthermore, we identified an issue regarding partial fetch when only
    the offset is specified. This is due to the usage of Long.MAX_VALUE to
    represent absence, and that causes some mis-calculations down the line.
---
 .../fetch/PartialFetchBodyElementTest.java         | 35 +++++++---
 .../james/imapserver/netty/IMAPServerTest.java     | 79 ++++++++++++++++++++++
 .../org/apache/james/utils/TestIMAPClient.java     |  2 +-
 3 files changed, 106 insertions(+), 10 deletions(-)

diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/fetch/PartialFetchBodyElementTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/fetch/PartialFetchBodyElementTest.java
index 5a8f2d4..a35226d 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/fetch/PartialFetchBodyElementTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/fetch/PartialFetchBodyElementTest.java
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.when;
 
 import org.apache.james.imap.message.response.FetchResponse.BodyElement;
 import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
 class PartialFetchBodyElementTest {
@@ -39,8 +40,7 @@ class PartialFetchBodyElementTest {
     }
 
     @Test
-    void testSizeShouldBeNumberOfOctetsWhenSizeMoreWhenStartIsZero()
-            throws Exception {
+    void testSizeShouldBeNumberOfOctetsWhenSizeMoreWhenStartIsZero() throws Exception {
         final long moreThanNumberOfOctets = NUMBER_OF_OCTETS + 1;
         PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 0, NUMBER_OF_OCTETS);
         when(mockBodyElement.size()).thenReturn(moreThanNumberOfOctets);
@@ -49,8 +49,7 @@ class PartialFetchBodyElementTest {
     }
 
     @Test
-    void testSizeShouldBeSizeWhenNumberOfOctetsMoreWhenStartIsZero()
-            throws Exception {
+    void testSizeShouldBeSizeWhenNumberOfOctetsMoreWhenStartIsZero() throws Exception {
         final long lessThanNumberOfOctets = NUMBER_OF_OCTETS - 1;
         PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 0, NUMBER_OF_OCTETS);
         when(mockBodyElement.size()).thenReturn(lessThanNumberOfOctets);
@@ -59,8 +58,7 @@ class PartialFetchBodyElementTest {
     }
 
     @Test
-    void testWhenStartPlusNumberOfOctetsIsMoreThanSizeSizeShouldBeSizeMinusStart()
-            throws Exception {
+    void testWhenStartPlusNumberOfOctetsIsMoreThanSizeSizeShouldBeSizeMinusStart() throws Exception {
         final long size = 60;
         PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 10, NUMBER_OF_OCTETS);
         when(mockBodyElement.size()).thenReturn(size);
@@ -70,7 +68,7 @@ class PartialFetchBodyElementTest {
 
     @Test
     void testWhenStartPlusNumberOfOctetsIsLessThanSizeSizeShouldBeNumberOfOctetsMinusStart()
-            throws Exception {
+        throws Exception {
         final long size = 100;
         PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 10, NUMBER_OF_OCTETS);
         when(mockBodyElement.size()).thenReturn(size);
@@ -88,12 +86,31 @@ class PartialFetchBodyElementTest {
     }
 
     @Test
-    void testSizeShouldBeNumberOfOctetsWhenStartMoreThanOctets()
-            throws Exception {
+    void testSizeShouldBeNumberOfOctetsWhenStartMoreThanOctets() throws Exception {
         final long size = 2000;
         PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 1000, NUMBER_OF_OCTETS);
         when(mockBodyElement.size()).thenReturn(size);
 
         assertThat(element.size()).describedAs("Content size is less than start. Size should be zero.").isEqualTo(NUMBER_OF_OCTETS);
     }
+
+    @Test
+    void testSizeShouldBeNumberOfOctetsWhenSizeMoreWhenStartIsZeroAndNoLimitSpecified() throws Exception {
+        PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 0, Long.MAX_VALUE);
+        when(mockBodyElement.size()).thenReturn(NUMBER_OF_OCTETS);
+
+        assertThat(element.size()).describedAs("Size is more than number of octets so should be number of octets")
+            .isEqualTo(NUMBER_OF_OCTETS);
+    }
+
+    @Disabled("JAMES-3715 A bug due to usage of Long.MAX to represent a value that is absent prevents this" +
+        "from working decently. Returns 9223372036854775807L which cannot be parsed nor handled by IMAP clients.")
+    @Test
+    void testWhenStartPlusNumberOfOctetsIsMoreThanSizeSizeShouldBeSizeMinusStartAndNoLimitSpecified() throws Exception {
+        final long size = 60;
+        PartialFetchBodyElement element = new PartialFetchBodyElement(mockBodyElement, 10, Long.MAX_VALUE);
+        when(mockBodyElement.size()).thenReturn(size);
+
+        assertThat(element.size()).describedAs("Size is less than number of octets so should be size").isEqualTo(50);
+    }
 }
diff --git a/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java b/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java
index 6222c4d..4094f8d 100644
--- a/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java
+++ b/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java
@@ -141,6 +141,85 @@ class IMAPServerTest {
     }
 
     @Nested
+    class PartialFetch {
+        IMAPServer imapServer;
+        private int port;
+
+        @BeforeEach
+        void beforeEach() throws Exception {
+            imapServer = createImapServer("imapServer.xml");
+            port = imapServer.getListenAddresses().get(0).getPort();
+        }
+
+        @AfterEach
+        void tearDown() {
+            imapServer.destroy();
+        }
+
+        @Test
+        void fetchShouldRetrieveMessage() throws Exception {
+            testIMAPClient.connect("127.0.0.1", port)
+                .login(USER.asString(), USER_PASS)
+                .append("INBOX", SMALL_MESSAGE);
+
+            assertThat(testIMAPClient
+                    .select("INBOX")
+                    .readFirstMessage())
+                .contains("* 1 FETCH (FLAGS (\\Recent \\Seen) BODY[] {21}\r\nheader: value\r\n\r\nBODY)\r\n");
+        }
+
+        @Test
+        void fetchShouldRetrieveMessageWhenOffsetAndLimitExceedingMessageSize() throws Exception {
+            testIMAPClient.connect("127.0.0.1", port)
+                .login(USER.asString(), USER_PASS)
+                .append("INBOX", SMALL_MESSAGE);
+
+            assertThat(testIMAPClient
+                    .select("INBOX")
+                    .readFirstMessageInMailbox("BODY[]<8.20>"))
+                .contains("* 1 FETCH (FLAGS (\\Recent \\Seen) BODY[]<8> {13}\r\nvalue\r\n\r\nBODY)\r\n");
+        }
+
+        @Test
+        void fetchShouldRetrieveMessageWhenOffsetAndLimitEqualMessageSize() throws Exception {
+            testIMAPClient.connect("127.0.0.1", port)
+                .login(USER.asString(), USER_PASS)
+                .append("INBOX", SMALL_MESSAGE);
+
+            assertThat(testIMAPClient
+                    .select("INBOX")
+                    .readFirstMessageInMailbox("BODY[]<8.13>"))
+                .contains("* 1 FETCH (FLAGS (\\Recent \\Seen) BODY[]<8> {13}\r\nvalue\r\n\r\nBODY)\r\n");
+        }
+
+        @Test
+        void fetchShouldRetrieveMessageWhenOffsetAndLimitBelowMessageSize() throws Exception {
+            testIMAPClient.connect("127.0.0.1", port)
+                .login(USER.asString(), USER_PASS)
+                .append("INBOX", SMALL_MESSAGE);
+
+            assertThat(testIMAPClient
+                    .select("INBOX")
+                    .readFirstMessageInMailbox("BODY[]<8.12>"))
+                .contains("* 1 FETCH (FLAGS (\\Recent \\Seen) BODY[]<8> {12}\r\nvalue\r\n\r\nBOD)\r\n");
+        }
+
+        @Disabled("JAMES-3715 A bug due to usage of Long.MAX to represent a value that is absent prevents this" +
+            "from working decently.")
+        @Test
+        void fetchShouldRetrieveMessageWhenOffsetAndNoLimitSpecified() throws Exception {
+            testIMAPClient.connect("127.0.0.1", port)
+                .login(USER.asString(), USER_PASS)
+                .append("INBOX", SMALL_MESSAGE);
+
+            assertThat(testIMAPClient
+                    .select("INBOX")
+                    .readFirstMessageInMailbox("BODY[]<8>"))
+                .contains("* 1 FETCH (FLAGS (\\Recent \\Seen) BODY[]<8> {13}\r\nvalue\r\n\r\nBODY)\r\n");
+        }
+    }
+
+    @Nested
     class NoLimit {
         IMAPServer imapServer;
         private int port;
diff --git a/server/testing/src/main/java/org/apache/james/utils/TestIMAPClient.java b/server/testing/src/main/java/org/apache/james/utils/TestIMAPClient.java
index 72f1c79..25041a5 100644
--- a/server/testing/src/main/java/org/apache/james/utils/TestIMAPClient.java
+++ b/server/testing/src/main/java/org/apache/james/utils/TestIMAPClient.java
@@ -220,7 +220,7 @@ public class TestIMAPClient extends ExternalResource implements Closeable, After
         return imapClient.getReplyString();
     }
 
-    private String readFirstMessageInMailbox(String parameters) throws IOException {
+    public String readFirstMessageInMailbox(String parameters) throws IOException {
         imapClient.fetch("1:1", parameters);
         return imapClient.getReplyString();
     }

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