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 e13beea8c6 JAMES-4050 Allow `%` and `*` characters in mailbox names e13beea8c6 is described below commit e13beea8c6b42c3246b00d4427b9d7492f086f14 Author: Quan Tran <hqt...@linagora.com> AuthorDate: Tue Aug 27 14:50:34 2024 +0700 JAMES-4050 Allow `%` and `*` characters in mailbox names --- .../servers/pages/distributed/configure/jvm.adoc | 14 ++++- .../apache/james/mailbox/model/MailboxPath.java | 10 +++- .../james/mailbox/model/MailboxPathTest.java | 16 ++++++ .../suite/ListingWithRelaxedMailboxName.java | 55 ++++++++++++++++++ .../ListWithPercentWildcardInMailboxName.test | 67 ++++++++++++++++++++++ mpt/impl/imap-mailbox/inmemory/pom.xml | 2 +- .../InMemoryListingWithRelaxedMailboxNameTest.java | 45 +++++++++++++++ .../docker-configuration/jvm.properties | 6 +- .../sample-configuration/jvm.properties | 6 +- .../docker-configuration/jvm.properties | 4 ++ .../sample-configuration/jvm.properties | 6 +- .../docker-configuration/jvm.properties | 4 ++ .../sample-configuration/jvm.properties | 6 +- .../jpa-app/sample-configuration/jvm.properties | 6 +- .../memory-app/sample-configuration/jvm.properties | 6 +- 15 files changed, 244 insertions(+), 9 deletions(-) diff --git a/docs/modules/servers/pages/distributed/configure/jvm.adoc b/docs/modules/servers/pages/distributed/configure/jvm.adoc index 7aefd940bc..58aac81469 100644 --- a/docs/modules/servers/pages/distributed/configure/jvm.adoc +++ b/docs/modules/servers/pages/distributed/configure/jvm.adoc @@ -118,4 +118,16 @@ Ex in `jvm.properties` ---- james.mailet.container.check.enabled=false ---- -To disable the mailet container check at James startup. \ No newline at end of file +To disable the mailet container check at James startup. + +== Relax mailbox name validation + +The property `james.relaxed.mailbox.name.validation` allows to accept `*` and `%` characters in mailbox name. + +Optional. Boolean. Default to false. + +Ex in `jvm.properties` +---- +james.relaxed.mailbox.name.validation=true +---- +To relax validating `\*` and `%` characters in the mailbox name. Be careful as `%` and `*` are ambiguous for the LIST / LSUB commands that interpret those as wildcard thus returning all mailboxes matching the pattern. \ No newline at end of file diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxPath.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxPath.java index bba81a2082..d43641de5d 100644 --- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxPath.java +++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxPath.java @@ -51,6 +51,7 @@ public class MailboxPath { private static final Joiner PARTS_JOINER = Joiner.on(':'); private static final LookupTranslator USERNAME_ESCAPER = new LookupTranslator(Map.of(":", "/;", "/", "//")); private static final LookupTranslator USERNAME_UNESCAPER = new LookupTranslator(Map.of("/;", ":", "//", "/")); + private static final boolean RELAX_MAILBOX_NAME_VALIDATION = Boolean.parseBoolean(System.getProperty("james.relaxed.mailbox.name.validation", "false")); /** * Return a {@link MailboxPath} which represent the INBOX of the given @@ -94,7 +95,14 @@ public class MailboxPath { return Username.of(USERNAME_UNESCAPER.translate(parts.get(1))); } - private static final String INVALID_CHARS = "%*\r\n"; + private static String evaluateInvalidChars() { + if (RELAX_MAILBOX_NAME_VALIDATION) { + return "\r\n"; + } + return "%*\r\n"; + } + + private static final String INVALID_CHARS = evaluateInvalidChars(); private static final CharMatcher INVALID_CHARS_MATCHER = CharMatcher.anyOf(INVALID_CHARS); // This is the size that all mailbox backend should support public static final int MAX_MAILBOX_NAME_LENGTH = 200; diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxPathTest.java b/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxPathTest.java index d679f1c491..676db676be 100644 --- a/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxPathTest.java +++ b/mailbox/api/src/test/java/org/apache/james/mailbox/model/MailboxPathTest.java @@ -373,6 +373,14 @@ class MailboxPathTest { .isInstanceOf(MailboxNameException.class); } + @Test + void assertAcceptableShouldNotThrowOnPercentWhenRelaxMode() { + System.setProperty("james.relaxed.mailbox.name.validation", "true"); + + assertThatCode(() -> MailboxPath.forUser(USER, "a%b")) + .doesNotThrowAnyException(); + } + @Test void assertAcceptableShouldThrowOnWildcard() { assertThatThrownBy(() -> MailboxPath.forUser(USER, "a*b") @@ -380,6 +388,14 @@ class MailboxPathTest { .isInstanceOf(MailboxNameException.class); } + @Test + void assertAcceptableShouldNotThrowOnWildcardWhenRelaxMode() { + System.setProperty("james.relaxed.mailbox.name.validation", "true"); + + assertThatCode(() -> MailboxPath.forUser(USER, "a*b")) + .doesNotThrowAnyException(); + } + @Test void assertAcceptableShouldThrowOnTooLongMailboxName() { assertThatThrownBy(() -> MailboxPath.forUser(USER, Strings.repeat("a", 201)) diff --git a/mpt/impl/imap-mailbox/core/src/main/java/org/apache/james/mpt/imapmailbox/suite/ListingWithRelaxedMailboxName.java b/mpt/impl/imap-mailbox/core/src/main/java/org/apache/james/mpt/imapmailbox/suite/ListingWithRelaxedMailboxName.java new file mode 100644 index 0000000000..4fa368b3ae --- /dev/null +++ b/mpt/impl/imap-mailbox/core/src/main/java/org/apache/james/mpt/imapmailbox/suite/ListingWithRelaxedMailboxName.java @@ -0,0 +1,55 @@ +/**************************************************************** + * 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.mpt.imapmailbox.suite; + +import java.util.Locale; + +import org.apache.james.mpt.api.ImapHostSystem; +import org.apache.james.mpt.imapmailbox.ImapTestConstants; +import org.apache.james.mpt.imapmailbox.suite.base.BasicImapCommands; +import org.apache.james.mpt.script.SimpleScriptedTestProtocol; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public abstract class ListingWithRelaxedMailboxName implements ImapTestConstants { + + protected abstract ImapHostSystem createImapHostSystem(); + + protected ImapHostSystem system; + protected SimpleScriptedTestProtocol simpleScriptedTestProtocol; + + @BeforeEach + public void setUp() throws Exception { + System.setProperty("james.relaxed.mailbox.name.validation", "true"); + + system = createImapHostSystem(); + simpleScriptedTestProtocol = new SimpleScriptedTestProtocol("/org/apache/james/imap/scripts/", system) + .withUser(USER, PASSWORD); + BasicImapCommands.welcome(simpleScriptedTestProtocol); + BasicImapCommands.authenticate(simpleScriptedTestProtocol); + } + + @Test + public void testListWithPercentWildcardInMailboxNameUS() throws Exception { + simpleScriptedTestProtocol + .withLocale(Locale.US) + .run("ListWithPercentWildcardInMailboxName"); + } +} diff --git a/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/ListWithPercentWildcardInMailboxName.test b/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/ListWithPercentWildcardInMailboxName.test new file mode 100644 index 0000000000..d716d2a108 --- /dev/null +++ b/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/ListWithPercentWildcardInMailboxName.test @@ -0,0 +1,67 @@ +# Test creating and searching mailboxes with literal '*' and '%' characters in their names +C: B01 CREATE "star*mailbox" +S: B01 OK \[MAILBOXID \(.+\)\] CREATE completed. +C: B011 CREATE "starmailbox" +S: B011 OK \[MAILBOXID \(.+\)\] CREATE completed. +C: B02 CREATE "percent%mailbox" +S: B02 OK \[MAILBOXID \(.+\)\] CREATE completed. +C: B021 CREATE "percentmailbox" +S: B021 OK \[MAILBOXID \(.+\)\] CREATE completed. + +C: B03 LIST "" "star*mailbox" +SUB { +S: \* LIST \(\\HasNoChildren\) \"\.\" \"star\*mailbox\" +S: \* LIST \(\\HasNoChildren\) \"\.\" \"starmailbox\" +} +S: B03 OK LIST completed. + +C: B04 LIST "" "percent%mailbox" +SUB { +S: \* LIST \(\\HasNoChildren\) \"\.\" \"percent%mailbox\" +S: \* LIST \(\\HasNoChildren\) \"\.\" \"percentmailbox\" +} +S: B04 OK LIST completed. + +C: B05 LIST "" % +SUB { +S: \* LIST \(\\HasNoChildren\) \"\.\" \"star\*mailbox\" +S: \* LIST \(\\HasNoChildren\) \"\.\" \"starmailbox\" +S: \* LIST \(\\HasNoChildren\) \"\.\" \"percent%mailbox\" +S: \* LIST \(\\HasNoChildren\) \"\.\" \"percentmailbox\" +S: \* LIST \(\\HasNoChildren\) \"\.\" \"INBOX\" +} +S: B05 OK LIST completed. + +C: B06 LIST "" * +SUB { +S: \* LIST \(\\HasNoChildren\) \"\.\" \"star\*mailbox\" +S: \* LIST \(\\HasNoChildren\) \"\.\" \"starmailbox\" +S: \* LIST \(\\HasNoChildren\) \"\.\" \"percent%mailbox\" +S: \* LIST \(\\HasNoChildren\) \"\.\" \"percentmailbox\" +S: \* LIST \(\\HasNoChildren\) \"\.\" \"INBOX\" +} +S: B06 OK LIST completed. + +C: B07 LIST "" "star*mail%" +SUB { +S: \* LIST \(\\HasNoChildren\) \"\.\" \"star\*mailbox\" +S: \* LIST \(\\HasNoChildren\) \"\.\" \"starmailbox\" +} +S: B07 OK LIST completed. + +C: B08 LIST "" "percent%mail*" +SUB { +S: \* LIST \(\\HasNoChildren\) \"\.\" \"percent%mailbox\" +S: \* LIST \(\\HasNoChildren\) \"\.\" \"percentmailbox\" +} +S: B08 OK LIST completed. + +# Cleanup +C: D9 DELETE "star*mailbox" +S: D9 OK DELETE completed. +C: D10 DELETE "starmailbox" +S: D10 OK DELETE completed. +C: D11 DELETE "percent%mailbox" +S: D11 OK DELETE completed. +C: D12 DELETE "percentmailbox" +S: D12 OK DELETE completed. \ No newline at end of file diff --git a/mpt/impl/imap-mailbox/inmemory/pom.xml b/mpt/impl/imap-mailbox/inmemory/pom.xml index 5ce1fd9fa5..b814ece20d 100644 --- a/mpt/impl/imap-mailbox/inmemory/pom.xml +++ b/mpt/impl/imap-mailbox/inmemory/pom.xml @@ -81,7 +81,7 @@ <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> - <reuseForks>true</reuseForks> + <reuseForks>false</reuseForks> <forkCount>1C</forkCount> </configuration> </plugin> diff --git a/mpt/impl/imap-mailbox/inmemory/src/test/java/org/apache/james/mpt/imapmailbox/inmemory/InMemoryListingWithRelaxedMailboxNameTest.java b/mpt/impl/imap-mailbox/inmemory/src/test/java/org/apache/james/mpt/imapmailbox/inmemory/InMemoryListingWithRelaxedMailboxNameTest.java new file mode 100644 index 0000000000..e757e5322d --- /dev/null +++ b/mpt/impl/imap-mailbox/inmemory/src/test/java/org/apache/james/mpt/imapmailbox/inmemory/InMemoryListingWithRelaxedMailboxNameTest.java @@ -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. * + ****************************************************************/ + +package org.apache.james.mpt.imapmailbox.inmemory; + +import org.apache.james.mpt.api.ImapHostSystem; +import org.apache.james.mpt.imapmailbox.inmemory.host.InMemoryHostSystem; +import org.apache.james.mpt.imapmailbox.suite.ListingWithRelaxedMailboxName; +import org.junit.jupiter.api.BeforeEach; + +public class InMemoryListingWithRelaxedMailboxNameTest extends ListingWithRelaxedMailboxName { + private ImapHostSystem system; + + @Override + @BeforeEach + public void setUp() throws Exception { + System.setProperty("james.relaxed.mailbox.name.validation", "true"); + + system = new InMemoryHostSystem(); + system.beforeTest(); + super.setUp(); + } + + @Override + protected ImapHostSystem createImapHostSystem() { + return system; + } + +} diff --git a/server/apps/cassandra-app/docker-configuration/jvm.properties b/server/apps/cassandra-app/docker-configuration/jvm.properties index 7e3e6463ef..f638855ef4 100644 --- a/server/apps/cassandra-app/docker-configuration/jvm.properties +++ b/server/apps/cassandra-app/docker-configuration/jvm.properties @@ -45,4 +45,8 @@ config.file=/root/conf/cassandra-driver.conf # JMX, when enable causes RMI to plan System.gc every hour. Set this instead to once every 1000h. sun.rmi.dgc.server.gcInterval=3600000000 -sun.rmi.dgc.client.gcInterval=3600000000 \ No newline at end of file +sun.rmi.dgc.client.gcInterval=3600000000 + +# Relax validating `*` and `%` characters in the mailbox name. Defaults to false. +# Be careful turning on this as `%` and `*` are ambiguous for the LIST / LSUB commands that interpret those as wildcard thus returning all mailboxes matching the pattern. +#james.relaxed.mailbox.name.validation=true \ No newline at end of file diff --git a/server/apps/cassandra-app/sample-configuration/jvm.properties b/server/apps/cassandra-app/sample-configuration/jvm.properties index 7cef86567a..3cc3d17386 100644 --- a/server/apps/cassandra-app/sample-configuration/jvm.properties +++ b/server/apps/cassandra-app/sample-configuration/jvm.properties @@ -68,4 +68,8 @@ jmx.remote.x.mlet.allow.getMBeansFromURL=false # james.jwt.zip.allow=false # Enable/disable mailet container check at James startup. Defaults to true. -# james.mailet.container.check.enabled=true \ No newline at end of file +# james.mailet.container.check.enabled=true + +# Relax validating `*` and `%` characters in the mailbox name. Defaults to false. +# Be careful turning on this as `%` and `*` are ambiguous for the LIST / LSUB commands that interpret those as wildcard thus returning all mailboxes matching the pattern. +#james.relaxed.mailbox.name.validation=true \ No newline at end of file diff --git a/server/apps/distributed-app/docker-configuration/jvm.properties b/server/apps/distributed-app/docker-configuration/jvm.properties index 93165bbf95..b7183468f0 100644 --- a/server/apps/distributed-app/docker-configuration/jvm.properties +++ b/server/apps/distributed-app/docker-configuration/jvm.properties @@ -46,3 +46,7 @@ config.file=/root/conf/cassandra-driver.conf # JMX, when enable causes RMI to plan System.gc every hour. Set this instead to once every 1000h. sun.rmi.dgc.server.gcInterval=3600000000 sun.rmi.dgc.client.gcInterval=3600000000 + +# Relax validating `*` and `%` characters in the mailbox name. Defaults to false. +# Be careful turning on this as `%` and `*` are ambiguous for the LIST / LSUB commands that interpret those as wildcard thus returning all mailboxes matching the pattern. +#james.relaxed.mailbox.name.validation=true \ No newline at end of file diff --git a/server/apps/distributed-app/sample-configuration/jvm.properties b/server/apps/distributed-app/sample-configuration/jvm.properties index f55d3d20fe..9365a7fe91 100644 --- a/server/apps/distributed-app/sample-configuration/jvm.properties +++ b/server/apps/distributed-app/sample-configuration/jvm.properties @@ -84,4 +84,8 @@ jmx.remote.x.mlet.allow.getMBeansFromURL=false # james.reactor.inputstream.prefetch=4 # Enable/disable mailet container check at James startup. Defaults to true. -# james.mailet.container.check.enabled=true \ No newline at end of file +# james.mailet.container.check.enabled=true + +# Relax validating `*` and `%` characters in the mailbox name. Defaults to false. +# Be careful turning on this as `%` and `*` are ambiguous for the LIST / LSUB commands that interpret those as wildcard thus returning all mailboxes matching the pattern. +#james.relaxed.mailbox.name.validation=true \ No newline at end of file diff --git a/server/apps/distributed-pop3-app/docker-configuration/jvm.properties b/server/apps/distributed-pop3-app/docker-configuration/jvm.properties index 93dedf3ef8..f638855ef4 100644 --- a/server/apps/distributed-pop3-app/docker-configuration/jvm.properties +++ b/server/apps/distributed-pop3-app/docker-configuration/jvm.properties @@ -46,3 +46,7 @@ config.file=/root/conf/cassandra-driver.conf # JMX, when enable causes RMI to plan System.gc every hour. Set this instead to once every 1000h. sun.rmi.dgc.server.gcInterval=3600000000 sun.rmi.dgc.client.gcInterval=3600000000 + +# Relax validating `*` and `%` characters in the mailbox name. Defaults to false. +# Be careful turning on this as `%` and `*` are ambiguous for the LIST / LSUB commands that interpret those as wildcard thus returning all mailboxes matching the pattern. +#james.relaxed.mailbox.name.validation=true \ No newline at end of file diff --git a/server/apps/distributed-pop3-app/sample-configuration/jvm.properties b/server/apps/distributed-pop3-app/sample-configuration/jvm.properties index e7ece390c2..2612e150ff 100644 --- a/server/apps/distributed-pop3-app/sample-configuration/jvm.properties +++ b/server/apps/distributed-pop3-app/sample-configuration/jvm.properties @@ -58,4 +58,8 @@ jmx.remote.x.mlet.allow.getMBeansFromURL=false # james.jwt.zip.allow=false # Enable/disable mailet container check at James startup. Defaults to true. -# james.mailet.container.check.enabled=true \ No newline at end of file +# james.mailet.container.check.enabled=true + +# Relax validating `*` and `%` characters in the mailbox name. Defaults to false. +# Be careful turning on this as `%` and `*` are ambiguous for the LIST / LSUB commands that interpret those as wildcard thus returning all mailboxes matching the pattern. +#james.relaxed.mailbox.name.validation=true \ No newline at end of file diff --git a/server/apps/jpa-app/sample-configuration/jvm.properties b/server/apps/jpa-app/sample-configuration/jvm.properties index 04cfad0b6c..68859135ac 100644 --- a/server/apps/jpa-app/sample-configuration/jvm.properties +++ b/server/apps/jpa-app/sample-configuration/jvm.properties @@ -56,4 +56,8 @@ openjpa.Multithreaded=true # james.jwt.zip.allow=false # Enable/disable mailet container check at James startup. Defaults to true. -# james.mailet.container.check.enabled=true \ No newline at end of file +# james.mailet.container.check.enabled=true + +# Relax validating `*` and `%` characters in the mailbox name. Defaults to false. +# Be careful turning on this as `%` and `*` are ambiguous for the LIST / LSUB commands that interpret those as wildcard thus returning all mailboxes matching the pattern. +#james.relaxed.mailbox.name.validation=true \ No newline at end of file diff --git a/server/apps/memory-app/sample-configuration/jvm.properties b/server/apps/memory-app/sample-configuration/jvm.properties index 649b5fc3b1..692bc6bf46 100644 --- a/server/apps/memory-app/sample-configuration/jvm.properties +++ b/server/apps/memory-app/sample-configuration/jvm.properties @@ -58,4 +58,8 @@ jmx.remote.x.mlet.allow.getMBeansFromURL=false # james.jwt.zip.allow=false # Enable/disable mailet container check at James startup. Defaults to true. -# james.mailet.container.check.enabled=true \ No newline at end of file +# james.mailet.container.check.enabled=true + +# Relax validating `*` and `%` characters in the mailbox name. Defaults to false. +# Be careful turning on this as `%` and `*` are ambiguous for the LIST / LSUB commands that interpret those as wildcard thus returning all mailboxes matching the pattern. +#james.relaxed.mailbox.name.validation=true \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@james.apache.org For additional commands, e-mail: notifications-h...@james.apache.org