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 2018/06/13 02:49:13 UTC

[4/8] james-project git commit: JAMES-2413 [DLP] Mailet to store an email in a repository depending on the domain of the sender

JAMES-2413 [DLP] Mailet to store an email in a repository depending on the domain of the sender


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

Branch: refs/heads/master
Commit: adfcf46d62be5c2eb5e2a174123ae40dbb12349b
Parents: ca761df
Author: duc <tr...@gmail.com>
Authored: Wed Jun 6 16:55:06 2018 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Jun 13 09:42:35 2018 +0700

----------------------------------------------------------------------
 .../mailets/ToSenderDomainRepositoryTest.java   | 102 ++++++++++
 server/mailet/mailets/pom.xml                   |  31 ++-
 .../mailets/ToSenderDomainRepository.java       |  89 +++++++++
 .../mailets/ToSenderDomainRepositoryTest.java   | 195 +++++++++++++++++++
 4 files changed, 412 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/adfcf46d/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
new file mode 100644
index 0000000..1e19e08
--- /dev/null
+++ b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/ToSenderDomainRepositoryTest.java
@@ -0,0 +1,102 @@
+/****************************************************************
+ * 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.transport.mailets;
+
+import static org.apache.james.mailets.configuration.Constants.DEFAULT_DOMAIN;
+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 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;
+
+public class ToSenderDomainRepositoryTest {
+
+    private static final String RECIPIENT = "touser@" + DEFAULT_DOMAIN;
+    private static final String CUSTOM_REPOSITORY_PREFIX = "file://var/mail/custom/";
+
+    @Rule
+    public TemporaryFolder temporaryFolder = new TemporaryFolder();
+    @Rule
+    public IMAPMessageReader imapMessageReader = new IMAPMessageReader();
+    @Rule
+    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
+            .putProcessor(ProcessorConfiguration.root()
+                .addMailet(MailetConfiguration.builder()
+                    .matcher(All.class)
+                    .mailet(ToSenderDomainRepository.class)
+                    .addProperty("urlPrefix", CUSTOM_REPOSITORY_PREFIX)));
+
+        jamesServer = TemporaryJamesServer.builder()
+            .withMailetContainer(mailetContainer)
+            .build(temporaryFolder);
+
+        DataProbe dataProbe = jamesServer.getProbe(DataProbeImpl.class);
+        dataProbe.addDomain(DEFAULT_DOMAIN);
+        dataProbe.addUser(RECIPIENT, PASSWORD);
+
+        probe = jamesServer.getProbe(MailRepositoryProbeImpl.class);
+    }
+
+    @After
+    public void tearDown() {
+        jamesServer.shutdown();
+    }
+
+    @Test
+    public void incomingMailShouldBeStoredInCorrespondingMailRepository() throws Exception {
+        messageSender.connect(LOCALHOST_IP, SMTP_PORT)
+            .sendMessage(RECIPIENT, RECIPIENT);
+
+        awaitAtMostOneMinute.until(
+            () -> probe.getRepositoryMailCount(CUSTOM_REPOSITORY_PREFIX + DEFAULT_DOMAIN) == 1);
+    }
+
+    @Test
+    public void incomingMailsShouldBeStoredInCorrespondingMailRepository() throws Exception {
+        messageSender.connect(LOCALHOST_IP, SMTP_PORT)
+            .sendMessage(RECIPIENT, RECIPIENT)
+            .sendMessage(RECIPIENT, RECIPIENT);
+
+        awaitAtMostOneMinute.until(
+            () -> probe.getRepositoryMailCount(CUSTOM_REPOSITORY_PREFIX + DEFAULT_DOMAIN) == 2);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/adfcf46d/server/mailet/mailets/pom.xml
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/pom.xml b/server/mailet/mailets/pom.xml
index fdbe73a..eb72017 100644
--- a/server/mailet/mailets/pom.xml
+++ b/server/mailet/mailets/pom.xml
@@ -113,6 +113,12 @@
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>james-server-data-library</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>james-server-data-memory</artifactId>
             <scope>test</scope>
         </dependency>
@@ -140,6 +146,11 @@
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>james-server-mailrepository-memory</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>james-server-queue-api</artifactId>
         </dependency>
         <dependency>
@@ -192,11 +203,6 @@
             <artifactId>joda-time</artifactId>
         </dependency>
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
         </dependency>
@@ -230,6 +236,21 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.platform</groupId>
+            <artifactId>junit-platform-launcher</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.vintage</groupId>
+            <artifactId>junit-vintage-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-core</artifactId>
             <scope>test</scope>

http://git-wip-us.apache.org/repos/asf/james-project/blob/adfcf46d/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
new file mode 100644
index 0000000..b86482e
--- /dev/null
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/ToSenderDomainRepository.java
@@ -0,0 +1,89 @@
+/****************************************************************
+ * 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.transport.mailets;
+
+import java.util.Optional;
+
+import javax.inject.Inject;
+import javax.mail.MessagingException;
+
+import org.apache.james.mailrepository.api.MailRepositoryStore;
+import org.apache.mailet.Mail;
+import org.apache.mailet.base.GenericMailet;
+
+/**
+ * Stores incoming Mail in a repository defined by the sender's domain.<br>
+ *
+ * Supported configuration parameters:
+ *
+ *  - "urlPrefix" mandatory: defines the prefix for the per sender's domain repository.
+ *  For example for the value 'cassandra://var/mail/sendersRepositories/', a mail sent by 'user@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.
+ *
+ *  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;/mailet&gt;
+ */
+public class ToSenderDomainRepository extends GenericMailet {
+
+    private static final boolean DEFAULT_CONSUME = false;
+
+    private final MailRepositoryStore mailRepositoryStore;
+    private String urlPrefix;
+    private boolean passThrough;
+
+    @Inject
+    public ToSenderDomainRepository(MailRepositoryStore mailRepositoryStore) {
+        this.mailRepositoryStore = mailRepositoryStore;
+    }
+
+    @Override
+    public void init() throws MessagingException {
+        urlPrefix = Optional.ofNullable(getInitParameter("urlPrefix"))
+            .orElseThrow(() -> new MessagingException("'urlPrefix' is a mandatory configuration property"));
+        passThrough = getInitParameter("passThrough", DEFAULT_CONSUME);
+    }
+
+    @Override
+    public void service(Mail mail) throws MessagingException {
+        String url = urlPrefix + mail.getSender().getDomain().asString();
+        store(mail, url);
+        if (!passThrough) {
+            mail.setState(Mail.GHOST);
+        }
+    }
+
+    private void store(Mail mail, String url) throws MessagingException {
+        try {
+            mailRepositoryStore.select(url).store(mail);
+        } catch (MailRepositoryStore.MailRepositoryStoreException e) {
+            throw new MessagingException("Error while selecting url " + url, e);
+        }
+    }
+
+    @Override
+    public String getMailetInfo() {
+        return "ToSenderDomainRepository Mailet";
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/adfcf46d/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/ToSenderDomainRepositoryTest.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/ToSenderDomainRepositoryTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/ToSenderDomainRepositoryTest.java
new file mode 100644
index 0000000..e532e90
--- /dev/null
+++ b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/ToSenderDomainRepositoryTest.java
@@ -0,0 +1,195 @@
+/****************************************************************
+ * 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.transport.mailets;
+
+import static org.apache.mailet.base.MailAddressFixture.JAMES_LOCAL;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import javax.mail.MessagingException;
+
+import org.apache.james.mailrepository.api.MailRepository;
+import org.apache.james.mailrepository.api.MailRepositoryStore;
+import org.apache.james.mailrepository.memory.MemoryMailRepository;
+import org.apache.james.mailrepository.mock.MockMailRepositoryStore;
+import org.apache.mailet.Mail;
+import org.apache.mailet.base.MailAddressFixture;
+import org.apache.mailet.base.test.FakeMail;
+import org.apache.mailet.base.test.FakeMailetConfig;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class ToSenderDomainRepositoryTest {
+
+    private static final FakeMailetConfig DEFAULT_MAILET_CONFIG = FakeMailetConfig.builder()
+        .mailetName("TestConfig")
+        .setProperty("urlPrefix", "memory://var/mail/dlp/")
+        .build();
+    private ToSenderDomainRepository mailet;
+    private MockMailRepositoryStore mailRepositoryStore;
+
+    @BeforeEach
+    void setup() {
+        mailRepositoryStore = new MockMailRepositoryStore();
+        mailRepositoryStore.add("memory://var/mail/dlp/" + JAMES_LOCAL, new MemoryMailRepository());
+        mailet = new ToSenderDomainRepository(mailRepositoryStore);
+    }
+
+    @Test
+    void initShouldThrowExceptionWhenUrlPrefixIsAbsent() {
+        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
+            .mailetName("Test")
+            .build();
+
+        assertThatThrownBy(() -> mailet.init(mailetConfig))
+            .isInstanceOf(MessagingException.class);
+    }
+
+    @Test
+    void initShouldNotThrowWhenUrlPrefixIsPresent() throws MessagingException {
+        mailet.init(DEFAULT_MAILET_CONFIG);
+    }
+
+    @Test
+    void serviceShouldStoreMailInRepository() throws Exception {
+        mailet.init(DEFAULT_MAILET_CONFIG);
+
+        String mailName = "mailName";
+        mailet.service(FakeMail.builder()
+            .name(mailName)
+            .sender(MailAddressFixture.SENDER)
+            .build());
+
+        MailRepository mailRepository = mailRepositoryStore.select("memory://var/mail/dlp/" + JAMES_LOCAL);
+
+        assertThat(mailRepository.list())
+            .extracting(mailRepository::retrieve)
+            .extracting(Mail::getName)
+            .containsOnly(mailName);
+    }
+
+    @Test
+    void serviceShouldGhostMailWhenNotPassThrough() throws Exception {
+        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
+            .mailetName("TestConfig")
+            .setProperty("passThrough", "false")
+            .setProperty("urlPrefix", "memory://var/mail/dlp/")
+            .build();
+        mailet.init(mailetConfig);
+
+        FakeMail mail = FakeMail.builder()
+            .name("mailName")
+            .sender(MailAddressFixture.SENDER)
+            .state(Mail.DEFAULT)
+            .build();
+
+        mailet.service(mail);
+
+        assertThat(mail.getState())
+            .isEqualTo(Mail.GHOST);
+    }
+
+    @Test
+    void serviceShouldPreserveMailStateWhenPassThrough() throws Exception {
+        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
+            .mailetName("TestConfig")
+            .setProperty("passThrough", "true")
+            .setProperty("urlPrefix", "memory://var/mail/dlp/")
+            .build();
+        mailet.init(mailetConfig);
+
+        FakeMail mail = FakeMail.builder()
+            .name("mailName")
+            .sender(MailAddressFixture.SENDER)
+            .state(Mail.DEFAULT)
+            .build();
+
+        mailet.service(mail);
+
+        assertThat(mail.getState())
+            .isEqualTo(Mail.DEFAULT);
+    }
+
+    @Test
+    void passThroughShouldDefaultToFalse() throws Exception {
+        mailet.init(DEFAULT_MAILET_CONFIG);
+
+        FakeMail mail = FakeMail.builder()
+            .name("mailName")
+            .sender(MailAddressFixture.SENDER)
+            .state(Mail.DEFAULT)
+            .build();
+
+        mailet.service(mail);
+
+        assertThat(mail.getState())
+            .isEqualTo(Mail.GHOST);
+    }
+
+    @Test
+    void initShouldSetNotPassThroughWhenPassThroughIsNotSet() throws Exception {
+        MailRepositoryStore mailRepositoryStore = mock(MailRepositoryStore.class);
+        ToSenderDomainRepository mailet = new ToSenderDomainRepository(mailRepositoryStore);
+        when(mailRepositoryStore.select(any()))
+            .thenThrow(new MailRepositoryStore.MailRepositoryStoreException("any"));
+
+        mailet.init(DEFAULT_MAILET_CONFIG);
+
+        FakeMail mail = FakeMail.builder()
+            .name("mailName")
+            .sender(MailAddressFixture.SENDER)
+            .state(Mail.DEFAULT)
+            .build();
+
+        assertThatThrownBy(() -> mailet.service(mail))
+            .isInstanceOf(MessagingException.class);
+    }
+
+    @Test
+    void initShouldSetNotPassThroughWhenPassThroughIsNotBoolean() throws Exception {
+        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
+            .mailetName("TestConfig")
+            .setProperty("urlPrefix", "memory://var/mail/dlp/")
+            .setProperty("passThrough", "not boolean")
+            .build();
+
+        mailet.init(mailetConfig);
+
+        FakeMail mail = FakeMail.builder()
+            .name("mailName")
+            .sender(MailAddressFixture.SENDER)
+            .state(Mail.DEFAULT)
+            .build();
+
+        mailet.service(mail);
+
+        assertThat(mail.getState())
+            .isEqualTo(Mail.GHOST);
+    }
+
+    @Test
+    void getMailetInfoShouldReturnExpectedResult() {
+        assertThat(mailet.getMailetInfo())
+            .isEqualTo("ToSenderDomainRepository Mailet");
+    }
+}


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