This is an automated email from the ASF dual-hosted git repository.
kao pushed a commit to branch 3.7.x
in repository https://gitbox.apache.org/repos/asf/james-project.git
The following commit(s) were added to refs/heads/3.7.x by this push:
new 5e0a60e6f0 JAMES-3791 Remote Delivery uses a pool of SMTP sessions.
5e0a60e6f0 is described below
commit 5e0a60e6f09a506a9806cf511effd2e2bdb53fb6
Author: Karsten Otto <[email protected]>
AuthorDate: Wed Jul 13 14:23:43 2022 +0200
JAMES-3791 Remote Delivery uses a pool of SMTP sessions.
This prevents a race condition in setting per-delivery properties.
(cherry picked from commit ad05e797507bbab2bbb3709b402c3627262874c3)
---
server/mailet/mailets/pom.xml | 4 ++
.../remote/delivery/MailDelivrerToHost.java | 67 ++++++++++++++++++----
2 files changed, 60 insertions(+), 11 deletions(-)
diff --git a/server/mailet/mailets/pom.xml b/server/mailet/mailets/pom.xml
index 56f19becde..493d2711fc 100644
--- a/server/mailet/mailets/pom.xml
+++ b/server/mailet/mailets/pom.xml
@@ -215,6 +215,10 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-pool2</artifactId>
+ </dependency>
<dependency>
<groupId>org.apache.james</groupId>
<artifactId>apache-mime4j-dom</artifactId>
diff --git
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/MailDelivrerToHost.java
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/MailDelivrerToHost.java
index 64686f1eee..184a8aeb3a 100644
---
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/MailDelivrerToHost.java
+++
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/MailDelivrerToHost.java
@@ -39,6 +39,12 @@ import javax.mail.internet.MimeMessage;
import org.apache.commons.lang3.NotImplementedException;
import org.apache.commons.lang3.tuple.Pair;
+import org.apache.commons.pool2.BasePooledObjectFactory;
+import org.apache.commons.pool2.ObjectPool;
+import org.apache.commons.pool2.PooledObject;
+import org.apache.commons.pool2.impl.DefaultPooledObject;
+import org.apache.commons.pool2.impl.GenericObjectPool;
+import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.james.core.MailAddress;
import org.apache.mailet.DsnParameters;
import org.apache.mailet.HostAddress;
@@ -60,21 +66,43 @@ public class MailDelivrerToHost {
private final RemoteDeliveryConfiguration configuration;
private final Converter7Bit converter7Bit;
- private final Session smtpSession;
- private final Session smtpsSession;
+ private final ObjectPool<Session> smtpSessionPool;
+ private final ObjectPool<Session> smtpsSessionPool;
public MailDelivrerToHost(RemoteDeliveryConfiguration
remoteDeliveryConfiguration, MailetContext mailetContext) {
this.configuration = remoteDeliveryConfiguration;
this.converter7Bit = new Converter7Bit(mailetContext);
if (configuration.isSSLEnable()) {
- this.smtpSession =
Session.getInstance(configuration.createFinalJavaxProperties());
- this.smtpsSession =
Session.getInstance(configuration.createFinalJavaxPropertiesWithSSL());
+ this.smtpSessionPool =
createSessionPool(configuration.createFinalJavaxProperties());
+ this.smtpsSessionPool =
createSessionPool(configuration.createFinalJavaxPropertiesWithSSL());
} else {
- this.smtpSession =
Session.getInstance(configuration.createFinalJavaxProperties());
- this.smtpsSession = this.smtpSession;
+ this.smtpSessionPool =
createSessionPool(configuration.createFinalJavaxProperties());
+ this.smtpsSessionPool = smtpSessionPool;
}
}
+ private ObjectPool<Session> createSessionPool(Properties
defaultConfiguration) {
+ GenericObjectPoolConfig<Session> poolConfig = new
GenericObjectPoolConfig<>();
+ poolConfig.setMaxTotal(-1); // unbounded pool, scales to match peak
delivery thread concurrency
+ return new GenericObjectPool<>(new BasePooledObjectFactory<>() {
+ @Override
+ public Session create() {
+ // Since we modify session properties per delivery, each
session must have its own properties
+ return Session.getInstance(new
Properties(defaultConfiguration));
+ }
+
+ @Override
+ public PooledObject<Session> wrap(Session session) {
+ return new DefaultPooledObject<>(session);
+ }
+
+ @Override
+ public void passivateObject(PooledObject<Session> p) {
+ p.getObject().getProperties().clear(); // reset to default
configuration
+ }
+ }, poolConfig);
+ }
+
public ExecutionResult tryDeliveryToHost(Mail mail,
Collection<InternetAddress> addr, HostAddress outgoingMailServer) throws
MessagingException {
Session session = selectSession(outgoingMailServer);
Properties props = getPropertiesForMail(mail, session);
@@ -101,15 +129,32 @@ public class MailDelivrerToHost {
outgoingMailServer.getHost(), props.get(inContext(session,
"mail.smtp.from")), mail.getRecipients());
} finally {
closeTransport(mail, outgoingMailServer, transport);
+ releaseSession(outgoingMailServer, session);
}
return ExecutionResult.success();
}
- private Session selectSession(HostAddress host) {
- if (host.getProtocol().equalsIgnoreCase("smtps")) {
- return smtpsSession;
- } else {
- return smtpSession;
+ private Session selectSession(HostAddress host) throws MessagingException {
+ try {
+ if (host.getProtocol().equalsIgnoreCase("smtps")) {
+ return smtpsSessionPool.borrowObject();
+ } else {
+ return smtpSessionPool.borrowObject();
+ }
+ } catch (Exception e) {
+ throw new MessagingException("could not create SMTP session for
mail delivery", e);
+ }
+ }
+
+ private void releaseSession(HostAddress host, Session session) {
+ try {
+ if (host.getProtocol().equalsIgnoreCase("smtps")) {
+ smtpsSessionPool.returnObject(session);
+ } else {
+ smtpSessionPool.returnObject(session);
+ }
+ } catch (Exception e) {
+ LOGGER.warn("Warning: failed to release SMTP session after mail
delivery", e);
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]