You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2019/08/02 09:56:44 UTC
[james-project] branch master updated (523958b -> 68dcf80)
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 523958b JAMES-2838 CassandraBlobStore delete implementation
new 79e4177 JAMES-2842 AddressMappingRoutes Implementation
new b8c45f8 JAMES-2842 AddressMappingRoutes markdown documentation
new 3d74bdc JAMES-2842 AddressMappingRoutes guice binding
new 150168c JAMES-2842 addAddressMapping should check same source and destination
new 68dcf80 JAMES-2832 RegexMappingRoutes implementation and documentation
The 5 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:
.../james/modules/server/DataRoutesModules.java | 4 +
...tsException.java => InvalidRegexException.java} | 8 +-
.../rrt/lib/AbstractRecipientRewriteTable.java | 4 +-
.../test/resources/cucumber/rewrite_tables.feature | 2 +-
...appingRoutes.java => AddressMappingRoutes.java} | 69 +++++----
.../james/webadmin/routes/RegexMappingRoutes.java | 116 +++++++++++++++
.../apache/james/webadmin/routes/UserRoutes.java | 5 +-
.../webadmin/routes/AddressMappingRoutesTest.java | 143 ++++++++++++++++++
.../webadmin/routes/RegexMappingRoutesTest.java | 159 +++++++++++++++++++++
src/site/markdown/server/manage-webadmin.md | 74 +++++++++-
10 files changed, 539 insertions(+), 45 deletions(-)
copy server/data/data-api/src/main/java/org/apache/james/rrt/api/{MappingAlreadyExistsException.java => InvalidRegexException.java} (88%)
copy server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/{MappingRoutes.java => AddressMappingRoutes.java} (53%)
create mode 100644 server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/RegexMappingRoutes.java
create mode 100644 server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AddressMappingRoutesTest.java
create mode 100644 server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/RegexMappingRoutesTest.java
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[james-project] 04/05: JAMES-2842 addAddressMapping should check
same source and destination
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 150168c4b9a159236f3e65efd6a57692e41362ec
Author: Khanh Le <bk...@linagora.com>
AuthorDate: Mon Jul 29 17:06:59 2019 +0700
JAMES-2842 addAddressMapping should check same source and destination
---
.../java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
index 598db33..7af23d4 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
@@ -206,6 +206,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
checkHasValidAddress(mapping);
checkDuplicateMapping(source, mapping);
checkDomainMappingSourceIsManaged(source);
+ checkNotSameSourceAndDestination(source, address);
LOGGER.info("Add address mapping => {} for source: {}", mapping.asString(), source.asString());
addMapping(source, mapping);
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[james-project] 05/05: JAMES-2832 RegexMappingRoutes implementation
and documentation
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 68dcf80e55e086cd3506dfdbf62259343938d180
Author: tranduong <qd...@linagora.com>
AuthorDate: Mon Jul 29 10:05:46 2019 +0700
JAMES-2832 RegexMappingRoutes implementation and documentation
---
.../james/modules/server/DataRoutesModules.java | 2 +
.../james/rrt/api/InvalidRegexException.java | 26 ++++
.../rrt/lib/AbstractRecipientRewriteTable.java | 3 +-
.../test/resources/cucumber/rewrite_tables.feature | 2 +-
.../james/webadmin/routes/RegexMappingRoutes.java | 116 +++++++++++++++
.../apache/james/webadmin/routes/UserRoutes.java | 5 +-
.../webadmin/routes/RegexMappingRoutesTest.java | 159 +++++++++++++++++++++
src/site/markdown/server/manage-webadmin.md | 43 +++++-
8 files changed, 347 insertions(+), 9 deletions(-)
diff --git a/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java b/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java
index 9f8c8a56..d198069 100644
--- a/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java
+++ b/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java
@@ -28,6 +28,7 @@ import org.apache.james.webadmin.routes.DomainsRoutes;
import org.apache.james.webadmin.routes.ForwardRoutes;
import org.apache.james.webadmin.routes.GroupsRoutes;
import org.apache.james.webadmin.routes.MappingRoutes;
+import org.apache.james.webadmin.routes.RegexMappingRoutes;
import org.apache.james.webadmin.routes.UserRoutes;
import org.apache.james.webadmin.utils.JsonTransformerModule;
@@ -46,6 +47,7 @@ public class DataRoutesModules extends AbstractModule {
routesMultibinder.addBinding().to(ForwardRoutes.class);
routesMultibinder.addBinding().to(GroupsRoutes.class);
routesMultibinder.addBinding().to(MappingRoutes.class);
+ routesMultibinder.addBinding().to(RegexMappingRoutes.class);
routesMultibinder.addBinding().to(UserRoutes.class);
Multibinder<JsonTransformerModule> jsonTransformerModuleMultibinder = Multibinder.newSetBinder(binder(), JsonTransformerModule.class);
diff --git a/server/data/data-api/src/main/java/org/apache/james/rrt/api/InvalidRegexException.java b/server/data/data-api/src/main/java/org/apache/james/rrt/api/InvalidRegexException.java
new file mode 100644
index 0000000..1ae93e8
--- /dev/null
+++ b/server/data/data-api/src/main/java/org/apache/james/rrt/api/InvalidRegexException.java
@@ -0,0 +1,26 @@
+/****************************************************************
+ * 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.rrt.api;
+
+public class InvalidRegexException extends RecipientRewriteTableException {
+ public InvalidRegexException(String msg, Exception e) {
+ super(msg, e);
+ }
+}
diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
index 7af23d4..e8b07e5 100644
--- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
+++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/AbstractRecipientRewriteTable.java
@@ -35,6 +35,7 @@ import org.apache.james.core.User;
import org.apache.james.domainlist.api.DomainList;
import org.apache.james.domainlist.api.DomainListException;
import org.apache.james.lifecycle.api.Configurable;
+import org.apache.james.rrt.api.InvalidRegexException;
import org.apache.james.rrt.api.MappingAlreadyExistsException;
import org.apache.james.rrt.api.RecipientRewriteTable;
import org.apache.james.rrt.api.RecipientRewriteTableException;
@@ -182,7 +183,7 @@ public abstract class AbstractRecipientRewriteTable implements RecipientRewriteT
try {
Pattern.compile(regex);
} catch (PatternSyntaxException e) {
- throw new RecipientRewriteTableException("Invalid regex: " + regex, e);
+ throw new InvalidRegexException("Invalid regex: " + regex, e);
}
Mapping mapping = Mapping.regex(regex);
diff --git a/server/data/data-library/src/test/resources/cucumber/rewrite_tables.feature b/server/data/data-library/src/test/resources/cucumber/rewrite_tables.feature
index 1048672..27802cd 100644
--- a/server/data/data-library/src/test/resources/cucumber/rewrite_tables.feature
+++ b/server/data/data-library/src/test/resources/cucumber/rewrite_tables.feature
@@ -29,7 +29,7 @@ Feature: Rewrite Tables tests
@readonly
Scenario: storing an invalid regexp mapping should not work
When store an invalid ".*):" regexp mapping for user "test" at domain "localhost"
- Then a "RecipientRewriteTableException" exception should have been thrown
+ Then a "InvalidRegexException" exception should have been thrown
# Address mapping
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/RegexMappingRoutes.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/RegexMappingRoutes.java
new file mode 100644
index 0000000..ee2cfd6
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/RegexMappingRoutes.java
@@ -0,0 +1,116 @@
+/****************************************************************
+ * 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.webadmin.routes;
+
+import static org.apache.james.webadmin.Constants.SEPARATOR;
+import static spark.Spark.halt;
+
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+
+import javax.inject.Inject;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+import org.apache.james.core.User;
+import org.apache.james.rrt.api.InvalidRegexException;
+import org.apache.james.rrt.api.RecipientRewriteTable;
+import org.apache.james.rrt.lib.MappingSource;
+import org.apache.james.webadmin.Constants;
+import org.apache.james.webadmin.Routes;
+import org.apache.james.webadmin.utils.ErrorResponder;
+import org.eclipse.jetty.http.HttpStatus;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import spark.HaltException;
+import spark.Request;
+import spark.Response;
+import spark.Service;
+
+@Api(tags = "Regex Mapping")
+@Path(RegexMappingRoutes.BASE_PATH)
+@Produces(Constants.JSON_CONTENT_TYPE)
+public class RegexMappingRoutes implements Routes {
+
+ static final String BASE_PATH = "/mappings/regex";
+ static final String MAPPING_SOURCE_PARAM = ":mappingSource";
+ static final String REGEX_PARAM = ":regex";
+ static final String ADD_ADDRESS_MAPPING_PATH = BASE_PATH + SEPARATOR
+ + MAPPING_SOURCE_PARAM + "/targets/" + REGEX_PARAM;
+
+ private final RecipientRewriteTable recipientRewriteTable;
+
+ @Inject
+ @VisibleForTesting
+ RegexMappingRoutes(RecipientRewriteTable recipientRewriteTable) {
+ this.recipientRewriteTable = recipientRewriteTable;
+ }
+
+ @Override
+ public String getBasePath() {
+ return BASE_PATH;
+ }
+
+ @Override
+ public void define(Service service) {
+ service.post(ADD_ADDRESS_MAPPING_PATH, this::addRegexMapping);
+ }
+
+ @POST
+ @Path(ADD_ADDRESS_MAPPING_PATH)
+ @ApiOperation(value = "adding address-regex mappings to RecipientRewriteTable")
+ @ApiResponses(value = {
+ @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "Mapping successfully added"),
+ @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Invalid parameter")
+ })
+ private HaltException addRegexMapping(Request request, Response response) throws Exception {
+ try {
+ MappingSource mappingSource = extractMappingSource(request);
+ String regex = URLDecoder.decode(request.params(REGEX_PARAM), StandardCharsets.UTF_8.toString());
+ recipientRewriteTable.addRegexMapping(mappingSource, regex);
+ } catch (InvalidRegexException e) {
+ throw ErrorResponder.builder()
+ .statusCode(HttpStatus.BAD_REQUEST_400)
+ .type(ErrorResponder.ErrorType.INVALID_ARGUMENT)
+ .message(e.getMessage())
+ .haltError();
+ }
+ return halt(HttpStatus.NO_CONTENT_204);
+ }
+
+ private MappingSource extractMappingSource(Request request) {
+ try {
+ return MappingSource
+ .fromUser(User.fromUsername(request.params(MAPPING_SOURCE_PARAM)));
+ } catch (IllegalArgumentException e) {
+ throw ErrorResponder.builder()
+ .statusCode(HttpStatus.BAD_REQUEST_400)
+ .type(ErrorResponder.ErrorType.INVALID_ARGUMENT)
+ .message("Invalid `source` field.")
+ .haltError();
+ }
+ }
+}
\ No newline at end of file
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/UserRoutes.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/UserRoutes.java
index 6054d0e..0e7735d 100644
--- a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/UserRoutes.java
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/UserRoutes.java
@@ -184,7 +184,4 @@ public class UserRoutes implements Routes {
.haltError();
}
}
-
-
-
-}
+}
\ No newline at end of file
diff --git a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/RegexMappingRoutesTest.java b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/RegexMappingRoutesTest.java
new file mode 100644
index 0000000..1c9aebd
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/RegexMappingRoutesTest.java
@@ -0,0 +1,159 @@
+/****************************************************************
+ * 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.webadmin.routes;
+
+import static io.restassured.RestAssured.with;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.mockito.Mockito.mock;
+
+import org.apache.james.core.Domain;
+import org.apache.james.core.User;
+import org.apache.james.dnsservice.api.DNSService;
+import org.apache.james.domainlist.api.DomainList;
+import org.apache.james.domainlist.memory.MemoryDomainList;
+import org.apache.james.rrt.lib.Mapping;
+import org.apache.james.rrt.lib.MappingSource;
+import org.apache.james.rrt.memory.MemoryRecipientRewriteTable;
+import org.apache.james.webadmin.WebAdminServer;
+import org.apache.james.webadmin.WebAdminUtils;
+import org.eclipse.jetty.http.HttpStatus;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import io.restassured.RestAssured;
+import io.restassured.filter.log.LogDetail;
+import io.restassured.http.ContentType;
+
+class RegexMappingRoutesTest {
+ private WebAdminServer webAdminServer;
+ private MemoryRecipientRewriteTable memoryRecipientRewriteTable;
+
+ @BeforeEach
+ void beforeEach() throws Exception {
+ DNSService dnsService = mock(DNSService.class);
+ DomainList domainList = new MemoryDomainList(dnsService);
+ memoryRecipientRewriteTable = new MemoryRecipientRewriteTable();
+ memoryRecipientRewriteTable.setDomainList(domainList);
+ domainList.addDomain(Domain.of("domain.tld"));
+
+ webAdminServer = WebAdminUtils
+ .createWebAdminServer(new RegexMappingRoutes(memoryRecipientRewriteTable))
+ .start();
+
+ RestAssured.requestSpecification = WebAdminUtils.buildRequestSpecification(webAdminServer)
+ .setBasePath(RegexMappingRoutes.BASE_PATH)
+ .log(LogDetail.METHOD)
+ .build();
+ }
+
+ @AfterEach
+ void stop() {
+ webAdminServer.destroy();
+ }
+
+ @Test
+ void addRegexMappingShouldReturnNoContentWhenSuccess() {
+ with()
+ .post("james@domain.tld/targets/bis.*@apache.org")
+ .then()
+ .statusCode(HttpStatus.NO_CONTENT_204)
+ .contentType(ContentType.JSON);
+
+ assertThat(memoryRecipientRewriteTable
+ .getStoredMappings(MappingSource.fromUser(User.fromUsername("james@domain.tld"))))
+ .containsOnly(Mapping.regex("bis.*@apache.org"));
+ }
+
+ @Test
+ void addRegexMappingShouldAllowUserWithoutDomain() {
+ with()
+ .post("jamesdomaintld/targets/bis.*@apache.org")
+ .then()
+ .statusCode(HttpStatus.NO_CONTENT_204)
+ .contentType(ContentType.JSON);
+
+ assertThat(memoryRecipientRewriteTable
+ .getStoredMappings(MappingSource.fromUser(User.fromUsername("jamesdomaintld"))))
+ .containsOnly(Mapping.regex("bis.*@apache.org"));
+ }
+
+ @Test
+ void addRegexMappingShouldReturnNotFoundWhenSourceIsEmpty() {
+ with()
+ .post("/targets/bis.*@apache.org")
+ .then()
+ .statusCode(HttpStatus.NOT_FOUND_404)
+ .contentType(ContentType.JSON)
+ .body("type", is("notFound"))
+ .body("statusCode", is(HttpStatus.NOT_FOUND_404))
+ .body("message", is("POST /mappings/regex/targets/bis.*@apache.org can not be found"));
+ }
+
+ @Test
+ void addRegexMappingShouldReturnNotFoundWhenRegexIsEmpty() {
+ with()
+ .post("james@domain.tld/targets/")
+ .then()
+ .statusCode(HttpStatus.NOT_FOUND_404)
+ .contentType(ContentType.JSON)
+ .body("type", is("notFound"))
+ .body("statusCode", is(HttpStatus.NOT_FOUND_404))
+ .body("message", is("POST /mappings/regex/james@domain.tld/targets/ can not be found"));
+ }
+
+ @Test
+ void addRegexMappingShouldReturnNotFoundWhenSourceAndRegexEmpty() {
+ with()
+ .post("/targets/")
+ .then()
+ .statusCode(HttpStatus.NOT_FOUND_404)
+ .contentType(ContentType.JSON)
+ .body("type", is("notFound"))
+ .body("statusCode", is(HttpStatus.NOT_FOUND_404))
+ .body("message", is("POST /mappings/regex/targets/ can not be found"));
+ }
+
+ @Test
+ void addRegexMappingShouldReturnBadRequestWhenRegexIsInvalid() {
+ with()
+ .post("james@domain.tld/targets/O.*[]")
+ .then()
+ .statusCode(HttpStatus.BAD_REQUEST_400)
+ .contentType(ContentType.JSON)
+ .body("type", is("InvalidArgument"))
+ .body("statusCode", is(HttpStatus.BAD_REQUEST_400))
+ .body("message", is("Invalid regex: O.*[]"));
+ }
+
+ @Test
+ void addRegexMappingShouldReturnNoContentWhenRegexContainsQuestionMark() {
+ with()
+ .post("james@domain.tld/targets/^[aei%3Fou].*james@domain.tld")
+ .then()
+ .statusCode(HttpStatus.NO_CONTENT_204)
+ .contentType(ContentType.JSON);
+
+ assertThat(memoryRecipientRewriteTable
+ .getStoredMappings(MappingSource.fromUser(User.fromUsername("james@domain.tld"))))
+ .containsOnly(Mapping.regex("^[aei?ou].*james@domain.tld"));
+ }
+}
\ No newline at end of file
diff --git a/src/site/markdown/server/manage-webadmin.md b/src/site/markdown/server/manage-webadmin.md
index bc9a08b..812cf9c 100644
--- a/src/site/markdown/server/manage-webadmin.md
+++ b/src/site/markdown/server/manage-webadmin.md
@@ -35,10 +35,11 @@ as exposed above). To avoid information duplication, this is ommited on endpoint
- [Administrating global quotas](#Administrating_global_quotas)
- [Cassandra Schema upgrades](#Cassandra_Schema_upgrades)
- [Correcting ghost mailbox](#Correcting_ghost_mailbox)
- - [Creating address group](#Creating_address_group)
- - [Creating address forwards](#Creating_address_forwards)
- [Creating address aliases](#Creating_address_aliases)
- [Creating address domain](#Creating_address_domain)
+ - [Creating address forwards](#Creating_address_forwards)
+ - [Creating address group](#Creating_address_group)
+ - [Creating regex mapping](#Creating_regex_mapping)
- [Address Mappings](#Address_mappings)
- [Administrating mail repositories](#Administrating_mail_repositories)
- [Administrating mail queues](#Administrating_mail_queues)
@@ -1456,7 +1457,6 @@ Response codes:
- 400: Alias structure or member is not valid
## Creating address domain
-
You can use **webadmin** to define domain mappings.
Given a configured source (from) domain and a destination (to) domain, when an email is sent to an address belonging to the source domain, then the domain part of this address is overwritten, the destination domain is then used.
@@ -1546,6 +1546,43 @@ Response codes:
- 400: The `fromDomain` resource name is invalid
- 400: The destination domain specified in the body is invalid
+## Creating regex mapping
+You can use **webadmin** to create regex mappings.
+
+A regex mapping contains a mapping source and a Java Regular Expression (regex) in String as the mapping value.
+Everytime, if a mail containing a recipient matched with the mapping source,
+then that mail will be re-routed to a new recipient address
+which is re written by the regex.
+
+This feature uses [Recipients rewrite table](/server/config-recipientrewritetable.html) and
+requires the [RecipientRewriteTable API](https://github.com/apache/james-project/blob/master/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RecipientRewriteTable.java)
+to be configured.
+ - [Adding a regex mapping](#Adding_a_regex_mapping)
+
+### Adding a regex mapping
+
+```
+POST /mappings/regex/mappingSource/targets/regex
+```
+
+Where:
+ - the `mappingSource` is the path parameter represents for the Regex Mapping mapping source
+ - the `regex` is the path parameter represents for the Regex Mapping regex
+
+The route will add a regex mapping made from `mappingSource` and `regex` to RecipientRewriteTable.
+
+Example:
+
+```
+curl -XPOST http://ip:port/mappings/regex/james@domain.tld/targets/james@.*:james-intern@james.org
+```
+
+Response codes:
+
+ - 204: Mapping added successfully.
+ - 400: Invalid `mappingSource` path parameter.
+ - 400: Invalid `regex` path parameter.
+
## Address Mappings
You can use **webadmin** to define address mappings.
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[james-project] 03/05: JAMES-2842 AddressMappingRoutes guice binding
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 3d74bdc9de294d49b78695f66d8846a4ce291bd0
Author: Khanh Le <bk...@linagora.com>
AuthorDate: Tue Jul 23 17:34:30 2019 +0700
JAMES-2842 AddressMappingRoutes guice binding
---
.../main/java/org/apache/james/modules/server/DataRoutesModules.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java b/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java
index efc3aca..9f8c8a56 100644
--- a/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java
+++ b/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java
@@ -21,6 +21,7 @@ package org.apache.james.modules.server;
import org.apache.james.webadmin.Routes;
import org.apache.james.webadmin.dto.MappingSourceModule;
+import org.apache.james.webadmin.routes.AddressMappingRoutes;
import org.apache.james.webadmin.routes.AliasRoutes;
import org.apache.james.webadmin.routes.DomainMappingsRoutes;
import org.apache.james.webadmin.routes.DomainsRoutes;
@@ -38,6 +39,7 @@ public class DataRoutesModules extends AbstractModule {
@Override
protected void configure() {
Multibinder<Routes> routesMultibinder = Multibinder.newSetBinder(binder(), Routes.class);
+ routesMultibinder.addBinding().to(AddressMappingRoutes.class);
routesMultibinder.addBinding().to(AliasRoutes.class);
routesMultibinder.addBinding().to(DomainsRoutes.class);
routesMultibinder.addBinding().to(DomainMappingsRoutes.class);
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[james-project] 02/05: JAMES-2842 AddressMappingRoutes markdown
documentation
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 b8c45f8a83967215d29d5871c0e377f350c29c6f
Author: Khanh Le <bk...@linagora.com>
AuthorDate: Tue Jul 23 17:31:26 2019 +0700
JAMES-2842 AddressMappingRoutes markdown documentation
---
src/site/markdown/server/manage-webadmin.md | 31 ++++++++++++++++++++++++++++-
1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/src/site/markdown/server/manage-webadmin.md b/src/site/markdown/server/manage-webadmin.md
index 848de88..bc9a08b 100644
--- a/src/site/markdown/server/manage-webadmin.md
+++ b/src/site/markdown/server/manage-webadmin.md
@@ -1548,7 +1548,22 @@ Response codes:
## Address Mappings
+You can use **webadmin** to define address mappings.
+
+When a specific email is sent to the base mail address, every destination addresses will receive it.
+
+This feature uses [Recipients rewrite table](/server/config-recipientrewritetable.html) and requires
+the [RecipientRewriteTable mailet](https://github.com/apache/james-project/blob/master/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RecipientRewriteTable.java)
+to be configured.
+
+Note that email addresses are restricted to ASCII character set. Mail addresses not matching this criteria will be rejected.
+
+Please use address mappings with caution, as it's not a typed address. If you know the type of your address (forward, alias, domain, group, etc), prefer using the corresponding routes to those types.
+
+Here are the following actions available on address mappings:
+
- [List all address mappings](#List_all_address_mappinig)
+ - [Add an address mapping](#Add_an_address_mapping)
### List all address mappings
@@ -1599,6 +1614,20 @@ Response body:
Response code:
- 200: OK
+### Add an address mapping
+
+```
+curl -XPOST http://ip:port/mappings/address/{mappingSource}/targets/{destinationAddress}
+```
+Add an address mapping to the [Recipients rewrite table](/server/config-recipientrewritetable.html)
+Mapping source is the value of {mappingSource}
+Mapping destination is the value of {destinationAddress}
+Type of mapping destination is Address
+
+Respond code:
+- 204: NO CONTENT
+- 400: INVALID PARAMETERS
+
## Administrating mail repositories
- [Create a mail repository](#Create_a_mail_repository)
@@ -2924,7 +2953,7 @@ Messages in the Deleted Messages Vault of a specified user that are matched with
}
```
- - For restoring all deleted messages, passing a query json with an empty criterion list to represent `matching all deleted messages`:
+ - For restoring all deleted messages, passing a query json with an empty criterion list to represent `matching all deleted messages`:
```
{
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[james-project] 01/05: JAMES-2842 AddressMappingRoutes
Implementation
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 79e41774299e88a50e0008e182b04beb48152b85
Author: Khanh Le <bk...@linagora.com>
AuthorDate: Tue Jul 23 17:30:37 2019 +0700
JAMES-2842 AddressMappingRoutes Implementation
---
.../webadmin/routes/AddressMappingRoutes.java | 108 ++++++++++++++++
.../webadmin/routes/AddressMappingRoutesTest.java | 143 +++++++++++++++++++++
2 files changed, 251 insertions(+)
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AddressMappingRoutes.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AddressMappingRoutes.java
new file mode 100644
index 0000000..faeb2cc
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/AddressMappingRoutes.java
@@ -0,0 +1,108 @@
+/****************************************************************
+ * 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.webadmin.routes;
+
+import static spark.Spark.halt;
+
+import java.util.List;
+
+import javax.inject.Inject;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+import org.apache.james.core.MailAddress;
+import org.apache.james.rrt.api.MappingAlreadyExistsException;
+import org.apache.james.rrt.api.RecipientRewriteTable;
+import org.apache.james.rrt.api.RecipientRewriteTableException;
+import org.apache.james.rrt.api.SameSourceAndDestinationException;
+import org.apache.james.rrt.api.SourceDomainIsNotInDomainListException;
+import org.apache.james.rrt.lib.MappingSource;
+import org.apache.james.webadmin.Constants;
+import org.apache.james.webadmin.Routes;
+import org.apache.james.webadmin.utils.ErrorResponder;
+import org.eclipse.jetty.http.HttpStatus;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import spark.HaltException;
+import spark.Request;
+import spark.Response;
+import spark.Service;
+
+
+@Api(tags = "AddressMappings")
+@Path(MappingRoutes.BASE_PATH)
+@Produces(Constants.JSON_CONTENT_TYPE)
+public class AddressMappingRoutes implements Routes {
+
+ static final String BASE_PATH = "/mappings/address/";
+ static final String ADD_ADDRESS_MAPPING_PATH = "/mappings/address/:mappingSource/targets/:destinationAddress";
+
+ private final RecipientRewriteTable recipientRewriteTable;
+
+ @Inject
+ AddressMappingRoutes(RecipientRewriteTable recipientRewriteTable) {
+ this.recipientRewriteTable = recipientRewriteTable;
+ }
+
+ @Override
+ public String getBasePath() {
+ return BASE_PATH;
+ }
+
+ @Override
+ public void define(Service service) {
+ service.post(ADD_ADDRESS_MAPPING_PATH, this::addAddressMapping);
+ }
+
+ @POST
+ @Path(ADD_ADDRESS_MAPPING_PATH)
+ @ApiOperation(value = "Getting all user mappings in RecipientRewriteTable")
+ @ApiResponses(value = {
+ @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "No body on created", response = List.class),
+ @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Invalid parameter values.")
+ })
+ public HaltException addAddressMapping(Request request, Response response) throws RecipientRewriteTableException {
+ MailAddress source = MailAddressParser.parseMailAddress(
+ request.params("mappingSource"),"address");
+ MailAddress destinationAddress = MailAddressParser.parseMailAddress(
+ request.params("destinationAddress"), "address");
+ addAddressMapping(MappingSource.fromMailAddress(source), destinationAddress);
+ return halt(HttpStatus.NO_CONTENT_204);
+ }
+
+ private void addAddressMapping(MappingSource source, MailAddress destination) throws RecipientRewriteTableException {
+ try {
+ recipientRewriteTable.addAddressMapping(source, destination.asString());
+ } catch (MappingAlreadyExistsException e) {
+ // ignore
+ } catch (SameSourceAndDestinationException | SourceDomainIsNotInDomainListException e) {
+ throw ErrorResponder.builder()
+ .statusCode(HttpStatus.BAD_REQUEST_400)
+ .type(ErrorResponder.ErrorType.INVALID_ARGUMENT)
+ .message(e.getMessage())
+ .haltError();
+ }
+ }
+
+}
diff --git a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AddressMappingRoutesTest.java b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AddressMappingRoutesTest.java
new file mode 100644
index 0000000..048f17e
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/AddressMappingRoutesTest.java
@@ -0,0 +1,143 @@
+/****************************************************************
+ * 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.webadmin.routes;
+
+import static io.restassured.RestAssured.when;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+import org.apache.james.core.Domain;
+import org.apache.james.core.MailAddress;
+import org.apache.james.dnsservice.api.DNSService;
+import org.apache.james.domainlist.api.DomainList;
+import org.apache.james.domainlist.api.DomainListException;
+import org.apache.james.domainlist.memory.MemoryDomainList;
+import org.apache.james.rrt.lib.Mapping;
+import org.apache.james.rrt.lib.MappingSource;
+import org.apache.james.rrt.memory.MemoryRecipientRewriteTable;
+import org.apache.james.webadmin.WebAdminServer;
+import org.apache.james.webadmin.WebAdminUtils;
+import org.eclipse.jetty.http.HttpStatus;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import io.restassured.RestAssured;
+import io.restassured.filter.log.LogDetail;
+
+class AddressMappingRoutesTest {
+
+ private WebAdminServer webAdminServer;
+ private MemoryRecipientRewriteTable recipientRewriteTable;
+
+ @BeforeEach
+ void setUp() throws DomainListException {
+ recipientRewriteTable = new MemoryRecipientRewriteTable();
+ DNSService dnsService = mock(DNSService.class);
+ DomainList domainList = new MemoryDomainList(dnsService);
+ domainList.addDomain(Domain.of("domain.tld"));
+
+ recipientRewriteTable.setDomainList(domainList);
+
+ webAdminServer = WebAdminUtils.createWebAdminServer(
+ new AddressMappingRoutes(recipientRewriteTable))
+ .start();
+
+ RestAssured.requestSpecification = WebAdminUtils.buildRequestSpecification(webAdminServer)
+ .setBasePath(AddressMappingRoutes.BASE_PATH)
+ .log(LogDetail.METHOD)
+ .build();
+ }
+
+ @AfterEach
+ void stop() {
+ webAdminServer.destroy();
+ }
+
+ @Test
+ void addAddressMappingShouldAddMappingOnRecipientRewriteTable() {
+ when()
+ .post("source@domain.tld/targets/user@domain.tld");
+
+ assertThat(recipientRewriteTable.getStoredMappings(MappingSource.parse("source@domain.tld")))
+ .containsAnyOf(Mapping.of("user@domain.tld"));
+ }
+
+ @Test
+ void addAddressMappingShouldReturnNotFoundWhenOneParameterIsEmpty() {
+ when()
+ .post("source@domain.tld/targets/" )
+ .then()
+ .statusCode(HttpStatus.NOT_FOUND_404);
+ }
+
+ @Test
+ void addAddressMappingShouldReturnNoContentWhenValidParameter() {
+ when()
+ .post("source@domain.tld/targets/alice@domain.tld")
+ .then()
+ .statusCode(HttpStatus.NO_CONTENT_204);
+ }
+
+ @Test
+ void addAddressMappingShouldReturnBadRequestWhenInvalidMappingSource() {
+ when()
+ .post("source/targets/alice@domain.tld")
+ .then()
+ .statusCode(HttpStatus.BAD_REQUEST_400);
+ }
+
+ @Test
+ void addAddressMappingShouldReturnBadRequestWhenInvalidDestinationAddress() {
+ when()
+ .post("source@domain.tld/targets/alice")
+ .then()
+ .statusCode(HttpStatus.BAD_REQUEST_400);
+ }
+
+ @Test
+ void addAddressMappingShouldReturnNoContentWithDuplicatedAddress() throws Exception {
+ MappingSource mappingSource = MappingSource.fromMailAddress(new MailAddress("source@domain.tld"));
+
+ recipientRewriteTable.addAddressMapping(mappingSource, "alice@domain.tld");
+ recipientRewriteTable.addAddressMapping(mappingSource, "bob@domain.tld");
+
+ when()
+ .post("source@domain.tld/targets/alice@domain.tld")
+ .then()
+ .statusCode(HttpStatus.NO_CONTENT_204);
+ }
+
+ @Test
+ void addAddressMappingShouldReturnBadRequestWhenSourceAndDestinationIsTheSame() {
+ when()
+ .post("source@domain.tld/targets/source@domain.tld")
+ .then()
+ .statusCode(HttpStatus.BAD_REQUEST_400);
+ }
+
+ @Test
+ void addressMappingSHouldReturnBadRequestWhenSourceDomainNotInDomainList() {
+ when()
+ .post("source@dexample/targets/alice@domain.tld")
+ .then()
+ .statusCode(HttpStatus.BAD_REQUEST_400);
+ }
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org