This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch droplist
in repository https://gitbox.apache.org/repos/asf/james-project.git
The following commit(s) were added to refs/heads/droplist by this push:
new 098bf4227b JAMES-3946 DropList Cassandra and Memory app (#2263)
098bf4227b is described below
commit 098bf4227b83bbd8a3400ba084a55100be218826
Author: Maksim <[email protected]>
AuthorDate: Wed May 29 05:14:42 2024 +0300
JAMES-3946 DropList Cassandra and Memory app (#2263)
---
.../distributed-app/docs/modules/ROOT/nav.adoc | 1 +
.../modules/ROOT/pages/configure/droplists.adoc | 32 ++++++++++++++++++++
.../docs/modules/ROOT/pages/configure/index.adoc | 1 +
.../sample-configuration/droplists.properties | 3 ++
.../james/CassandraRabbitMQJamesConfiguration.java | 28 ++++++++++++++++--
.../james/CassandraRabbitMQJamesServerMain.java | 15 +++++++++-
.../sample-configuration/droplists.properties | 3 ++
.../org/apache/james/MemoryJamesConfiguration.java | 31 ++++++++++++++++++--
.../org/apache/james/MemoryJamesServerMain.java | 14 ++++++++-
.../modules/data/CassandraDropListsModule.java | 33 +++++++++++++++++++++
.../james/modules/data/MemoryDropListsModule.java | 33 +++++++++++++++++++++
.../modules/server/DropListsRoutesModule.java | 34 ++++++++++++++++++++++
12 files changed, 222 insertions(+), 6 deletions(-)
diff --git a/server/apps/distributed-app/docs/modules/ROOT/nav.adoc
b/server/apps/distributed-app/docs/modules/ROOT/nav.adoc
index bf98a74134..60b767f250 100644
--- a/server/apps/distributed-app/docs/modules/ROOT/nav.adoc
+++ b/server/apps/distributed-app/docs/modules/ROOT/nav.adoc
@@ -34,6 +34,7 @@
**** xref:configure/batchsizes.adoc[batchsizes.properties]
**** xref:configure/dns.adoc[dnsservice.xml]
**** xref:configure/domainlist.adoc[domainlist.xml]
+**** xref:configure/droplists.adoc[DropLists]
**** xref:configure/healthcheck.adoc[healthcheck.properties]
**** xref:configure/mailetcontainer.adoc[mailetcontainer.xml]
**** xref:configure/mailets.adoc[Packaged Mailets]
diff --git
a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/droplists.adoc
b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/droplists.adoc
new file mode 100644
index 0000000000..e63a846404
--- /dev/null
+++
b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/droplists.adoc
@@ -0,0 +1,32 @@
+= Distributed James Server — DropLists
+:navtitle: DropLists
+
+The DropList, also known as the mail blacklist, is a collection of
+domains and email addresses that are denied from sending emails within the
system.
+It is disabled by default.
+To enable it, modify the `droplists.properties` file and include the
`IsInDropList` matcher in the `mailetcontainer.xml`.
+To disable it, adjust the `droplists.properties` file and remove the
`IsInDropList` matcher from the `mailetcontainer.xml`.
+
+.droplists.properties content
+|===
+| Property name | explanation
+
+| enabled
+| Boolean. Governs whether DropLists should be enabled. Defaults to `false`.
+|===
+
+== Enabling Matcher
+
+Plug the `IsInDropList` matcher within `mailetcontainer.xml` :
+
+....
+<mailet match="org.apache.james.transport.matchers.IsInDropList"
class="ToProcessor">
+ <processor>transport</processor>
+</mailet>
+....
+
+== DropList management
+
+DropList management, including adding and deleting entries, is performed
through the WebAdmin REST API.
+
+See xref:operate/webadmin.adoc#_administrating_droplists[WebAdmin DropLists].
\ No newline at end of file
diff --git
a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/index.adoc
b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/index.adoc
index 2fa9d90044..bc9b0f9392 100644
--- a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/index.adoc
+++ b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/index.adoc
@@ -66,6 +66,7 @@ By omitting these files, no extra behaviour is added.
** xref:configure/collecting-contacts.adoc[This page] documents contact
collection
** xref:configure/collecting-events.adoc[This page] documents event collection
** xref:configure/dsn.adoc[this page] specified how to support SMTP Delivery
Submission Notification (link:https://tools.ietf.org/html/rfc3461[RFC-3461])
+** xref:configure/droplists.adoc[This page] allows configuring drop lists.
== System properties
diff --git
a/server/apps/distributed-app/sample-configuration/droplists.properties
b/server/apps/distributed-app/sample-configuration/droplists.properties
new file mode 100644
index 0000000000..bbc27568cb
--- /dev/null
+++ b/server/apps/distributed-app/sample-configuration/droplists.properties
@@ -0,0 +1,3 @@
+# Configuration file for DropLists
+
+enabled=false
\ No newline at end of file
diff --git
a/server/apps/distributed-app/src/main/java/org/apache/james/CassandraRabbitMQJamesConfiguration.java
b/server/apps/distributed-app/src/main/java/org/apache/james/CassandraRabbitMQJamesConfiguration.java
index 7a4daa5d67..3beb1fe0cc 100644
---
a/server/apps/distributed-app/src/main/java/org/apache/james/CassandraRabbitMQJamesConfiguration.java
+++
b/server/apps/distributed-app/src/main/java/org/apache/james/CassandraRabbitMQJamesConfiguration.java
@@ -52,6 +52,7 @@ public class CassandraRabbitMQJamesConfiguration implements
Configuration {
private Optional<VaultConfiguration> vaultConfiguration;
private Optional<Boolean> jmapEnabled;
private Optional<Boolean> quotaCompatibilityMode;
+ private Optional<Boolean> dropListsEnabled;
private Builder() {
searchConfiguration = Optional.empty();
@@ -64,6 +65,7 @@ public class CassandraRabbitMQJamesConfiguration implements
Configuration {
vaultConfiguration = Optional.empty();
jmapEnabled = Optional.empty();
quotaCompatibilityMode = Optional.empty();
+ dropListsEnabled = Optional.empty();
}
public Builder workingDirectory(String path) {
@@ -134,6 +136,11 @@ public class CassandraRabbitMQJamesConfiguration
implements Configuration {
return this;
}
+ public Builder enableDropLists() {
+ this.dropListsEnabled = Optional.of(true);
+ return this;
+ }
+
public CassandraRabbitMQJamesConfiguration build() {
ConfigurationPath configurationPath =
this.configurationPath.orElse(new
ConfigurationPath(FileSystem.FILE_PROTOCOL_AND_CONF));
JamesServerResourceLoader directories = new
JamesServerResourceLoader(rootDirectory
@@ -190,6 +197,16 @@ public class CassandraRabbitMQJamesConfiguration
implements Configuration {
}
});
+ boolean dropListsEnabled = this.dropListsEnabled.orElseGet(() -> {
+ try {
+ return
propertiesProvider.getConfiguration("droplists").getBoolean("enabled", false);
+ } catch (FileNotFoundException e) {
+ return false;
+ } catch (ConfigurationException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
return new CassandraRabbitMQJamesConfiguration(
configurationPath,
directories,
@@ -199,7 +216,8 @@ public class CassandraRabbitMQJamesConfiguration implements
Configuration {
mailQueueChoice,
mailQueueViewChoice, vaultConfiguration,
jmapEnabled,
- quotaCompatibilityMode);
+ quotaCompatibilityMode,
+ dropListsEnabled);
}
}
@@ -217,12 +235,13 @@ public class CassandraRabbitMQJamesConfiguration
implements Configuration {
private final VaultConfiguration vaultConfiguration;
private final boolean jmapEnabled;
private final boolean quotaCompatibilityMode;
+ private final boolean dropListsEnabled;
public CassandraRabbitMQJamesConfiguration(ConfigurationPath
configurationPath, JamesDirectoriesProvider directories,
BlobStoreConfiguration
blobStoreConfiguration, SearchConfiguration searchConfiguration,
UsersRepositoryModuleChooser.Implementation usersRepositoryImplementation,
MailQueueChoice mailQueueChoice,
MailQueueViewChoice
mailQueueViewChoice, VaultConfiguration vaultConfiguration,
- boolean jmapEnabled, boolean
quotaCompatibilityMode) {
+ boolean jmapEnabled, boolean
quotaCompatibilityMode, boolean dropListsEnabled) {
this.configurationPath = configurationPath;
this.directories = directories;
this.blobStoreConfiguration = blobStoreConfiguration;
@@ -233,6 +252,7 @@ public class CassandraRabbitMQJamesConfiguration implements
Configuration {
this.vaultConfiguration = vaultConfiguration;
this.jmapEnabled = jmapEnabled;
this.quotaCompatibilityMode = quotaCompatibilityMode;
+ this.dropListsEnabled = dropListsEnabled;
}
public MailQueueViewChoice getMailQueueViewChoice() {
@@ -276,4 +296,8 @@ public class CassandraRabbitMQJamesConfiguration implements
Configuration {
public boolean isQuotaCompatibilityMode() {
return quotaCompatibilityMode;
}
+
+ public boolean isDropListsEnabled() {
+ return dropListsEnabled;
+ }
}
diff --git
a/server/apps/distributed-app/src/main/java/org/apache/james/CassandraRabbitMQJamesServerMain.java
b/server/apps/distributed-app/src/main/java/org/apache/james/CassandraRabbitMQJamesServerMain.java
index 02ccef2887..3c3b2f6d6d 100644
---
a/server/apps/distributed-app/src/main/java/org/apache/james/CassandraRabbitMQJamesServerMain.java
+++
b/server/apps/distributed-app/src/main/java/org/apache/james/CassandraRabbitMQJamesServerMain.java
@@ -41,6 +41,7 @@ import
org.apache.james.modules.blobstore.BlobStoreModulesChooser;
import org.apache.james.modules.data.CassandraDLPConfigurationStoreModule;
import org.apache.james.modules.data.CassandraDelegationStoreModule;
import org.apache.james.modules.data.CassandraDomainListModule;
+import org.apache.james.modules.data.CassandraDropListsModule;
import org.apache.james.modules.data.CassandraJmapModule;
import org.apache.james.modules.data.CassandraRecipientRewriteTableModule;
import org.apache.james.modules.data.CassandraSieveQuotaLegacyModule;
@@ -75,6 +76,7 @@ import org.apache.james.modules.queue.rabbitmq.RabbitMQModule;
import org.apache.james.modules.server.DKIMMailetModule;
import org.apache.james.modules.server.DLPRoutesModule;
import org.apache.james.modules.server.DataRoutesModules;
+import org.apache.james.modules.server.DropListsRoutesModule;
import org.apache.james.modules.server.InconsistencyQuotasSolvingRoutesModule;
import org.apache.james.modules.server.JMXServerModule;
import org.apache.james.modules.server.JmapTasksModule;
@@ -209,7 +211,8 @@ public class CassandraRabbitMQJamesServerMain implements
JamesServerMain {
.chooseModules(configuration.getUsersRepositoryImplementation()))
.combineWith(chooseDeletedMessageVault(configuration.getVaultConfiguration()))
.combineWith(chooseQuotaModule(configuration))
- .overrideWith(chooseJmapModules(configuration));
+ .overrideWith(chooseJmapModules(configuration))
+ .overrideWith(chooseDropListsModule(configuration));
}
private static Module chooseMailQueue(CassandraRabbitMQJamesConfiguration
configuration) {
@@ -258,4 +261,14 @@ public class CassandraRabbitMQJamesServerMain implements
JamesServerMain {
return Modules.combine(new CassandraMailboxQuotaModule(), new
CassandraSieveQuotaModule());
}
}
+
+ private static Module
chooseDropListsModule(CassandraRabbitMQJamesConfiguration configuration) {
+ if (configuration.isDropListsEnabled()) {
+ return Modules.combine(new CassandraDropListsModule(), new
DropListsRoutesModule());
+ }
+ return binder -> {
+
+ };
+ }
+
}
diff --git a/server/apps/memory-app/sample-configuration/droplists.properties
b/server/apps/memory-app/sample-configuration/droplists.properties
new file mode 100644
index 0000000000..bbc27568cb
--- /dev/null
+++ b/server/apps/memory-app/sample-configuration/droplists.properties
@@ -0,0 +1,3 @@
+# Configuration file for DropLists
+
+enabled=false
\ No newline at end of file
diff --git
a/server/apps/memory-app/src/main/java/org/apache/james/MemoryJamesConfiguration.java
b/server/apps/memory-app/src/main/java/org/apache/james/MemoryJamesConfiguration.java
index d186b9504d..78711d416a 100644
---
a/server/apps/memory-app/src/main/java/org/apache/james/MemoryJamesConfiguration.java
+++
b/server/apps/memory-app/src/main/java/org/apache/james/MemoryJamesConfiguration.java
@@ -41,12 +41,14 @@ public class MemoryJamesConfiguration implements
Configuration {
private Optional<ConfigurationPath> configurationPath;
private Optional<UsersRepositoryModuleChooser.Implementation>
usersRepositoryImplementation;
private Optional<Boolean> jmapEnabled;
+ private Optional<Boolean> dropListsEnabled;
private Builder() {
rootDirectory = Optional.empty();
configurationPath = Optional.empty();
usersRepositoryImplementation = Optional.empty();
jmapEnabled = Optional.empty();
+ dropListsEnabled = Optional.empty();
}
public Builder workingDirectory(String path) {
@@ -87,6 +89,11 @@ public class MemoryJamesConfiguration implements
Configuration {
return this;
}
+ public Builder enableDropLists() {
+ this.dropListsEnabled = Optional.of(true);
+ return this;
+ }
+
public MemoryJamesConfiguration build() {
ConfigurationPath configurationPath =
this.configurationPath.orElse(new
ConfigurationPath(FileSystem.FILE_PROTOCOL_AND_CONF));
JamesServerResourceLoader directories = new
JamesServerResourceLoader(rootDirectory
@@ -112,10 +119,22 @@ public class MemoryJamesConfiguration implements
Configuration {
}
});
+ boolean dropListsEnabled = this.dropListsEnabled.orElseGet(() -> {
+ PropertiesProvider propertiesProvider = new
PropertiesProvider(fileSystem, configurationPath);
+ try {
+ return
propertiesProvider.getConfiguration("droplists").getBoolean("enabled", false);
+ } catch (FileNotFoundException e) {
+ return false;
+ } catch (ConfigurationException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+
return new MemoryJamesConfiguration(
configurationPath,
directories,
- usersRepositoryChoice, jmapEnabled);
+ usersRepositoryChoice, jmapEnabled, dropListsEnabled);
}
}
@@ -127,12 +146,16 @@ public class MemoryJamesConfiguration implements
Configuration {
private final JamesDirectoriesProvider directories;
private final UsersRepositoryModuleChooser.Implementation
usersRepositoryImplementation;
private final boolean jmapEnabled;
+ private final boolean dropListsEnabled;
- public MemoryJamesConfiguration(ConfigurationPath configurationPath,
JamesDirectoriesProvider directories,
UsersRepositoryModuleChooser.Implementation usersRepositoryImplementation,
boolean jmapEnabled) {
+ public MemoryJamesConfiguration(ConfigurationPath configurationPath,
JamesDirectoriesProvider directories,
+
UsersRepositoryModuleChooser.Implementation usersRepositoryImplementation,
+ boolean jmapEnabled, boolean
dropListsEnabled) {
this.configurationPath = configurationPath;
this.directories = directories;
this.usersRepositoryImplementation = usersRepositoryImplementation;
this.jmapEnabled = jmapEnabled;
+ this.dropListsEnabled = dropListsEnabled;
}
@Override
@@ -152,4 +175,8 @@ public class MemoryJamesConfiguration implements
Configuration {
public boolean isJmapEnabled() {
return jmapEnabled;
}
+
+ public boolean isDropListsEnabled() {
+ return dropListsEnabled;
+ }
}
diff --git
a/server/apps/memory-app/src/main/java/org/apache/james/MemoryJamesServerMain.java
b/server/apps/memory-app/src/main/java/org/apache/james/MemoryJamesServerMain.java
index c7a78d206c..bcdeeaf392 100644
---
a/server/apps/memory-app/src/main/java/org/apache/james/MemoryJamesServerMain.java
+++
b/server/apps/memory-app/src/main/java/org/apache/james/MemoryJamesServerMain.java
@@ -34,6 +34,7 @@ import org.apache.james.modules.RunArgumentsModule;
import org.apache.james.modules.data.MemoryDataJmapModule;
import org.apache.james.modules.data.MemoryDataModule;
import org.apache.james.modules.data.MemoryDelegationStoreModule;
+import org.apache.james.modules.data.MemoryDropListsModule;
import org.apache.james.modules.data.MemoryUsersRepositoryModule;
import org.apache.james.modules.eventstore.MemoryEventStoreModule;
import org.apache.james.modules.mailbox.MemoryMailboxModule;
@@ -49,6 +50,7 @@ import
org.apache.james.modules.queue.memory.MemoryMailQueueModule;
import org.apache.james.modules.server.DKIMMailetModule;
import org.apache.james.modules.server.DLPRoutesModule;
import org.apache.james.modules.server.DataRoutesModules;
+import org.apache.james.modules.server.DropListsRoutesModule;
import org.apache.james.modules.server.InconsistencyQuotasSolvingRoutesModule;
import org.apache.james.modules.server.JMXServerModule;
import org.apache.james.modules.server.JmapTasksModule;
@@ -174,7 +176,8 @@ public class MemoryJamesServerMain implements
JamesServerMain {
.combineWith(IN_MEMORY_SERVER_AGGREGATE_MODULE)
.combineWith(new UsersRepositoryModuleChooser(new
MemoryUsersRepositoryModule())
.chooseModules(configuration.getUsersRepositoryImplementation()))
- .combineWith(chooseJmapModule(configuration));
+ .combineWith(chooseJmapModule(configuration))
+ .combineWith(chooseDropListsModule(configuration));
}
private static Module chooseJmapModule(MemoryJamesConfiguration
configuration) {
@@ -186,4 +189,13 @@ public class MemoryJamesServerMain implements
JamesServerMain {
};
}
+ private static Module chooseDropListsModule(MemoryJamesConfiguration
configuration) {
+ if (configuration.isDropListsEnabled()) {
+ return Modules.combine(new MemoryDropListsModule(), new
DropListsRoutesModule());
+ }
+ return binder -> {
+
+ };
+ }
+
}
diff --git
a/server/container/guice/cassandra/src/main/java/org/apache/james/modules/data/CassandraDropListsModule.java
b/server/container/guice/cassandra/src/main/java/org/apache/james/modules/data/CassandraDropListsModule.java
new file mode 100644
index 0000000000..450cc8529d
--- /dev/null
+++
b/server/container/guice/cassandra/src/main/java/org/apache/james/modules/data/CassandraDropListsModule.java
@@ -0,0 +1,33 @@
+/****************************************************************
+ * 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.modules.data;
+
+import org.apache.james.droplists.api.DropList;
+import org.apache.james.droplists.cassandra.CassandraDropList;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Scopes;
+
+public class CassandraDropListsModule extends AbstractModule {
+ @Override
+ protected void configure() {
+ bind(DropList.class).to(CassandraDropList.class).in(Scopes.SINGLETON);
+ }
+}
\ No newline at end of file
diff --git
a/server/container/guice/memory/src/main/java/org/apache/james/modules/data/MemoryDropListsModule.java
b/server/container/guice/memory/src/main/java/org/apache/james/modules/data/MemoryDropListsModule.java
new file mode 100644
index 0000000000..7810e73eba
--- /dev/null
+++
b/server/container/guice/memory/src/main/java/org/apache/james/modules/data/MemoryDropListsModule.java
@@ -0,0 +1,33 @@
+/****************************************************************
+ * 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.modules.data;
+
+import org.apache.james.droplists.api.DropList;
+import org.apache.james.droplists.memory.MemoryDropList;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Scopes;
+
+public class MemoryDropListsModule extends AbstractModule {
+ @Override
+ public void configure() {
+ bind(DropList.class).to(MemoryDropList.class).in(Scopes.SINGLETON);
+ }
+}
\ No newline at end of file
diff --git
a/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DropListsRoutesModule.java
b/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DropListsRoutesModule.java
new file mode 100644
index 0000000000..5a064221ea
--- /dev/null
+++
b/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DropListsRoutesModule.java
@@ -0,0 +1,34 @@
+/****************************************************************
+ * 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.modules.server;
+
+import org.apache.james.webadmin.Routes;
+import org.apache.james.webadmin.routes.DropListRoutes;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.multibindings.Multibinder;
+
+public class DropListsRoutesModule extends AbstractModule {
+ @Override
+ protected void configure() {
+ Multibinder.newSetBinder(binder(), Routes.class).addBinding()
+ .to(DropListRoutes.class);
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]