This is an automated email from the ASF dual-hosted git repository.
btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
The following commit(s) were added to refs/heads/master by this push:
new ccb731a JAMES-2912 RemoteDelivery: add a onSuccess processor (#776)
ccb731a is described below
commit ccb731acf93e01d389da416680ebd445dc663dbb
Author: Benoit TELLIER <[email protected]>
AuthorDate: Thu Dec 9 14:14:59 2021 +0700
JAMES-2912 RemoteDelivery: add a onSuccess processor (#776)
Convenient to emit success DSNs and track
successful sends, eg via logging.
---
.../docs/modules/ROOT/partials/RemoteDelivery.adoc | 6 +
.../james/utils/MailRepositoryProbeImpl.java | 6 +
.../james/transport/mailets/RemoteDelivery.java | 6 +
.../mailets/remote/delivery/DeliveryRunnable.java | 11 +-
.../mailets/remote/delivery/MailDelivrer.java | 31 ++-
.../delivery/RemoteDeliveryConfiguration.java | 7 +
.../remote/delivery/DeliveryRunnableTest.java | 3 +-
.../mailets/remote/delivery/MailDelivrerTest.java | 3 +-
.../james/mailets/RemoteDeliveryOnSuccessTest.java | 235 +++++++++++++++++++++
9 files changed, 297 insertions(+), 11 deletions(-)
diff --git
a/server/apps/distributed-app/docs/modules/ROOT/partials/RemoteDelivery.adoc
b/server/apps/distributed-app/docs/modules/ROOT/partials/RemoteDelivery.adoc
index 89ab13c..18c3a57 100644
--- a/server/apps/distributed-app/docs/modules/ROOT/partials/RemoteDelivery.adoc
+++ b/server/apps/distributed-app/docs/modules/ROOT/partials/RemoteDelivery.adoc
@@ -35,6 +35,12 @@ Default is 0.
* *connectionTimeout* (optional) - an Integer for the Socket connection
timeout in milliseconds. Default is 60000
* *bounceProcessor* (optional) - a String containing the name of the mailet
processor to pass messages that cannot
be delivered to for DSN bounce processing. Default is to send a traditional
message containing the bounce details.
+* *onSuccess* (optional) - if specified, this processor is called for each
email successfully sent to remote third parties.
+
+When using bounceProcessor or onSuccess processors, take special care of error
handling (see onMailetException and onMatcherException)
+ to avoid confusing situations. Also remember that on partial delivery, both
processors will be used: *onSuccess* with successfull recipients,
+ and *bounceProcessor* with failed recipients.
+
* *startTLS* (optional) - a Boolean (true/false) indicating whether the
STARTTLS command (if supported by the server)
to switch the connection to a TLS-protected connection before issuing any
login commands. Default is false.
* *sslEnable* (optional) - a Boolean (true/false) indicating whether to use
SSL to connect and use the SSL port unless
diff --git
a/server/container/guice/common/src/main/java/org/apache/james/utils/MailRepositoryProbeImpl.java
b/server/container/guice/common/src/main/java/org/apache/james/utils/MailRepositoryProbeImpl.java
index 2d88a87..129fabd 100644
---
a/server/container/guice/common/src/main/java/org/apache/james/utils/MailRepositoryProbeImpl.java
+++
b/server/container/guice/common/src/main/java/org/apache/james/utils/MailRepositoryProbeImpl.java
@@ -26,6 +26,7 @@ import javax.inject.Inject;
import org.apache.james.mailrepository.api.MailKey;
import org.apache.james.mailrepository.api.MailRepositoryStore;
import org.apache.james.mailrepository.api.MailRepositoryUrl;
+import org.apache.mailet.Mail;
import com.google.common.collect.ImmutableList;
@@ -55,6 +56,11 @@ public class MailRepositoryProbeImpl implements GuiceProbe {
.list());
}
+ public Mail getMail(MailRepositoryUrl url, MailKey key) throws Exception {
+ return repositoryStore.select(url)
+ .retrieve(key);
+ }
+
public List<MailRepositoryUrl> listRepositoryUrls() {
return repositoryStore.getUrls()
.collect(ImmutableList.toImmutableList());
diff --git
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
index 130267d..67e95d5 100644
---
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
+++
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
@@ -83,6 +83,12 @@ import com.google.common.collect.HashMultimap;
* <li><b>connectionTimeout</b> (optional) - an Integer for the Socket
connection timeout in milliseconds. Default is 60000</li>
* <li><b>bounceProcessor</b> (optional) - a String containing the name of the
mailet processor to pass messages that cannot
* be delivered to for DSN bounce processing. Default is to send a traditional
message containing the bounce details.</li>
+ * <li><b>onSuccess</b> (optional) - if specified, this processor is called
for each email successfully sent to remote third parties.</li>
+ *
+ * When using bounceProcessor or onSuccess processors, take special care of
error handling (see onMailetException and onMatcherException)
+ * to avoid confusing situations. Also remember that on partial delivery, both
processors will be used: <code>onSuccess</code> with successfull recipients,
+ * and <code>bounceProcessor</code> with failed recipients.
+ *
* <li><b>startTLS</b> (optional) - a Boolean (true/false) indicating whether
the STARTTLS command (if supported by the server)
* to switch the connection to a TLS-protected connection before issuing any
login commands. Default is false.</li>
* <li><b>sslEnable</b> (optional) - a Boolean (true/false) indicating whether
to use SSL to connect and use the SSL port unless
diff --git
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/DeliveryRunnable.java
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/DeliveryRunnable.java
index 23c8802..e42f0be 100644
---
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/DeliveryRunnable.java
+++
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/DeliveryRunnable.java
@@ -39,6 +39,7 @@ import org.apache.mailet.MailetContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.github.fge.lambdas.Throwing;
import com.google.common.annotations.VisibleForTesting;
import reactor.core.Disposable;
@@ -62,19 +63,20 @@ public class DeliveryRunnable implements Disposable {
private final Bouncer bouncer;
private final MailDelivrer mailDelivrer;
private final Supplier<Date> dateSupplier;
+ private final MailetContext mailetContext;
private Disposable disposable;
private Scheduler remoteDeliveryScheduler;
public DeliveryRunnable(MailQueue queue, RemoteDeliveryConfiguration
configuration, DNSService dnsServer, MetricFactory metricFactory,
MailetContext mailetContext, Bouncer bouncer) {
this(queue, configuration, metricFactory, bouncer,
- new MailDelivrer(configuration, new
MailDelivrerToHost(configuration, mailetContext), dnsServer, bouncer),
- CURRENT_DATE_SUPPLIER);
+ new MailDelivrer(configuration, new
MailDelivrerToHost(configuration, mailetContext), dnsServer, bouncer,
mailetContext),
+ CURRENT_DATE_SUPPLIER, mailetContext);
}
@VisibleForTesting
DeliveryRunnable(MailQueue queue, RemoteDeliveryConfiguration
configuration, MetricFactory metricFactory, Bouncer bouncer,
- MailDelivrer mailDelivrer, Supplier<Date> dateSupplier) {
+ MailDelivrer mailDelivrer, Supplier<Date> dateSupplier,
MailetContext mailetContext) {
this.queue = queue;
this.configuration = configuration;
this.outgoingMailsMetric = metricFactory.generate(OUTGOING_MAILS);
@@ -82,6 +84,7 @@ public class DeliveryRunnable implements Disposable {
this.mailDelivrer = mailDelivrer;
this.dateSupplier = dateSupplier;
this.metricFactory = metricFactory;
+ this.mailetContext = mailetContext;
}
public void start() {
@@ -136,6 +139,8 @@ public class DeliveryRunnable implements Disposable {
switch (executionResult.getExecutionState()) {
case SUCCESS:
outgoingMailsMetric.increment();
+ configuration.getOnSuccess()
+ .ifPresent(Throwing.consumer(onSuccess ->
mailetContext.sendMail(mail, onSuccess)));
break;
case TEMPORARY_FAILURE:
handleTemporaryFailure(mail, executionResult);
diff --git
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/MailDelivrer.java
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/MailDelivrer.java
index b7153a4..04dfa2f 100644
---
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/MailDelivrer.java
+++
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/MailDelivrer.java
@@ -21,7 +21,6 @@ package org.apache.james.transport.mailets.remote.delivery;
import java.io.IOException;
import java.util.Arrays;
-import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -37,11 +36,14 @@ import org.apache.james.core.Domain;
import org.apache.james.core.MailAddress;
import org.apache.james.dnsservice.api.DNSService;
import org.apache.james.dnsservice.api.TemporaryResolutionException;
+import org.apache.james.lifecycle.api.LifecycleUtil;
import org.apache.mailet.HostAddress;
import org.apache.mailet.Mail;
+import org.apache.mailet.MailetContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.github.fge.lambdas.Throwing;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
@@ -56,18 +58,20 @@ public class MailDelivrer {
private final DnsHelper dnsHelper;
private final MessageComposer messageComposer;
private final Bouncer bouncer;
+ private final MailetContext mailetContext;
- public MailDelivrer(RemoteDeliveryConfiguration configuration,
MailDelivrerToHost mailDelivrerToHost, DNSService dnsServer, Bouncer bouncer) {
- this(configuration, mailDelivrerToHost, new DnsHelper(dnsServer,
configuration), bouncer);
+ public MailDelivrer(RemoteDeliveryConfiguration configuration,
MailDelivrerToHost mailDelivrerToHost, DNSService dnsServer, Bouncer bouncer,
MailetContext mailetContext) {
+ this(configuration, mailDelivrerToHost, new DnsHelper(dnsServer,
configuration), bouncer, mailetContext);
}
@VisibleForTesting
- MailDelivrer(RemoteDeliveryConfiguration configuration, MailDelivrerToHost
mailDelivrerToHost, DnsHelper dnsHelper, Bouncer bouncer) {
+ MailDelivrer(RemoteDeliveryConfiguration configuration, MailDelivrerToHost
mailDelivrerToHost, DnsHelper dnsHelper, Bouncer bouncer, MailetContext
mailetContext) {
this.configuration = configuration;
this.mailDelivrerToHost = mailDelivrerToHost;
this.dnsHelper = dnsHelper;
this.messageComposer = new MessageComposer(configuration);
this.bouncer = bouncer;
+ this.mailetContext = mailetContext;
}
/**
@@ -135,7 +139,22 @@ public class MailDelivrer {
} catch (SendFailedException sfe) {
lastError = handleSendFailExceptionOnMxIteration(mail, sfe);
- targetAddresses.removeAll(listDeliveredAddresses(sfe));
+ ImmutableList<InternetAddress> deliveredAddresses =
listDeliveredAddresses(sfe);
+
+ configuration.getOnSuccess()
+ .ifPresent(Throwing.consumer(onSuccess -> {
+ Mail copy = mail.duplicate();
+ try {
+ copy.setRecipients(deliveredAddresses.stream()
+ .map(Throwing.function(MailAddress::new))
+ .collect(ImmutableList.toImmutableList()));
+ mailetContext.sendMail(copy, onSuccess);
+ } finally {
+ LifecycleUtil.dispose(copy);
+ }
+ }));
+
+ targetAddresses.removeAll(deliveredAddresses);
} catch (MessagingException me) {
lastError = handleMessagingException(mail, me);
if (configuration.isDebug()) {
@@ -157,7 +176,7 @@ public class MailDelivrer {
return ExecutionResult.temporaryFailure();
}
- private Collection<InternetAddress>
listDeliveredAddresses(SendFailedException sfe) {
+ private ImmutableList<InternetAddress>
listDeliveredAddresses(SendFailedException sfe) {
return Optional.ofNullable(sfe.getValidSentAddresses())
.map(addresses ->
Arrays.stream(addresses)
diff --git
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/RemoteDeliveryConfiguration.java
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/RemoteDeliveryConfiguration.java
index fa5908c..036106e 100644
---
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/RemoteDeliveryConfiguration.java
+++
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/RemoteDeliveryConfiguration.java
@@ -62,6 +62,7 @@ public class RemoteDeliveryConfiguration {
public static final String MAX_RETRIES = "maxRetries";
public static final String DELAY_TIME = "delayTime";
public static final String DEBUG = "debug";
+ public static final String ON_SUCCESS = "onSuccess";
public static final int DEFAULT_SMTP_TIMEOUT = 180000;
public static final MailQueueName DEFAULT_OUTGOING_QUEUE_NAME =
MailQueueName.of("outgoing");
public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
@@ -88,6 +89,7 @@ public class RemoteDeliveryConfiguration {
private final String authUser;
private final String authPass;
private final Properties javaxAdditionalProperties;
+ private final Optional<String> onSuccess;
public RemoteDeliveryConfiguration(MailetConfig mailetConfig, DomainList
domainList) {
isDebug = MailetUtil.getInitParameter(mailetConfig,
DEBUG).orElse(false);
@@ -121,6 +123,7 @@ public class RemoteDeliveryConfiguration {
}
isBindUsed = bindAddress != null;
javaxAdditionalProperties = computeJavaxProperties(mailetConfig);
+ onSuccess =
Optional.ofNullable(mailetConfig.getInitParameter(ON_SUCCESS));
}
private Properties computeJavaxProperties(MailetConfig mailetConfig) {
@@ -322,4 +325,8 @@ public class RemoteDeliveryConfiguration {
public String getBindAddress() {
return bindAddress;
}
+
+ public Optional<String> getOnSuccess() {
+ return onSuccess;
+ }
}
diff --git
a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remote/delivery/DeliveryRunnableTest.java
b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remote/delivery/DeliveryRunnableTest.java
index 0990cd0..2419555 100644
---
a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remote/delivery/DeliveryRunnableTest.java
+++
b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remote/delivery/DeliveryRunnableTest.java
@@ -40,6 +40,7 @@ import org.apache.james.queue.api.MailQueue;
import org.apache.mailet.Attribute;
import org.apache.mailet.AttributeValue;
import org.apache.mailet.Mail;
+import org.apache.mailet.MailetContext;
import org.apache.mailet.base.test.FakeMail;
import org.apache.mailet.base.test.FakeMailetConfig;
import org.junit.jupiter.api.BeforeEach;
@@ -68,7 +69,7 @@ public class DeliveryRunnableTest {
bouncer = mock(Bouncer.class);
mailDelivrer = mock(MailDelivrer.class);
mailQueue = mock(MailQueue.class);
- testee = new DeliveryRunnable(mailQueue, configuration, metricFactory,
bouncer, mailDelivrer, FIXED_DATE_SUPPLIER);
+ testee = new DeliveryRunnable(mailQueue, configuration, metricFactory,
bouncer, mailDelivrer, FIXED_DATE_SUPPLIER, mock(MailetContext.class));
}
@Test
diff --git
a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remote/delivery/MailDelivrerTest.java
b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remote/delivery/MailDelivrerTest.java
index 61cd095..7d711d7 100644
---
a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remote/delivery/MailDelivrerTest.java
+++
b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remote/delivery/MailDelivrerTest.java
@@ -40,6 +40,7 @@ import
org.apache.james.dnsservice.api.TemporaryResolutionException;
import org.apache.james.domainlist.api.DomainList;
import org.apache.mailet.HostAddress;
import org.apache.mailet.Mail;
+import org.apache.mailet.MailetContext;
import org.apache.mailet.base.MailAddressFixture;
import org.apache.mailet.base.test.FakeMail;
import org.apache.mailet.base.test.FakeMailetConfig;
@@ -74,7 +75,7 @@ class MailDelivrerTest {
.setProperty(RemoteDeliveryConfiguration.DEBUG, "true")
.build(),
mock(DomainList.class));
- testee = new MailDelivrer(configuration, mailDelivrerToHost,
dnsHelper, bouncer);
+ testee = new MailDelivrer(configuration, mailDelivrerToHost,
dnsHelper, bouncer, mock(MailetContext.class));
}
@Test
diff --git
a/server/mailet/remote-delivery-integration-testing/src/test/java/org/apache/james/mailets/RemoteDeliveryOnSuccessTest.java
b/server/mailet/remote-delivery-integration-testing/src/test/java/org/apache/james/mailets/RemoteDeliveryOnSuccessTest.java
new file mode 100644
index 0000000..42c6c65
--- /dev/null
+++
b/server/mailet/remote-delivery-integration-testing/src/test/java/org/apache/james/mailets/RemoteDeliveryOnSuccessTest.java
@@ -0,0 +1,235 @@
+/****************************************************************
+ * 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.mailets;
+
+import static org.apache.james.MemoryJamesServerMain.SMTP_AND_IMAP_MODULE;
+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.awaitAtMostOneMinute;
+import static
org.apache.james.mock.smtp.server.ConfigurationClient.BehaviorsParamsBuilder.ConditionStep.anyInput;
+import static
org.apache.james.mock.smtp.server.ConfigurationClient.BehaviorsParamsBuilder.ConditionStep.inputContaining;
+import static
org.apache.james.mock.smtp.server.ConfigurationClient.BehaviorsParamsBuilder.ResponseStep.serviceNotAvailable;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.File;
+
+import javax.mail.internet.AddressException;
+
+import org.apache.james.core.MailAddress;
+import org.apache.james.dnsservice.api.DNSService;
+import org.apache.james.dnsservice.api.InMemoryDNSService;
+import org.apache.james.mailets.configuration.CommonProcessors;
+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.mailrepository.api.MailRepositoryUrl;
+import org.apache.james.mock.smtp.server.ConfigurationClient;
+import org.apache.james.mock.smtp.server.model.SMTPCommand;
+import org.apache.james.mock.smtp.server.testing.MockSmtpServerExtension;
+import org.apache.james.modules.protocols.SmtpGuiceProbe;
+import org.apache.james.transport.mailets.RemoteDelivery;
+import org.apache.james.transport.mailets.ToRepository;
+import org.apache.james.transport.matchers.All;
+import org.apache.james.utils.DataProbeImpl;
+import org.apache.james.utils.MailRepositoryProbeImpl;
+import org.apache.james.utils.SMTPMessageSender;
+import org.apache.mailet.Mail;
+import org.assertj.core.api.SoftAssertions;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.RepeatedTest;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.api.io.TempDir;
+
+import com.github.fge.lambdas.Throwing;
+import com.google.common.collect.ImmutableList;
+
+class RemoteDeliveryOnSuccessTest {
+ public static final MailRepositoryUrl SUCCESS_REPOSITORY =
MailRepositoryUrl.from("memory://var/mail/success/");
+
+ private static final String ANOTHER_DOMAIN = "other.com";
+ private static final String FROM = "from@" + DEFAULT_DOMAIN;
+ private static final String RECIPIENT = "touser@" + ANOTHER_DOMAIN;
+ private static final String RECIPIENT1 = "touser1@" + ANOTHER_DOMAIN;
+ private static final String RECIPIENT2 = "touser2@" + ANOTHER_DOMAIN;
+
+
+ private static MailAddress RECIPIENT1_ADDRESS;
+ private static MailAddress RECIPIENT2_ADDRESS;
+
+ private InMemoryDNSService inMemoryDNSService;
+ private ConfigurationClient mockSMTP1Configuration;
+
+ @RegisterExtension
+ public SMTPMessageSender messageSender = new
SMTPMessageSender(DEFAULT_DOMAIN);
+ @RegisterExtension
+ public static MockSmtpServerExtension mockSmtp1 = new
MockSmtpServerExtension();
+
+ private TemporaryJamesServer jamesServer;
+
+ @BeforeAll
+ static void setUpClass() throws AddressException {
+ RECIPIENT1_ADDRESS = new MailAddress(RECIPIENT1);
+ RECIPIENT2_ADDRESS = new MailAddress(RECIPIENT2);
+ }
+
+ @BeforeEach
+ void setUp(@TempDir File temporaryFolder) throws Exception {
+ inMemoryDNSService = new InMemoryDNSService()
+ .registerMxRecord(DEFAULT_DOMAIN, LOCALHOST_IP)
+ .registerMxRecord(ANOTHER_DOMAIN,
mockSmtp1.getMockSmtp().getIPAddress());
+
+ jamesServer = TemporaryJamesServer.builder()
+ .withBase(SMTP_AND_IMAP_MODULE)
+ .withOverrides(binder ->
binder.bind(DNSService.class).toInstance(inMemoryDNSService))
+ .withMailetContainer(MailetContainer.builder()
+ .putProcessor(CommonProcessors.simpleRoot())
+ .putProcessor(CommonProcessors.error())
+ .putProcessor(ProcessorConfiguration.builder()
+ .enableJmx(false)
+ .state("success")
+ .addMailet(MailetConfiguration.builder()
+ .matcher(All.class)
+ .mailet(ToRepository.class)
+ .addProperty("repositoryPath",
SUCCESS_REPOSITORY.asString()))
+ .build())
+ .putProcessor(directResolutionTransport())
+ .putProcessor(CommonProcessors.bounces()))
+ .build(temporaryFolder);
+ jamesServer.start();
+
+ jamesServer.getProbe(DataProbeImpl.class)
+ .fluent()
+ .addDomain(DEFAULT_DOMAIN)
+ .addUser(FROM, PASSWORD);
+
+ mockSMTP1Configuration =
mockSmtp1.getMockSmtp().getConfigurationClient();
+
+ assertThat(mockSMTP1Configuration.version()).isEqualTo("0.4");
+ }
+
+ @AfterEach
+ void tearDown() {
+ mockSMTP1Configuration.clearBehaviors();
+ jamesServer.shutdown();
+ }
+
+ @Test
+ void deliveredEmailShouldTransitViaSuccessProcessor() throws Exception {
+ messageSender.connect(LOCALHOST_IP,
jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpPort())
+ .sendMessage(FROM, RECIPIENT);
+
+ awaitAtMostOneMinute.untilAsserted(() ->
+ assertThat(jamesServer.getProbe(MailRepositoryProbeImpl.class)
+ .listMailKeys(SUCCESS_REPOSITORY))
+ .hasSize(1));
+ }
+
+ @Test
+ void deliveredEmailShouldTransitViaSuccessProcessorAfterRetry() throws
Exception {
+ mockSMTP1Configuration
+ .addNewBehavior()
+ .expect(SMTPCommand.RCPT_TO)
+ .matching(anyInput())
+ .thenRespond(serviceNotAvailable("mock response"))
+ .onlySomeTimes(1)
+ .post();
+
+ messageSender.connect(LOCALHOST_IP,
jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpPort())
+ .sendMessage(FROM, RECIPIENT);
+
+ awaitAtMostOneMinute.untilAsserted(() ->
+ assertThat(jamesServer.getProbe(MailRepositoryProbeImpl.class)
+ .listMailKeys(SUCCESS_REPOSITORY))
+ .hasSize(1));
+ }
+
+ @Test
+ void partiallyDeliveredEmailsShouldTransitViaSuccessProcessor() throws
Exception {
+ mockSMTP1Configuration
+ .addNewBehavior()
+ .expect(SMTPCommand.RCPT_TO)
+ .matching(inputContaining(RECIPIENT1))
+ .thenRespond(serviceNotAvailable("mock response"))
+ .anyTimes()
+ .post();
+
+ messageSender.connect(LOCALHOST_IP,
jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpPort())
+ .sendMessage(FROM, ImmutableList.of(RECIPIENT1, RECIPIENT2));
+
+ MailRepositoryProbeImpl mailRepositoryProbe =
jamesServer.getProbe(MailRepositoryProbeImpl.class);
+ awaitAtMostOneMinute.untilAsserted(() -> assertThat(mailRepositoryProbe
+ .listMailKeys(SUCCESS_REPOSITORY))
+ .hasSize(1));
+ assertThat(mailRepositoryProbe.getMail(SUCCESS_REPOSITORY,
mailRepositoryProbe.listMailKeys(SUCCESS_REPOSITORY).get(0))
+ .getRecipients())
+ .containsOnly(RECIPIENT2_ADDRESS);
+ }
+
+ @Test
+ void partiallyDeliveredEmailsShouldTransitViaSuccessProcessorAfterRetry()
throws Exception {
+ mockSMTP1Configuration
+ .addNewBehavior()
+ .expect(SMTPCommand.RCPT_TO)
+ .matching(inputContaining(RECIPIENT1))
+ .thenRespond(serviceNotAvailable("mock response"))
+ .onlySomeTimes(1)
+ .post();
+
+ messageSender.connect(LOCALHOST_IP,
jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpPort())
+ .sendMessage(FROM, ImmutableList.of(RECIPIENT1, RECIPIENT2));
+
+ MailRepositoryProbeImpl mailRepositoryProbe =
jamesServer.getProbe(MailRepositoryProbeImpl.class);
+ awaitAtMostOneMinute.untilAsserted(() -> assertThat(mailRepositoryProbe
+ .listMailKeys(SUCCESS_REPOSITORY))
+ .hasSize(2));
+ Mail mail1 = mailRepositoryProbe.getMail(SUCCESS_REPOSITORY,
mailRepositoryProbe.listMailKeys(SUCCESS_REPOSITORY).get(0));
+ Mail mail2 = mailRepositoryProbe.getMail(SUCCESS_REPOSITORY,
mailRepositoryProbe.listMailKeys(SUCCESS_REPOSITORY).get(1));
+
+ SoftAssertions.assertSoftly(Throwing.consumer(softly -> {
+ assertThat(mail1.getRecipients()).hasSize(1);
+ assertThat(mail2.getRecipients()).hasSize(1);
+ assertThat(ImmutableList.builder()
+ .addAll(mail1.getRecipients())
+ .addAll(mail2.getRecipients())
+ .build())
+ .containsOnly(RECIPIENT1_ADDRESS, RECIPIENT2_ADDRESS);
+ }));
+ }
+
+ private ProcessorConfiguration.Builder directResolutionTransport() {
+ return ProcessorConfiguration.transport()
+ .addMailet(MailetConfiguration.BCC_STRIPPER)
+ .addMailet(MailetConfiguration.LOCAL_DELIVERY)
+ .addMailet(MailetConfiguration.builder()
+ .mailet(RemoteDelivery.class)
+ .matcher(All.class)
+ .addProperty("outgoingQueue", "outgoing")
+ .addProperty("delayTime", "3 * 10 ms")
+ .addProperty("maxRetries", "3")
+ .addProperty("maxDnsProblemRetries", "0")
+ .addProperty("deliveryThreads", "2")
+ .addProperty("sendpartial", "true")
+ .addProperty("onSuccess", "success"));
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]