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
The following commit(s) were added to refs/heads/master by this push:
new a190bf8555 JAMES-2128 IMAP list should skip mailboxes not handled by
the naming schema (#2506)
a190bf8555 is described below
commit a190bf855565225696b76f66b1ef0834078b7cfb
Author: Benoit TELLIER <[email protected]>
AuthorDate: Tue Nov 19 15:07:57 2024 +0700
JAMES-2128 IMAP list should skip mailboxes not handled by the naming schema
(#2506)
---
.../org/apache/james/imap/main/PathConverter.java | 9 +++--
.../apache/james/imap/processor/LSubProcessor.java | 2 +-
.../apache/james/imap/processor/ListProcessor.java | 46 ++++++++++++----------
.../james/imap/processor/StatusProcessor.java | 5 ++-
.../apache/james/imap/main/PathConverterTest.java | 28 ++++++-------
5 files changed, 49 insertions(+), 41 deletions(-)
diff --git
a/protocols/imap/src/main/java/org/apache/james/imap/main/PathConverter.java
b/protocols/imap/src/main/java/org/apache/james/imap/main/PathConverter.java
index 5164f14602..7987eafd24 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/main/PathConverter.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/main/PathConverter.java
@@ -20,6 +20,7 @@
package org.apache.james.imap.main;
import java.util.List;
+import java.util.Optional;
import org.apache.james.core.Domain;
import org.apache.james.core.Username;
@@ -160,11 +161,11 @@ public interface PathConverter {
return sb.toString();
}
- public String mailboxName(boolean relative, MailboxPath path,
MailboxSession session) {
+ public Optional<String> mailboxName(boolean relative, MailboxPath
path, MailboxSession session) {
if (relative && path.belongsTo(session)) {
- return path.getName();
+ return Optional.of(path.getName());
} else {
- return joinMailboxPath(path, session);
+ return Optional.of(joinMailboxPath(path, session));
}
}
@@ -250,7 +251,7 @@ public interface PathConverter {
MailboxPath buildFullPath(String mailboxName);
- String mailboxName(boolean relative, MailboxPath path, MailboxSession
session);
+ Optional<String> mailboxName(boolean relative, MailboxPath path,
MailboxSession session);
MailboxQuery mailboxQuery(String finalReferencename, String mailboxName,
ImapSession session);
}
diff --git
a/protocols/imap/src/main/java/org/apache/james/imap/processor/LSubProcessor.java
b/protocols/imap/src/main/java/org/apache/james/imap/processor/LSubProcessor.java
index 581b0472e0..1ba7850434 100644
---
a/protocols/imap/src/main/java/org/apache/james/imap/processor/LSubProcessor.java
+++
b/protocols/imap/src/main/java/org/apache/james/imap/processor/LSubProcessor.java
@@ -81,7 +81,7 @@ public class LSubProcessor extends
AbstractMailboxProcessor<LsubRequest> {
try {
PathConverter pathConverter =
pathConverterFactory.forSession(session);
Mono<List<String>> mailboxesMono =
Flux.from(subscriptionManager.subscriptionsReactive(mailboxSession))
- .map(path -> pathConverter.mailboxName(RELATIVE, path,
mailboxSession))
+ .<String>handle((path, sink) ->
pathConverter.mailboxName(RELATIVE, path, mailboxSession).ifPresent(sink::next))
.collectList();
String decodedMailName =
ModifiedUtf7.decodeModifiedUTF7(referenceName);
diff --git
a/protocols/imap/src/main/java/org/apache/james/imap/processor/ListProcessor.java
b/protocols/imap/src/main/java/org/apache/james/imap/processor/ListProcessor.java
index ee3cce3edc..17c92b022a 100644
---
a/protocols/imap/src/main/java/org/apache/james/imap/processor/ListProcessor.java
+++
b/protocols/imap/src/main/java/org/apache/james/imap/processor/ListProcessor.java
@@ -213,13 +213,14 @@ public class ListProcessor<T extends ListRequest> extends
AbstractMailboxProcess
.doOnNext(metaData -> {
MailboxType mailboxType = getMailboxType(request, session,
metaData.getPath());
if (!request.getSelectOptions().contains(SPECIAL_USE) ||
mailboxType.getRfc6154attributeName() != null) {
- responder.respond(
- createResponse(metaData.inferiors(),
- metaData.getSelectability(),
-
pathConverterFactory.forSession(session).mailboxName(isRelative,
metaData.getPath(), mailboxSession),
- metaData.getHierarchyDelimiter(),
- mailboxType,
- isSubscribed.test(metaData.getPath())));
+
pathConverterFactory.forSession(session).mailboxName(isRelative,
metaData.getPath(), mailboxSession)
+ .ifPresent(mailboxName -> responder.respond(
+ createResponse(metaData.inferiors(),
+ metaData.getSelectability(),
+ mailboxName,
+ metaData.getHierarchyDelimiter(),
+ mailboxType,
+ isSubscribed.test(metaData.getPath()))));
}
})
.doOnNext(metaData -> respondMyRights(request, responder,
mailboxSession, metaData, isRelative))
@@ -267,23 +268,24 @@ public class ListProcessor<T extends ListRequest> extends
AbstractMailboxProcess
allSubscribedSearch.stream()
.filter(subscribed -> !listRecursiveMatchPath.contains(subscribed))
.filter(mailboxQuery::isPathMatch)
- .map(subscribed -> buildListResponse(listRequest,
searchedResultMap, session, relative, subscribed))
+ .flatMap(subscribed -> buildListResponse(listRequest,
searchedResultMap, session, relative, subscribed).stream())
.filter(pair ->
!listRequest.getSelectOptions().contains(SPECIAL_USE) ||
mailboxTyper.getMailboxType(session, pair.getKey()).getRfc6154attributeName()
!= null)
.forEach(pair -> responseBuilders.add(Triple.of(pair.getLeft(),
pair.getRight(), Optional.ofNullable(searchedResultMap.get(pair.getLeft())))));
return responseBuilders.build();
}
- private Pair<MailboxPath, ListResponse> buildListResponse(ListRequest
listRequest, Map<MailboxPath, MailboxMetaData> searchedResultMap, ImapSession
session, boolean relative, MailboxPath subscribed) {
- return Pair.of(subscribed,
Optional.ofNullable(searchedResultMap.get(subscribed))
+ private Optional<Pair<MailboxPath, ListResponse>>
buildListResponse(ListRequest listRequest, Map<MailboxPath, MailboxMetaData>
searchedResultMap, ImapSession session, boolean relative, MailboxPath
subscribed) {
+ return pathConverterFactory.forSession(session).mailboxName(relative,
subscribed, session.getMailboxSession())
+ .map(name -> Pair.of(subscribed,
Optional.ofNullable(searchedResultMap.get(subscribed))
.map(mailboxMetaData -> ListResponse.builder()
.returnSubscribed(RETURN_SUBSCRIBED)
.forMetaData(mailboxMetaData)
-
.name(pathConverterFactory.forSession(session).mailboxName(relative,
subscribed, session.getMailboxSession()))
+ .name(name)
.returnNonExistent(!RETURN_NON_EXISTENT)
.mailboxType(getMailboxType(listRequest, session,
mailboxMetaData.getPath())))
.orElseGet(() ->
ListResponse.builder().nonExitingSubscribedMailbox(subscribed))
- .build());
+ .build()));
}
private List<Pair<MailboxPath, ListResponse>>
listRecursiveMatch(ImapSession session, Map<MailboxPath, MailboxMetaData>
searchedResultMap,
@@ -299,26 +301,28 @@ public class ListProcessor<T extends ListRequest> extends
AbstractMailboxProcess
return searchedResultMap.entrySet().stream()
.filter(pair -> allSubscribedSearchParent.contains(pair.getKey()))
- .map(pair -> {
+ .flatMap(pair -> {
MailboxMetaData metaData = pair.getValue();
- ListResponse listResponse = ListResponse.builder()
+ Optional<String> maybeMailboxName =
pathConverterFactory.forSession(session).mailboxName(relative,
metaData.getPath(), mailboxSession);
+ return maybeMailboxName.map(mailboxName ->
Pair.of(pair.getKey(), ListResponse.builder()
.forMetaData(metaData)
-
.name(pathConverterFactory.forSession(session).mailboxName(relative,
metaData.getPath(), mailboxSession))
+ .name(mailboxName)
.childInfos(ListResponse.ChildInfo.SUBSCRIBED)
.returnSubscribed(allSubscribedSearch.contains(pair.getKey()))
.mailboxType(getMailboxType(listRequest, session,
metaData.getPath()))
- .build();
- return Pair.of(pair.getKey(), listResponse);
+ .build()))
+ .stream();
})
.collect(Collectors.toList());
}
private void respondMyRights(T request, Responder responder,
MailboxSession mailboxSession, MailboxMetaData metaData, boolean isRelative) {
if
(request.getReturnOptions().contains(ListRequest.ListReturnOption.MYRIGHTS)) {
- MailboxName mailboxName = new
MailboxName(pathConverterFactory.forSession(mailboxSession)
- .mailboxName(isRelative, metaData.getPath(), mailboxSession));
- MyRightsResponse myRightsResponse = new
MyRightsResponse(mailboxName, getRfc4314Rights(mailboxSession, metaData));
- responder.respond(myRightsResponse);
+ pathConverterFactory.forSession(mailboxSession)
+ .mailboxName(isRelative, metaData.getPath(), mailboxSession)
+ .map(MailboxName::new)
+ .map(mailboxName -> new MyRightsResponse(mailboxName,
getRfc4314Rights(mailboxSession, metaData)))
+ .ifPresent(responder::respond);
}
}
diff --git
a/protocols/imap/src/main/java/org/apache/james/imap/processor/StatusProcessor.java
b/protocols/imap/src/main/java/org/apache/james/imap/processor/StatusProcessor.java
index bade56b99b..2c8d0ac79c 100644
---
a/protocols/imap/src/main/java/org/apache/james/imap/processor/StatusProcessor.java
+++
b/protocols/imap/src/main/java/org/apache/james/imap/processor/StatusProcessor.java
@@ -186,12 +186,15 @@ public class StatusProcessor extends
AbstractMailboxProcessor<StatusRequest> imp
Long unseen = unseen(statusDataItems, metaData);
ModSeq highestModSeq = highestModSeq(statusDataItems,
metaData);
MailboxId mailboxId = mailboxId(statusDataItems, mailbox);
+ String mailboxName =
pathConverterFactory.forSession(mailboxSession)
+ .mailboxName(RELATIVE, mailbox.getMailboxPath(),
mailboxSession)
+ .orElseThrow(() -> new RuntimeException("Not exposed
mailbox"));
return new MailboxStatusResponse(
appendLimit,
maybeIterationResult.flatMap(result ->
result.getSize(statusDataItems)).orElse(null),
maybeIterationResult.flatMap(result ->
result.getDeleted(statusDataItems)).orElse(null),
maybeIterationResult.flatMap(result ->
result.getDeletedStorage(statusDataItems)).orElse(null),
- messages, recent, uidNext, highestModSeq, uidValidity,
unseen, pathConverterFactory.forSession(mailboxSession).mailboxName(RELATIVE,
mailbox.getMailboxPath(), mailboxSession), mailboxId);
+ messages, recent, uidNext, highestModSeq, uidValidity,
unseen, mailboxName, mailboxId);
});
}
diff --git
a/protocols/imap/src/test/java/org/apache/james/imap/main/PathConverterTest.java
b/protocols/imap/src/test/java/org/apache/james/imap/main/PathConverterTest.java
index 02a9a12807..3541ad53e3 100644
---
a/protocols/imap/src/test/java/org/apache/james/imap/main/PathConverterTest.java
+++
b/protocols/imap/src/test/java/org/apache/james/imap/main/PathConverterTest.java
@@ -137,49 +137,49 @@ class PathConverterTest {
@Test
void mailboxNameShouldReturnNameOnlyWhenRelativeAndUserMailbox() {
assertThat(pathConverter.mailboxName(RELATIVE,
MailboxPath.forUser(USERNAME, "abc"), mailboxSession))
- .isEqualTo("abc");
+ .contains("abc");
}
@Test
void mailboxNameShouldReturnFQDNWhenRelativeAndOtherUserMailbox() {
assertThat(pathConverter.mailboxName(RELATIVE,
MailboxPath.forUser(USERNAME2, "abc"), mailboxSession))
- .isEqualTo("#user.username2.abc");
+ .contains("#user.username2.abc");
}
@Test
void mailboxNameShouldEscapeDotInUsername() {
assertThat(pathConverter.mailboxName(RELATIVE,
MailboxPath.forUser(USERNAME_WITH_DOT, "abc"), mailboxSession))
- .isEqualTo("#user.username__with__dot.abc");
+ .contains("#user.username__with__dot.abc");
}
@Test
void mailboxNameShouldEscapeUnderscoreInUsername() {
assertThat(pathConverter.mailboxName(RELATIVE,
MailboxPath.forUser(USERNAME_WITH_UNDERSCORE, "abc"), mailboxSession))
- .isEqualTo("#user.username_-with_-underscore.abc");
+ .contains("#user.username_-with_-underscore.abc");
}
@Test
void mailboxNameShouldReturnFQDNWhenRelativeAndSharedMailbox() {
assertThat(pathConverter.mailboxName(RELATIVE, new
MailboxPath("#Shared", Username.of("marketing"), "abc"), mailboxSession))
- .isEqualTo("#Shared.marketing.abc");
+ .contains("#Shared.marketing.abc");
}
@Test
void mailboxNameShouldReturnFQDNWhenNotRelativeAndUserMailbox() {
assertThat(pathConverter.mailboxName(!RELATIVE,
MailboxPath.forUser(USERNAME, "abc"), mailboxSession))
- .isEqualTo("#private.abc");
+ .contains("#private.abc");
}
@Test
void mailboxNameShouldReturnFQDNWhenNotRelativeAndOtherUserMailbox() {
assertThat(pathConverter.mailboxName(!RELATIVE,
MailboxPath.forUser(USERNAME2, "abc"), mailboxSession))
- .isEqualTo("#user.username2.abc");
+ .contains("#user.username2.abc");
}
@Test
void mailboxNameShouldReturnFQDNWhenNotRelativeAndSharedMailbox() {
assertThat(pathConverter.mailboxName(!RELATIVE, new
MailboxPath("#Shared", Username.of("marketing"), "abc"), mailboxSession))
- .isEqualTo("#Shared.marketing.abc");
+ .contains("#Shared.marketing.abc");
}
@Nested
@@ -257,37 +257,37 @@ class PathConverterTest {
@Test
void mailboxNameShouldReturnNameOnlyWhenRelativeAndUserMailbox() {
assertThat(pathConverter.mailboxName(RELATIVE,
MailboxPath.forUser(USERNAME_WITH_MAIL, "abc"), mailboxSession))
- .isEqualTo("abc");
+ .contains("abc");
}
@Test
void mailboxNameShouldReturnFQDNWhenRelativeAndOtherUserMailbox() {
assertThat(pathConverter.mailboxName(RELATIVE,
MailboxPath.forUser(USERNAME2_WITH_MAIL, "abc"), mailboxSession))
- .isEqualTo("#user.username2.abc");
+ .contains("#user.username2.abc");
}
@Test
void mailboxNameShouldReturnFQDNWhenRelativeAndSharedMailbox() {
assertThat(pathConverter.mailboxName(RELATIVE, new
MailboxPath("#Shared", Username.of("[email protected]"), "abc"),
mailboxSession))
- .isEqualTo("#Shared.marketing.abc");
+ .contains("#Shared.marketing.abc");
}
@Test
void mailboxNameShouldReturnFQDNWhenNotRelativeAndUserMailbox() {
assertThat(pathConverter.mailboxName(!RELATIVE,
MailboxPath.forUser(USERNAME_WITH_MAIL, "abc"), mailboxSession))
- .isEqualTo("#private.abc");
+ .contains("#private.abc");
}
@Test
void mailboxNameShouldReturnFQDNWhenNotRelativeAndOtherUserMailbox() {
assertThat(pathConverter.mailboxName(!RELATIVE,
MailboxPath.forUser(USERNAME2_WITH_MAIL, "abc"), mailboxSession))
- .isEqualTo("#user.username2.abc");
+ .contains("#user.username2.abc");
}
@Test
void mailboxNameShouldReturnFQDNWhenNotRelativeAndSharedMailbox() {
assertThat(pathConverter.mailboxName(!RELATIVE, new
MailboxPath("#Shared", Username.of("[email protected]"), "abc"),
mailboxSession))
- .isEqualTo("#Shared.marketing.abc");
+ .contains("#Shared.marketing.abc");
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]