JAMES-2413 Enable / disable repository creation in ToSenderDomainRepository


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/addce27e
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/addce27e
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/addce27e

Branch: refs/heads/master
Commit: addce27e46343b643404aebb9e05a9a7290ef06f
Parents: be94620
Author: benwa <btell...@linagora.com>
Authored: Thu Jun 7 11:03:52 2018 +0700
Committer: benwa <btell...@linagora.com>
Committed: Wed Jun 13 09:42:35 2018 +0700

----------------------------------------------------------------------
 .../james/utils/MailRepositoryProbeImpl.java    |   9 ++
 .../mailets/ToSenderDomainRepositoryTest.java   | 131 ++++++++++++++++---
 .../mailets/ToSenderDomainRepository.java       |  31 ++++-
 3 files changed, 150 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/addce27e/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProbeImpl.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProbeImpl.java
 
b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProbeImpl.java
index e3143f2..f49fedd 100644
--- 
a/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProbeImpl.java
+++ 
b/server/container/guice/guice-common/src/main/java/org/apache/james/utils/MailRepositoryProbeImpl.java
@@ -43,10 +43,19 @@ public class MailRepositoryProbeImpl implements GuiceProbe {
         return repositoryStore.select(url).size();
     }
 
+    public void createRepository(String url) throws Exception {
+        repositoryStore.select(url);
+    }
+
     public List<String> listMailKeys(String url) throws Exception {
         return ImmutableList.copyOf(
             repositoryStore.select(url)
                 .list());
     }
 
+    public List<String> listRepositoryUrls() {
+        return ImmutableList.copyOf(
+            repositoryStore.getUrls());
+    }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/addce27e/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ToSenderDomainRepositoryTest.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ToSenderDomainRepositoryTest.java
 
b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ToSenderDomainRepositoryTest.java
index 1e19e08..b811e8f 100644
--- 
a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ToSenderDomainRepositoryTest.java
+++ 
b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ToSenderDomainRepositoryTest.java
@@ -24,19 +24,18 @@ import static 
org.apache.james.mailets.configuration.Constants.LOCALHOST_IP;
 import static org.apache.james.mailets.configuration.Constants.PASSWORD;
 import static org.apache.james.mailets.configuration.Constants.SMTP_PORT;
 import static 
org.apache.james.mailets.configuration.Constants.awaitAtMostOneMinute;
+import static org.assertj.core.api.Assertions.assertThat;
 
 import org.apache.james.mailets.TemporaryJamesServer;
 import org.apache.james.mailets.configuration.MailetConfiguration;
 import org.apache.james.mailets.configuration.MailetContainer;
 import org.apache.james.mailets.configuration.ProcessorConfiguration;
-import org.apache.james.probe.DataProbe;
 import org.apache.james.transport.matchers.All;
 import org.apache.james.utils.DataProbeImpl;
 import org.apache.james.utils.IMAPMessageReader;
 import org.apache.james.utils.MailRepositoryProbeImpl;
 import org.apache.james.utils.SMTPMessageSender;
 import org.junit.After;
-import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
@@ -45,6 +44,7 @@ public class ToSenderDomainRepositoryTest {
 
     private static final String RECIPIENT = "touser@" + DEFAULT_DOMAIN;
     private static final String CUSTOM_REPOSITORY_PREFIX = 
"file://var/mail/custom/";
+    public static final String AWAIT_REPOSITORY_PATH = 
"file://var/mail/await/";
 
     @Rule
     public TemporaryFolder temporaryFolder = new TemporaryFolder();
@@ -54,49 +54,140 @@ public class ToSenderDomainRepositoryTest {
     public SMTPMessageSender messageSender = new 
SMTPMessageSender(DEFAULT_DOMAIN);
 
     private TemporaryJamesServer jamesServer;
-    private MailRepositoryProbeImpl probe;
 
-    @Before
-    public void setup() throws Exception {
-        MailetContainer.Builder mailetContainer = 
TemporaryJamesServer.SIMPLE_MAILET_CONTAINER_CONFIGURATION
+    @After
+    public void tearDown() {
+        if (jamesServer != null) {
+            jamesServer.shutdown();
+        }
+    }
+
+    @Test
+    public void incomingMailShouldBeStoredInCorrespondingMailRepository() 
throws Exception {
+        
initializeJamesServer(TemporaryJamesServer.SIMPLE_MAILET_CONTAINER_CONFIGURATION
             .putProcessor(ProcessorConfiguration.root()
                 .addMailet(MailetConfiguration.builder()
                     .matcher(All.class)
                     .mailet(ToSenderDomainRepository.class)
-                    .addProperty("urlPrefix", CUSTOM_REPOSITORY_PREFIX)));
+                    .addProperty("urlPrefix", CUSTOM_REPOSITORY_PREFIX))));
 
-        jamesServer = TemporaryJamesServer.builder()
-            .withMailetContainer(mailetContainer)
-            .build(temporaryFolder);
+        messageSender.connect(LOCALHOST_IP, SMTP_PORT)
+            .sendMessage(RECIPIENT, RECIPIENT);
+
+        awaitAtMostOneMinute.until(
+            () -> jamesServer.getProbe(MailRepositoryProbeImpl.class)
+                .getRepositoryMailCount(CUSTOM_REPOSITORY_PREFIX + 
DEFAULT_DOMAIN) == 1);
+    }
+
+    @Test
+    public void 
incomingMailShouldBeStoredWhenRepositoryDoNotExistAndAllowedToCreateRepository()
 throws Exception {
+        
initializeJamesServer(TemporaryJamesServer.SIMPLE_MAILET_CONTAINER_CONFIGURATION
+            .putProcessor(ProcessorConfiguration.root()
+                .addMailet(MailetConfiguration.builder()
+                    .matcher(All.class)
+                    .mailet(ToSenderDomainRepository.class)
+                    .addProperty("urlPrefix", CUSTOM_REPOSITORY_PREFIX)
+                    .addProperty("allowRepositoryCreation", "true"))));
 
-        DataProbe dataProbe = jamesServer.getProbe(DataProbeImpl.class);
-        dataProbe.addDomain(DEFAULT_DOMAIN);
-        dataProbe.addUser(RECIPIENT, PASSWORD);
+        messageSender.connect(LOCALHOST_IP, SMTP_PORT)
+            .sendMessage(RECIPIENT, RECIPIENT);
 
-        probe = jamesServer.getProbe(MailRepositoryProbeImpl.class);
+        awaitAtMostOneMinute.until(
+            () -> jamesServer.getProbe(MailRepositoryProbeImpl.class)
+                .getRepositoryMailCount(CUSTOM_REPOSITORY_PREFIX + 
DEFAULT_DOMAIN) == 1);
     }
 
-    @After
-    public void tearDown() {
-        jamesServer.shutdown();
+    @Test
+    public void 
incomingMailShouldBeStoredWhenRepositoryExistsAndAllowedToCreateRepository() 
throws Exception {
+        
initializeJamesServer(TemporaryJamesServer.SIMPLE_MAILET_CONTAINER_CONFIGURATION
+            .putProcessor(ProcessorConfiguration.root()
+                .addMailet(MailetConfiguration.builder()
+                    .matcher(All.class)
+                    .mailet(ToSenderDomainRepository.class)
+                    .addProperty("urlPrefix", CUSTOM_REPOSITORY_PREFIX)
+                    .addProperty("allowRepositoryCreation", "true"))));
+        jamesServer.getProbe(MailRepositoryProbeImpl.class)
+            .createRepository(CUSTOM_REPOSITORY_PREFIX + DEFAULT_DOMAIN);
+
+        messageSender.connect(LOCALHOST_IP, SMTP_PORT)
+            .sendMessage(RECIPIENT, RECIPIENT);
+
+        awaitAtMostOneMinute.until(
+            () -> jamesServer.getProbe(MailRepositoryProbeImpl.class)
+                .getRepositoryMailCount(CUSTOM_REPOSITORY_PREFIX + 
DEFAULT_DOMAIN) == 1);
     }
 
     @Test
-    public void incomingMailShouldBeStoredInCorrespondingMailRepository() 
throws Exception {
+    public void 
incomingMailShouldBeIgnoredWhenRepositoryDoNotExistAndNotAllowedToCreateRepository()
 throws Exception {
+        
initializeJamesServer(TemporaryJamesServer.SIMPLE_MAILET_CONTAINER_CONFIGURATION
+            .putProcessor(ProcessorConfiguration.root()
+                .addMailet(MailetConfiguration.builder()
+                    .matcher(All.class)
+                    .mailet(ToSenderDomainRepository.class)
+                    .addProperty("urlPrefix", CUSTOM_REPOSITORY_PREFIX)
+                    .addProperty("allowRepositoryCreation", "false")
+                    .addProperty("passThrough", "true"))
+                .addMailet(MailetConfiguration.builder()
+                    .matcher(All.class)
+                    .mailet(ToRepository.class)
+                    .addProperty("repositoryPath", AWAIT_REPOSITORY_PATH))));
+        MailRepositoryProbeImpl mailRepositoryProbe = 
jamesServer.getProbe(MailRepositoryProbeImpl.class);
+
         messageSender.connect(LOCALHOST_IP, SMTP_PORT)
             .sendMessage(RECIPIENT, RECIPIENT);
 
         awaitAtMostOneMinute.until(
-            () -> probe.getRepositoryMailCount(CUSTOM_REPOSITORY_PREFIX + 
DEFAULT_DOMAIN) == 1);
+            () -> 
mailRepositoryProbe.getRepositoryMailCount(AWAIT_REPOSITORY_PATH) == 1);
+
+        assertThat(mailRepositoryProbe.listRepositoryUrls())
+            .doesNotContain(CUSTOM_REPOSITORY_PREFIX + DEFAULT_DOMAIN);
+    }
+
+    @Test
+    public void 
incomingMailShouldBeStoredWhenRepositoryExistsAndNotAllowedToCreateRepository() 
throws Exception {
+        
initializeJamesServer(TemporaryJamesServer.SIMPLE_MAILET_CONTAINER_CONFIGURATION
+            .putProcessor(ProcessorConfiguration.root()
+                .addMailet(MailetConfiguration.builder()
+                    .matcher(All.class)
+                    .mailet(ToSenderDomainRepository.class)
+                    .addProperty("urlPrefix", CUSTOM_REPOSITORY_PREFIX)
+                    .addProperty("allowRepositoryCreation", "false"))));
+        jamesServer.getProbe(MailRepositoryProbeImpl.class)
+            .createRepository(CUSTOM_REPOSITORY_PREFIX + DEFAULT_DOMAIN);
+
+        messageSender.connect(LOCALHOST_IP, SMTP_PORT)
+            .sendMessage(RECIPIENT, RECIPIENT);
+
+        awaitAtMostOneMinute.until(
+            () -> jamesServer.getProbe(MailRepositoryProbeImpl.class)
+                .getRepositoryMailCount(CUSTOM_REPOSITORY_PREFIX + 
DEFAULT_DOMAIN) == 1);
     }
 
     @Test
     public void incomingMailsShouldBeStoredInCorrespondingMailRepository() 
throws Exception {
+        
initializeJamesServer(TemporaryJamesServer.SIMPLE_MAILET_CONTAINER_CONFIGURATION
+            .putProcessor(ProcessorConfiguration.root()
+                .addMailet(MailetConfiguration.builder()
+                    .matcher(All.class)
+                    .mailet(ToSenderDomainRepository.class)
+                    .addProperty("urlPrefix", CUSTOM_REPOSITORY_PREFIX))));
+
         messageSender.connect(LOCALHOST_IP, SMTP_PORT)
             .sendMessage(RECIPIENT, RECIPIENT)
             .sendMessage(RECIPIENT, RECIPIENT);
 
         awaitAtMostOneMinute.until(
-            () -> probe.getRepositoryMailCount(CUSTOM_REPOSITORY_PREFIX + 
DEFAULT_DOMAIN) == 2);
+            () -> jamesServer.getProbe(MailRepositoryProbeImpl.class)
+                .getRepositoryMailCount(CUSTOM_REPOSITORY_PREFIX + 
DEFAULT_DOMAIN) == 2);
+    }
+
+    private void initializeJamesServer(MailetContainer.Builder 
mailetContainer) throws Exception {
+        jamesServer = TemporaryJamesServer.builder()
+            .withMailetContainer(mailetContainer)
+            .build(temporaryFolder);
+
+        jamesServer.getProbe(DataProbeImpl.class)
+            .fluentAddDomain(DEFAULT_DOMAIN)
+            .fluentAddUser(RECIPIENT, PASSWORD);
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/addce27e/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/ToSenderDomainRepository.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/ToSenderDomainRepository.java
 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/ToSenderDomainRepository.java
index b86482e..8f417c6 100644
--- 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/ToSenderDomainRepository.java
+++ 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/ToSenderDomainRepository.java
@@ -24,9 +24,15 @@ import java.util.Optional;
 import javax.inject.Inject;
 import javax.mail.MessagingException;
 
+import org.apache.james.mailrepository.api.MailRepository;
 import org.apache.james.mailrepository.api.MailRepositoryStore;
 import org.apache.mailet.Mail;
 import org.apache.mailet.base.GenericMailet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.github.fge.lambdas.Throwing;
+import com.github.fge.lambdas.consumers.ThrowingConsumer;
 
 /**
  * Stores incoming Mail in a repository defined by the sender's domain.<br>
@@ -37,21 +43,29 @@ import org.apache.mailet.base.GenericMailet;
  *  For example for the value 'cassandra://var/mail/sendersRepositories/', a 
mail sent by 'u...@james.org'
  *  will be stored in 'cassandra://var/mail/sendersRepositories/james.org'.
  *  - "passThrough" optional, defaults to false. If true, the processing of 
the mail continues. If false it stops.
+ *  - "allowRepositoryCreation" optional, defaults to true. If true, non 
existing repository will be created. In case of
+ *  misconfiguration, this might lead to arbitrary repository creation. If 
false, the incoming mails will be stored only
+ *  in already existing repository. If not existing, the email will be dropped 
with an appropriate log warning (leading
+ *  to potential data loss).
  *
  *  Example:
  *
  * &lt;mailet matcher="All" class="ToSenderDomainRepository"&gt;
  *     
&lt;urlPrefix&gt;cassandra://var/mail/sendersRepositories/&lt;/urlPrefix&gt;
  *     &lt;passThrough&gt;false&lt;/passThrough&gt;
+ *     &lt;allowRepositoryCreation&gt;true&lt;/allowRepositoryCreation&gt;
  * &lt;/mailet&gt;
  */
 public class ToSenderDomainRepository extends GenericMailet {
 
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(ToSenderDomainRepository.class);
     private static final boolean DEFAULT_CONSUME = false;
+    private static final boolean DEFAULT_ALLOW_REPOSITORY_CREATION = true;
 
     private final MailRepositoryStore mailRepositoryStore;
     private String urlPrefix;
     private boolean passThrough;
+    private boolean allowRepositoryCreation;
 
     @Inject
     public ToSenderDomainRepository(MailRepositoryStore mailRepositoryStore) {
@@ -63,6 +77,7 @@ public class ToSenderDomainRepository extends GenericMailet {
         urlPrefix = Optional.ofNullable(getInitParameter("urlPrefix"))
             .orElseThrow(() -> new MessagingException("'urlPrefix' is a 
mandatory configuration property"));
         passThrough = getInitParameter("passThrough", DEFAULT_CONSUME);
+        allowRepositoryCreation = getInitParameter("allowRepositoryCreation", 
DEFAULT_ALLOW_REPOSITORY_CREATION);
     }
 
     @Override
@@ -76,12 +91,26 @@ public class ToSenderDomainRepository extends GenericMailet 
{
 
     private void store(Mail mail, String url) throws MessagingException {
         try {
-            mailRepositoryStore.select(url).store(mail);
+            Optional<MailRepository> mailRepository = retrieveRepository(url);
+            if (!mailRepository.isPresent()) {
+                LOGGER.warn("'{}' mail repository does not exist and will not 
be created. Mail {} will not be stored in it.",
+                    url, mail.getName());
+            }
+            ThrowingConsumer<MailRepository> storingConsumer = repository -> 
repository.store(mail);
+            
mailRepository.ifPresent(Throwing.consumer(storingConsumer).sneakyThrow());
         } catch (MailRepositoryStore.MailRepositoryStoreException e) {
             throw new MessagingException("Error while selecting url " + url, 
e);
         }
     }
 
+    private Optional<MailRepository> retrieveRepository(String url) throws 
MailRepositoryStore.MailRepositoryStoreException {
+        if (allowRepositoryCreation) {
+            return Optional.of(mailRepositoryStore.select(url));
+        } else {
+            return mailRepositoryStore.get(url);
+        }
+    }
+
     @Override
     public String getMailetInfo() {
         return "ToSenderDomainRepository Mailet";


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org
For additional commands, e-mail: server-dev-h...@james.apache.org

Reply via email to