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 2020/03/20 12:15:45 UTC
[james-project] 02/08: JAMES-3119 Strong type ProtocolSession
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
commit 58b1d879abfd679758c95725375ab3f7f5598af7
Author: Gautier DI FOLCO <gd...@linagora.com>
AuthorDate: Wed Mar 18 13:08:57 2020 +0100
JAMES-3119 Strong type ProtocolSession
---
.../james/protocols/api/ProtocolSession.java | 83 +++++++++++++++++++---
.../james/protocols/api/ProtocolSessionImpl.java | 45 +++++++-----
.../james/protocols/api/ProtocolSessionTest.java | 22 +++---
.../lmtp/core/DataLineMessageHookHandler.java | 4 +-
.../apache/james/protocols/pop3/POP3Session.java | 11 ++-
.../pop3/core/AbstractApopCmdHandler.java | 7 +-
.../james/protocols/pop3/core/DeleCmdHandler.java | 8 ++-
.../james/protocols/pop3/core/ListCmdHandler.java | 11 +--
.../protocols/pop3/core/MessageMetaDataUtils.java | 12 ++--
.../james/protocols/pop3/core/QuitCmdHandler.java | 4 +-
.../james/protocols/pop3/core/RetrCmdHandler.java | 5 +-
.../james/protocols/pop3/core/RsetCmdHandler.java | 2 +-
.../james/protocols/pop3/core/StatCmdHandler.java | 10 +--
.../james/protocols/pop3/core/TopCmdHandler.java | 4 +-
.../james/protocols/pop3/core/UidlCmdHandler.java | 8 +--
.../apache/james/protocols/smtp/SMTPSession.java | 13 ++--
.../james/protocols/smtp/SMTPSessionImpl.java | 22 ++----
.../smtp/core/AbstractAddHeadersFilter.java | 9 +--
...ractSenderAuthIdentifyVerificationRcptHook.java | 2 +-
.../james/protocols/smtp/core/DataCmdHandler.java | 14 ++--
.../smtp/core/DataLineMessageHookHandler.java | 20 ++++--
.../james/protocols/smtp/core/MailCmdHandler.java | 20 +++---
.../james/protocols/smtp/core/RcptCmdHandler.java | 31 ++++----
.../smtp/core/ReceivedDataLineFilter.java | 18 +++--
.../smtp/core/SeparatingDataLineFilter.java | 5 +-
.../protocols/smtp/core/UnknownCmdHandler.java | 7 +-
.../smtp/core/esmtp/MailSizeEsmtpExtension.java | 29 ++++----
.../smtp/core/fastfail/DNSRBLHandler.java | 21 +++---
.../smtp/core/fastfail/MaxUnknownCmdHandler.java | 13 ++--
.../core/fastfail/ResolvableEhloHeloHandler.java | 12 ++--
.../core/fastfail/SupressDuplicateRcptHandler.java | 38 +++++-----
.../smtp/core/fastfail/DNSRBLHandlerTest.java | 73 ++++++++++---------
.../smtp/core/fastfail/MaxRcptHandlerTest.java | 4 +-
.../core/fastfail/MaxUnknownCmdHandlerTest.java | 32 ++++++---
.../fastfail/ResolvableEhloHeloHandlerTest.java | 60 +++++++++-------
.../fastfail/ValidSenderDomainHandlerTest.java | 35 +++++----
.../protocols/smtp/utils/BaseFakeSMTPSession.java | 14 ++--
.../DataLineJamesMessageHookHandler.java | 11 +--
.../org/apache/james/smtpserver/SMTPConstants.java | 8 ++-
.../james/smtpserver/fastfail/SPFHandler.java | 29 ++++----
.../james/smtpserver/fastfail/URIRBLHandler.java | 18 ++---
.../netty/SMTPChannelUpstreamHandler.java | 4 +-
.../apache/james/smtpserver/SPFHandlerTest.java | 41 +++++++----
.../james/smtpserver/SpamAssassinHandlerTest.java | 41 +++++++----
.../apache/james/smtpserver/URIRBLHandlerTest.java | 41 +++++++----
.../james/smtpserver/ValidRcptHandlerTest.java | 39 ++++++----
.../apache/james/smtpserver/ValidRcptMXTest.java | 38 ++++++----
upgrade-instructions.md | 18 +++++
48 files changed, 614 insertions(+), 402 deletions(-)
diff --git a/protocols/api/src/main/java/org/apache/james/protocols/api/ProtocolSession.java b/protocols/api/src/main/java/org/apache/james/protocols/api/ProtocolSession.java
index 0937b4b..b483985 100644
--- a/protocols/api/src/main/java/org/apache/james/protocols/api/ProtocolSession.java
+++ b/protocols/api/src/main/java/org/apache/james/protocols/api/ProtocolSession.java
@@ -22,10 +22,16 @@ package org.apache.james.protocols.api;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
import org.apache.james.core.Username;
import org.apache.james.protocols.api.handler.LineHandler;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+
/**
* Session for a protocol. Every new connection generates a new session
*/
@@ -36,16 +42,75 @@ public interface ProtocolSession {
Transaction
}
+ class AttachmentKey<T> {
+ public static <U> AttachmentKey<U> of(String value, Class<U> type) {
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(value), "An attachment key should not be empty or null");
+
+ return new AttachmentKey<>(value, type);
+ }
+
+ private final String value;
+ private final Class<T> type;
+
+ private AttachmentKey(String value, Class<T> type) {
+ this.value = value;
+ this.type = type;
+ }
+
+ public String asString() {
+ return value;
+ }
+
+ public Optional<T> convert(Object object) {
+ return Optional.ofNullable(object)
+ .filter(type::isInstance)
+ .map(type::cast);
+ }
+
+ @Override
+ public final boolean equals(Object o) {
+ if (o instanceof AttachmentKey) {
+ AttachmentKey<?> that = (AttachmentKey<?>) o;
+
+ return Objects.equals(this.value, that.value)
+ && Objects.equals(this.type, that.type);
+ }
+ return false;
+ }
+
+ @Override
+ public final int hashCode() {
+ return Objects.hash(value, type);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("value", value)
+ .add("type", type.getName())
+ .toString();
+ }
+ }
+
/**
- * Store the given value with the given key in the specified {@link State}. If you want to remove a value you need to use <code>null</code> as value
+ * Store the given value with the given key in the specified {@link State}.
*
* @param key the key under which the value should get stored
- * @param value the value which will get stored under the given key or <code>null</code> if you want to remove any value which is stored under the key
+ * @param value the value which will get stored under the given key
* @param state the {@link State} to which the mapping belongs
* @return oldValue the value which was stored before for this key or <code>null</code> if non was stored before.
*/
- Object setAttachment(String key, Object value, State state);
-
+ <T> Optional<T> setAttachment(AttachmentKey<T> key, T value, State state);
+
+ /**
+ * Remove a value stored for the given key in the specified {@link State}.
+ *
+ * @param key the key under which the value should get stored
+ * @param state the {@link State} to which the mapping belongs
+ * @return oldValue the value which was stored before for this key or <code>null</code> if non was stored before.
+ */
+ <T> Optional<T> removeAttachment(AttachmentKey<T> key,State state);
+
/**
* Return the value which is stored for the given key in the specified {@link State} or <code>null</code> if non was stored before.
*
@@ -53,27 +118,27 @@ public interface ProtocolSession {
* @param state the {@link State} in which the value was stored for the key
* @return value the stored value for the key
*/
- Object getAttachment(String key, State state);
+ <T> Optional<T> getAttachment(AttachmentKey<T> key, State state);
/**
* Return Map which can be used to store objects within a session
*
* @return state
- * @deprecated use {@link #setAttachment(String, Object, State)}
+ * @deprecated use {@link #setAttachment(AttachmentKey, Object, State)}
*/
@Deprecated
- Map<String, Object> getState();
+ Map<AttachmentKey<?>, Object> getState();
/**
* Returns Map that consists of the state of the {@link ProtocolSession} per connection
*
* @return map of the current {@link ProtocolSession} state per connection
- * @deprecated use {@link #getAttachment(String, State)}
+ * @deprecated use {@link #getAttachment(AttachmentKey, State)}
*/
@Deprecated
- Map<String,Object> getConnectionState();
+ Map<AttachmentKey<?>, Object> getConnectionState();
/**
diff --git a/protocols/api/src/main/java/org/apache/james/protocols/api/ProtocolSessionImpl.java b/protocols/api/src/main/java/org/apache/james/protocols/api/ProtocolSessionImpl.java
index 266aeba..ec27d9e 100644
--- a/protocols/api/src/main/java/org/apache/james/protocols/api/ProtocolSessionImpl.java
+++ b/protocols/api/src/main/java/org/apache/james/protocols/api/ProtocolSessionImpl.java
@@ -23,10 +23,13 @@ import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
+import java.util.Optional;
import org.apache.james.core.Username;
import org.apache.james.protocols.api.handler.LineHandler;
+import com.google.common.base.Preconditions;
+
/**
* Basic implementation of {@link ProtocolSession}
*
@@ -34,8 +37,8 @@ import org.apache.james.protocols.api.handler.LineHandler;
*/
public class ProtocolSessionImpl implements ProtocolSession {
private final ProtocolTransport transport;
- private final Map<String, Object> connectionState;
- private final Map<String, Object> sessionState;
+ private final Map<AttachmentKey<?>, Object> connectionState;
+ private final Map<AttachmentKey<?>, Object> sessionState;
private Username username;
protected final ProtocolConfiguration config;
private static final Charset CHARSET = Charset.forName("US-ASCII");
@@ -92,12 +95,12 @@ public class ProtocolSessionImpl implements ProtocolSession {
@Override
- public Map<String, Object> getConnectionState() {
+ public Map<AttachmentKey<?>, Object> getConnectionState() {
return connectionState;
}
@Override
- public Map<String, Object> getState() {
+ public Map<AttachmentKey<?>, Object> getState() {
return sessionState;
}
@@ -134,28 +137,34 @@ public class ProtocolSessionImpl implements ProtocolSession {
}
@Override
- public Object setAttachment(String key, Object value, State state) {
+ public <T> Optional<T> setAttachment(AttachmentKey<T> key, T value, State state) {
+ Preconditions.checkNotNull(key, "key cannot be null");
+ Preconditions.checkNotNull(value, "value cannot be null");
+
+ if (state == State.Connection) {
+ return key.convert(connectionState.put(key, value));
+ } else {
+ return key.convert(sessionState.put(key, value));
+ }
+ }
+
+ @Override
+ public <T> Optional<T> removeAttachment(AttachmentKey<T> key, State state) {
+ Preconditions.checkNotNull(key, "key cannot be null");
+
if (state == State.Connection) {
- if (value == null) {
- return connectionState.remove(key);
- } else {
- return connectionState.put(key, value);
- }
+ return key.convert(connectionState.remove(key));
} else {
- if (value == null) {
- return sessionState.remove(key);
- } else {
- return sessionState.put(key, value);
- }
+ return key.convert(sessionState.remove(key));
}
}
@Override
- public Object getAttachment(String key, State state) {
+ public <T> Optional<T> getAttachment(AttachmentKey<T> key, State state) {
if (state == State.Connection) {
- return connectionState.get(key);
+ return key.convert(connectionState.get(key));
} else {
- return sessionState.get(key);
+ return key.convert(sessionState.get(key));
}
}
diff --git a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/SMTPConstants.java b/protocols/api/src/test/java/org/apache/james/protocols/api/ProtocolSessionTest.java
similarity index 75%
copy from server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/SMTPConstants.java
copy to protocols/api/src/test/java/org/apache/james/protocols/api/ProtocolSessionTest.java
index b401721..584735f 100644
--- a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/SMTPConstants.java
+++ b/protocols/api/src/test/java/org/apache/james/protocols/api/ProtocolSessionTest.java
@@ -7,7 +7,7 @@
* "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 *
+ * 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 *
@@ -15,16 +15,18 @@
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
- ****************************************************************/
+ ***************************************************************/
-package org.apache.james.smtpserver;
+package org.apache.james.protocols.api;
-/**
- * Constants which are used within SMTP Session
- */
-public interface SMTPConstants {
+import org.junit.jupiter.api.Test;
- String DATA_MIMEMESSAGE_STREAMSOURCE = "org.apache.james.core.DataCmdHandler.DATA_MIMEMESSAGE_STREAMSOURCE";
- String MAIL = "MAIL";
+import nl.jqno.equalsverifier.EqualsVerifier;
-}
+class ProtocolSessionTest {
+
+ @Test
+ void attachmentKeyShouldRespectBeanContract() {
+ EqualsVerifier.forClass(ProtocolSession.AttachmentKey.class).verify();
+ }
+}
\ No newline at end of file
diff --git a/protocols/lmtp/src/main/java/org/apache/james/protocols/lmtp/core/DataLineMessageHookHandler.java b/protocols/lmtp/src/main/java/org/apache/james/protocols/lmtp/core/DataLineMessageHookHandler.java
index 1e971cf..cc69dab 100644
--- a/protocols/lmtp/src/main/java/org/apache/james/protocols/lmtp/core/DataLineMessageHookHandler.java
+++ b/protocols/lmtp/src/main/java/org/apache/james/protocols/lmtp/core/DataLineMessageHookHandler.java
@@ -27,7 +27,7 @@ import org.apache.james.protocols.api.Response;
import org.apache.james.protocols.api.handler.WiringException;
import org.apache.james.protocols.lmtp.LMTPMultiResponse;
import org.apache.james.protocols.lmtp.hook.DeliverToRecipientHook;
-import org.apache.james.protocols.smtp.MailEnvelopeImpl;
+import org.apache.james.protocols.smtp.MailEnvelope;
import org.apache.james.protocols.smtp.SMTPResponse;
import org.apache.james.protocols.smtp.SMTPRetCode;
import org.apache.james.protocols.smtp.SMTPSession;
@@ -43,7 +43,7 @@ public class DataLineMessageHookHandler extends org.apache.james.protocols.smtp.
@Override
- protected Response processExtensions(SMTPSession session, MailEnvelopeImpl mail) {
+ protected Response processExtensions(SMTPSession session, MailEnvelope mail) {
LMTPMultiResponse mResponse = null;
for (MailAddress recipient : mail.getRecipients()) {
diff --git a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/POP3Session.java b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/POP3Session.java
index 332cef4..1be4efd 100644
--- a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/POP3Session.java
+++ b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/POP3Session.java
@@ -19,8 +19,11 @@
package org.apache.james.protocols.pop3;
+import java.util.List;
+
import org.apache.james.protocols.api.ProtocolSession;
import org.apache.james.protocols.pop3.mailbox.Mailbox;
+import org.apache.james.protocols.pop3.mailbox.MessageMetaData;
/**
* All the handlers access this interface to communicate with POP3Handler object
@@ -28,9 +31,11 @@ import org.apache.james.protocols.pop3.mailbox.Mailbox;
public interface POP3Session extends ProtocolSession {
- String UID_LIST = "UID_LIST";
- String DELETED_UID_LIST = "DELETED_UID_LIST";
- String APOP_TIMESTAMP = "APOP_TIMESTAMP";
+ @SuppressWarnings("unchecked")
+ AttachmentKey<List<MessageMetaData>> UID_LIST = AttachmentKey.of("UID_LIST", (Class<List<MessageMetaData>>) (Object) List.class);
+ @SuppressWarnings("unchecked")
+ AttachmentKey<List<String>> DELETED_UID_LIST = AttachmentKey.of("DELETED_UID_LIST", (Class<List<String>>) (Object) List.class);
+ AttachmentKey<String> APOP_TIMESTAMP = AttachmentKey.of("APOP_TIMESTAMP", String.class);
// Authentication states for the POP3 interaction
/** Waiting for user id */
diff --git a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/AbstractApopCmdHandler.java b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/AbstractApopCmdHandler.java
index 656339a..521c1df 100644
--- a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/AbstractApopCmdHandler.java
+++ b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/AbstractApopCmdHandler.java
@@ -37,10 +37,11 @@ import com.google.common.collect.ImmutableSet;
public abstract class AbstractApopCmdHandler extends AbstractPassCmdHandler {
private static final Collection<String> COMMANDS = ImmutableSet.of("APOP");
-
+ private static final String MISSING_APOP_TIMESTAMP = "";
+
@Override
public Response onCommand(POP3Session session, Request request) {
- if (session.getAttachment(POP3Session.APOP_TIMESTAMP, State.Connection) == null) {
+ if (!session.getAttachment(POP3Session.APOP_TIMESTAMP, State.Connection).isPresent()) {
// APOP timestamp was not found in the session so APOP is not supported
return POP3Response.ERR;
}
@@ -81,7 +82,7 @@ public abstract class AbstractApopCmdHandler extends AbstractPassCmdHandler {
@Override
protected final Mailbox auth(POP3Session session, Username username, String password) throws Exception {
- return auth(session, (String)session.getAttachment(POP3Session.APOP_TIMESTAMP, State.Connection), username, password);
+ return auth(session, session.getAttachment(POP3Session.APOP_TIMESTAMP, State.Connection).orElse(MISSING_APOP_TIMESTAMP), username, password);
}
diff --git a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/DeleCmdHandler.java b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/DeleCmdHandler.java
index 93263aa..ce499d7 100644
--- a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/DeleCmdHandler.java
+++ b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/DeleCmdHandler.java
@@ -19,6 +19,7 @@
package org.apache.james.protocols.pop3.core;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -61,7 +62,12 @@ public class DeleCmdHandler implements CommandHandler<POP3Session> {
StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") does not exist.");
return new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString());
}
- List<String> deletedUidList = (List<String>) session.getAttachment(POP3Session.DELETED_UID_LIST, State.Transaction);
+ List<String> deletedUidList = session.getAttachment(POP3Session.DELETED_UID_LIST, State.Transaction)
+ .orElseGet(() -> {
+ ArrayList<String> uidList = new ArrayList<>();
+ session.setAttachment(POP3Session.DELETED_UID_LIST, uidList, State.Transaction);
+ return uidList;
+ });
String uid = meta.getUid();
diff --git a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/ListCmdHandler.java b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/ListCmdHandler.java
index 7cfeaf9..b706146 100644
--- a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/ListCmdHandler.java
+++ b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/ListCmdHandler.java
@@ -31,6 +31,7 @@ import org.apache.james.protocols.pop3.POP3Response;
import org.apache.james.protocols.pop3.POP3Session;
import org.apache.james.protocols.pop3.mailbox.MessageMetaData;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
/**
@@ -55,8 +56,8 @@ public class ListCmdHandler implements CommandHandler<POP3Session> {
@SuppressWarnings("unchecked")
public Response onCommand(POP3Session session, Request request) {
String parameters = request.getArgument();
- List<MessageMetaData> uidList = (List<MessageMetaData>) session.getAttachment(POP3Session.UID_LIST, State.Transaction);
- List<String> deletedUidList = (List<String>) session.getAttachment(POP3Session.DELETED_UID_LIST, State.Transaction);
+ List<MessageMetaData> uidList = session.getAttachment(POP3Session.UID_LIST, State.Transaction).orElse(ImmutableList.of());
+ List<String> deletedUidList = session.getAttachment(POP3Session.DELETED_UID_LIST, State.Transaction).orElse(ImmutableList.of());
if (session.getHandlerState() == POP3Session.TRANSACTION) {
POP3Response response = null;
@@ -66,10 +67,10 @@ public class ListCmdHandler implements CommandHandler<POP3Session> {
long size = 0;
int count = 0;
List<MessageMetaData> validResults = new ArrayList<>();
- if (uidList.isEmpty() == false) {
+ if (!uidList.isEmpty()) {
for (MessageMetaData data : uidList) {
- if (deletedUidList.contains(data.getUid()) == false) {
+ if (!deletedUidList.contains(data.getUid())) {
size += data.getSize();
count++;
validResults.add(data);
@@ -95,7 +96,7 @@ public class ListCmdHandler implements CommandHandler<POP3Session> {
return new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString());
}
- if (deletedUidList.contains(data.getUid()) == false) {
+ if (!deletedUidList.contains(data.getUid())) {
StringBuilder responseBuffer = new StringBuilder(64).append(num).append(" ").append(data.getSize());
response = new POP3Response(POP3Response.OK_RESPONSE, responseBuffer.toString());
} else {
diff --git a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/MessageMetaDataUtils.java b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/MessageMetaDataUtils.java
index 477f5cf..339c758 100644
--- a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/MessageMetaDataUtils.java
+++ b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/MessageMetaDataUtils.java
@@ -19,7 +19,6 @@
package org.apache.james.protocols.pop3.core;
-import java.util.List;
import java.util.stream.IntStream;
import org.apache.james.protocols.api.ProtocolSession.State;
@@ -33,13 +32,10 @@ public class MessageMetaDataUtils {
* found.
*/
public static MessageMetaData getMetaData(POP3Session session, int number) {
- @SuppressWarnings("unchecked")
- List<MessageMetaData> uidList = (List<MessageMetaData>) session.getAttachment(POP3Session.UID_LIST, State.Transaction);
- if (uidList == null || number > uidList.size()) {
- return null;
- } else {
- return uidList.get(number - 1);
- }
+ return session.getAttachment(POP3Session.UID_LIST, State.Transaction)
+ .filter(uidList -> number <= uidList.size())
+ .map(uidList -> uidList.get(number - 1))
+ .orElse(null);
}
/**
diff --git a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/QuitCmdHandler.java b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/QuitCmdHandler.java
index 791c062..f61714d 100644
--- a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/QuitCmdHandler.java
+++ b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/QuitCmdHandler.java
@@ -33,6 +33,7 @@ import org.apache.james.protocols.pop3.mailbox.Mailbox;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
/**
@@ -59,13 +60,12 @@ public class QuitCmdHandler implements CommandHandler<POP3Session> {
* cleanup of the POP3Handler state.
*/
@Override
- @SuppressWarnings("unchecked")
public Response onCommand(POP3Session session, Request request) {
Response response = null;
if (session.getHandlerState() == POP3Session.AUTHENTICATION_READY || session.getHandlerState() == POP3Session.AUTHENTICATION_USERSET) {
return SIGN_OFF;
}
- List<String> toBeRemoved = (List<String>) session.getAttachment(POP3Session.DELETED_UID_LIST, State.Transaction);
+ List<String> toBeRemoved = session.getAttachment(POP3Session.DELETED_UID_LIST, State.Transaction).orElse(ImmutableList.of());
Mailbox mailbox = session.getUserMailbox();
try {
String[] uids = toBeRemoved.toArray(new String[toBeRemoved.size()]);
diff --git a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/RetrCmdHandler.java b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/RetrCmdHandler.java
index f87d604..99d050c 100644
--- a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/RetrCmdHandler.java
+++ b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/RetrCmdHandler.java
@@ -34,6 +34,7 @@ import org.apache.james.protocols.pop3.POP3StreamResponse;
import org.apache.james.protocols.pop3.mailbox.MessageMetaData;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
/**
@@ -70,10 +71,10 @@ public class RetrCmdHandler implements CommandHandler<POP3Session> {
response = new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString());
return response;
}
- List<String> deletedUidList = (List<String>) session.getAttachment(POP3Session.DELETED_UID_LIST, State.Transaction);
+ List<String> deletedUidList = session.getAttachment(POP3Session.DELETED_UID_LIST, State.Transaction).orElse(ImmutableList.of());
String uid = data.getUid();
- if (deletedUidList.contains(uid) == false) {
+ if (!deletedUidList.contains(uid)) {
InputStream content = session.getUserMailbox().getMessage(uid);
if (content != null) {
diff --git a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/RsetCmdHandler.java b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/RsetCmdHandler.java
index 74601ad..f88ec0b 100644
--- a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/RsetCmdHandler.java
+++ b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/RsetCmdHandler.java
@@ -69,7 +69,7 @@ public class RsetCmdHandler implements CommandHandler<POP3Session> {
List<MessageMetaData> messages = session.getUserMailbox().getMessages();
session.setAttachment(POP3Session.UID_LIST, messages, State.Transaction);
- session.setAttachment(POP3Session.DELETED_UID_LIST, new ArrayList<String>(), State.Transaction);
+ session.setAttachment(POP3Session.DELETED_UID_LIST, new ArrayList<>(), State.Transaction);
} catch (IOException e) {
// In the event of an exception being thrown there may or may not be
// anything in userMailbox
diff --git a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/StatCmdHandler.java b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/StatCmdHandler.java
index 89105f9..f942124 100644
--- a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/StatCmdHandler.java
+++ b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/StatCmdHandler.java
@@ -31,6 +31,7 @@ import org.apache.james.protocols.pop3.POP3Response;
import org.apache.james.protocols.pop3.POP3Session;
import org.apache.james.protocols.pop3.mailbox.MessageMetaData;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
/**
@@ -44,18 +45,17 @@ public class StatCmdHandler implements CommandHandler<POP3Session> {
* of messages in the mailbox and its aggregate size.
*/
@Override
- @SuppressWarnings("unchecked")
public Response onCommand(POP3Session session, Request request) {
if (session.getHandlerState() == POP3Session.TRANSACTION) {
- List<MessageMetaData> uidList = (List<MessageMetaData>) session.getAttachment(POP3Session.UID_LIST, State.Transaction);
- List<String> deletedUidList = (List<String>) session.getAttachment(POP3Session.DELETED_UID_LIST, State.Transaction);
+ List<MessageMetaData> uidList = session.getAttachment(POP3Session.UID_LIST, State.Transaction).orElse(ImmutableList.of());
+ List<String> deletedUidList = session.getAttachment(POP3Session.DELETED_UID_LIST, State.Transaction).orElse(ImmutableList.of());
long size = 0;
int count = 0;
- if (uidList.isEmpty() == false) {
+ if (!uidList.isEmpty()) {
List<MessageMetaData> validResults = new ArrayList<>();
for (MessageMetaData data : uidList) {
- if (deletedUidList.contains(data.getUid()) == false) {
+ if (!deletedUidList.contains(data.getUid())) {
size += data.getSize();
count++;
validResults.add(data);
diff --git a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/TopCmdHandler.java b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/TopCmdHandler.java
index b77f3ff..5931a2b 100644
--- a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/TopCmdHandler.java
+++ b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/TopCmdHandler.java
@@ -88,10 +88,10 @@ public class TopCmdHandler extends RetrCmdHandler implements CapaCapability {
return new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString());
}
- List<String> deletedUidList = (List<String>) session.getAttachment(POP3Session.DELETED_UID_LIST, State.Transaction);
+ List<String> deletedUidList = session.getAttachment(POP3Session.DELETED_UID_LIST, State.Transaction).orElse(ImmutableList.of());
String uid = data.getUid();
- if (deletedUidList.contains(uid) == false) {
+ if (!deletedUidList.contains(uid)) {
InputStream message = new CountingBodyInputStream(new ExtraDotInputStream(new CRLFTerminatedInputStream(session.getUserMailbox().getMessage(uid))), lines);
return new POP3StreamResponse(POP3Response.OK_RESPONSE, "Message follows", message);
diff --git a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/UidlCmdHandler.java b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/UidlCmdHandler.java
index 7f33832..4155a65 100644
--- a/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/UidlCmdHandler.java
+++ b/protocols/pop3/src/main/java/org/apache/james/protocols/pop3/core/UidlCmdHandler.java
@@ -33,6 +33,7 @@ import org.apache.james.protocols.pop3.POP3Response;
import org.apache.james.protocols.pop3.POP3Session;
import org.apache.james.protocols.pop3.mailbox.MessageMetaData;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
/**
@@ -47,13 +48,12 @@ public class UidlCmdHandler implements CommandHandler<POP3Session>, CapaCapabili
* of message ids to the client.
*/
@Override
- @SuppressWarnings("unchecked")
public Response onCommand(POP3Session session, Request request) {
POP3Response response = null;
String parameters = request.getArgument();
if (session.getHandlerState() == POP3Session.TRANSACTION) {
- List<MessageMetaData> uidList = (List<MessageMetaData>) session.getAttachment(POP3Session.UID_LIST, State.Transaction);
- List<String> deletedUidList = (List<String>) session.getAttachment(POP3Session.DELETED_UID_LIST, State.Transaction);
+ List<MessageMetaData> uidList = session.getAttachment(POP3Session.UID_LIST, State.Transaction).orElse(ImmutableList.of());
+ List<String> deletedUidList = session.getAttachment(POP3Session.DELETED_UID_LIST, State.Transaction).orElse(ImmutableList.of());
try {
String identifier = session.getUserMailbox().getIdentifier();
if (parameters == null) {
@@ -61,7 +61,7 @@ public class UidlCmdHandler implements CommandHandler<POP3Session>, CapaCapabili
for (int i = 0; i < uidList.size(); i++) {
MessageMetaData metadata = uidList.get(i);
- if (deletedUidList.contains(metadata.getUid()) == false) {
+ if (!deletedUidList.contains(metadata.getUid())) {
StringBuilder responseBuffer = new StringBuilder().append(i + 1).append(" ").append(metadata.getUid(identifier));
response.appendLine(responseBuffer.toString());
}
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/SMTPSession.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/SMTPSession.java
index 02c84c2..1167750 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/SMTPSession.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/SMTPSession.java
@@ -19,6 +19,10 @@
package org.apache.james.protocols.smtp;
+import java.util.List;
+
+import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
import org.apache.james.protocols.api.ProtocolSession;
/**
@@ -30,12 +34,13 @@ public interface SMTPSession extends ProtocolSession {
// Keys used to store/lookup data in the internal state hash map
/** Sender's email address */
- String SENDER = "SENDER_ADDRESS";
+ AttachmentKey<MaybeSender> SENDER = AttachmentKey.of("SENDER_ADDRESS", MaybeSender.class);
/** The message recipients */
- String RCPT_LIST = "RCPT_LIST";
+ @SuppressWarnings("unchecked")
+ AttachmentKey<List<MailAddress>> RCPT_LIST = AttachmentKey.of("RCPT_LIST", (Class<List<MailAddress>>) (Object) List.class);
/** HELO or EHLO */
- String CURRENT_HELO_MODE = "CURRENT_HELO_MODE";
- String CURRENT_HELO_NAME = "CURRENT_HELO_NAME";
+ AttachmentKey<String> CURRENT_HELO_MODE = AttachmentKey.of("CURRENT_HELO_MODE", String.class);
+ AttachmentKey<String> CURRENT_HELO_NAME = AttachmentKey.of("CURRENT_HELO_NAME", String.class);
/**
* Returns the service wide configuration
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/SMTPSessionImpl.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/SMTPSessionImpl.java
index 91cde64..6b02cf4 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/SMTPSessionImpl.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/SMTPSessionImpl.java
@@ -18,9 +18,9 @@
****************************************************************/
package org.apache.james.protocols.smtp;
-import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
-import org.apache.james.core.MailAddress;
import org.apache.james.protocols.api.ProtocolSessionImpl;
import org.apache.james.protocols.api.ProtocolTransport;
import org.apache.james.protocols.api.Response;
@@ -65,27 +65,19 @@ public class SMTPSessionImpl extends ProtocolSessionImpl implements SMTPSession
@Override
public void resetState() {
// remember the ehlo mode between resets
- Object currentHeloMode = getState().get(CURRENT_HELO_MODE);
+ Optional<String> currentHeloMode = getAttachment(CURRENT_HELO_MODE, State.Transaction);
getState().clear();
// start again with the old helo mode
- if (currentHeloMode != null) {
- getState().put(CURRENT_HELO_MODE, currentHeloMode);
- }
+ currentHeloMode.ifPresent(heloMode -> setAttachment(CURRENT_HELO_MODE, heloMode, State.Transaction));
}
@Override
- @SuppressWarnings("unchecked")
public int getRcptCount() {
- int count = 0;
-
- // check if the key exists
- if (getState().get(SMTPSession.RCPT_LIST) != null) {
- count = ((Collection<MailAddress>) getState().get(SMTPSession.RCPT_LIST)).size();
- }
-
- return count;
+ return getAttachment(SMTPSession.RCPT_LIST, State.Transaction)
+ .map(List::size)
+ .orElse(0);
}
@Override
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractAddHeadersFilter.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractAddHeadersFilter.java
index 9c29ffd..8f0e8e3 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractAddHeadersFilter.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractAddHeadersFilter.java
@@ -25,6 +25,7 @@ import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.james.protocols.api.ProtocolSession;
import org.apache.james.protocols.api.ProtocolSession.State;
import org.apache.james.protocols.api.Response;
import org.apache.james.protocols.api.handler.LineHandler;
@@ -39,8 +40,8 @@ public abstract class AbstractAddHeadersFilter extends SeparatingDataLineFilter
private static final AtomicInteger COUNTER = new AtomicInteger(0);
- private final String headersPrefixAdded = "HEADERS_PREFIX_ADDED" + COUNTER.incrementAndGet();
- private final String headersSuffixAdded = "HEADERS_SUFFIX_ADDED" + COUNTER.incrementAndGet();
+ private final ProtocolSession.AttachmentKey<Boolean> headersPrefixAdded = ProtocolSession.AttachmentKey.of("HEADERS_PREFIX_ADDED" + COUNTER.incrementAndGet(), Boolean.class);
+ private final ProtocolSession.AttachmentKey<Boolean> headersSuffixAdded = ProtocolSession.AttachmentKey.of("HEADERS_SUFFIX_ADDED" + COUNTER.incrementAndGet(), Boolean.class);
enum Location {
Prefix,
@@ -57,7 +58,7 @@ public abstract class AbstractAddHeadersFilter extends SeparatingDataLineFilter
@Override
protected Response onSeparatorLine(SMTPSession session, ByteBuffer line, LineHandler<SMTPSession> next) {
- if (getLocation() == Location.Suffix && session.getAttachment(headersSuffixAdded, State.Transaction) == null) {
+ if (getLocation() == Location.Suffix && !session.getAttachment(headersSuffixAdded, State.Transaction).isPresent()) {
session.setAttachment(headersSuffixAdded, Boolean.TRUE, State.Transaction);
return addHeaders(session, line, next);
}
@@ -66,7 +67,7 @@ public abstract class AbstractAddHeadersFilter extends SeparatingDataLineFilter
@Override
protected Response onHeadersLine(SMTPSession session, ByteBuffer line, LineHandler<SMTPSession> next) {
- if (getLocation() == Location.Prefix && session.getAttachment(headersPrefixAdded, State.Transaction) == null) {
+ if (getLocation() == Location.Prefix && !session.getAttachment(headersPrefixAdded, State.Transaction).isPresent()) {
session.setAttachment(headersPrefixAdded, Boolean.TRUE, State.Transaction);
return addHeaders(session, line, next);
}
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractSenderAuthIdentifyVerificationRcptHook.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractSenderAuthIdentifyVerificationRcptHook.java
index 487ec8c..e709b3e 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractSenderAuthIdentifyVerificationRcptHook.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/AbstractSenderAuthIdentifyVerificationRcptHook.java
@@ -46,7 +46,7 @@ public abstract class AbstractSenderAuthIdentifyVerificationRcptHook implements
@Override
public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
if (session.getUsername() != null) {
- MaybeSender senderAddress = (MaybeSender) session.getAttachment(SMTPSession.SENDER, ProtocolSession.State.Transaction);
+ MaybeSender senderAddress = session.getAttachment(SMTPSession.SENDER, ProtocolSession.State.Transaction).orElse(MaybeSender.nullSender());
// Check if the sender address is the same as the user which was used to authenticate.
// Its important to ignore case here to fix JAMES-837. This is save todo because if the handler is called
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataCmdHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataCmdHandler.java
index 8bebea0..d93b22f 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataCmdHandler.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataCmdHandler.java
@@ -21,7 +21,6 @@ package org.apache.james.protocols.smtp.core;
import java.io.Closeable;
import java.io.IOException;
import java.nio.ByteBuffer;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
@@ -49,6 +48,7 @@ import org.apache.james.protocols.smtp.SMTPSession;
import org.apache.james.protocols.smtp.dsn.DSNStatus;
import org.apache.james.util.MDCBuilder;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -112,7 +112,7 @@ public class DataCmdHandler implements CommandHandler<SMTPSession>, ExtensibleHa
}
}
- public static final String MAILENV = "MAILENV";
+ public static final ProtocolSession.AttachmentKey<MailEnvelope> MAILENV = ProtocolSession.AttachmentKey.of("MAILENV", MailEnvelope.class);
private final MetricFactory metricFactory;
@@ -161,9 +161,9 @@ public class DataCmdHandler implements CommandHandler<SMTPSession>, ExtensibleHa
*/
@SuppressWarnings("unchecked")
protected Response doDATA(SMTPSession session, String argument) {
- MaybeSender sender = (MaybeSender) session.getAttachment(SMTPSession.SENDER, ProtocolSession.State.Transaction);
- MailEnvelope env = createEnvelope(session, sender, new ArrayList<>((Collection<MailAddress>) session.getAttachment(SMTPSession.RCPT_LIST, ProtocolSession.State.Transaction)));
- session.setAttachment(MAILENV, env,ProtocolSession.State.Transaction);
+ MaybeSender sender = session.getAttachment(SMTPSession.SENDER, ProtocolSession.State.Transaction).orElse(MaybeSender.nullSender());
+ MailEnvelope env = createEnvelope(session, sender, session.getAttachment(SMTPSession.RCPT_LIST, ProtocolSession.State.Transaction).orElse(ImmutableList.of()));
+ session.setAttachment(MAILENV, env, ProtocolSession.State.Transaction);
session.pushLineHandler(lineHandler);
return DATA_READY;
@@ -208,9 +208,9 @@ public class DataCmdHandler implements CommandHandler<SMTPSession>, ExtensibleHa
if ((argument != null) && (argument.length() > 0)) {
return UNEXPECTED_ARG;
}
- if (session.getAttachment(SMTPSession.SENDER, ProtocolSession.State.Transaction) == null) {
+ if (!session.getAttachment(SMTPSession.SENDER, ProtocolSession.State.Transaction).isPresent()) {
return NO_SENDER;
- } else if (session.getAttachment(SMTPSession.RCPT_LIST, ProtocolSession.State.Transaction) == null) {
+ } else if (!session.getAttachment(SMTPSession.RCPT_LIST, ProtocolSession.State.Transaction).isPresent()) {
return NO_RECIPIENT;
}
return null;
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataLineMessageHookHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataLineMessageHookHandler.java
index cc645ea..80aded3 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataLineMessageHookHandler.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataLineMessageHookHandler.java
@@ -32,7 +32,7 @@ import org.apache.james.protocols.api.Response;
import org.apache.james.protocols.api.handler.ExtensibleHandler;
import org.apache.james.protocols.api.handler.LineHandler;
import org.apache.james.protocols.api.handler.WiringException;
-import org.apache.james.protocols.smtp.MailEnvelopeImpl;
+import org.apache.james.protocols.smtp.MailEnvelope;
import org.apache.james.protocols.smtp.SMTPResponse;
import org.apache.james.protocols.smtp.SMTPRetCode;
import org.apache.james.protocols.smtp.SMTPSession;
@@ -59,8 +59,10 @@ public class DataLineMessageHookHandler implements DataLineFilter, ExtensibleHan
@Override
public Response onLine(SMTPSession session, ByteBuffer line, LineHandler<SMTPSession> next) {
- MailEnvelopeImpl env = (MailEnvelopeImpl) session.getAttachment(DataCmdHandler.MAILENV, ProtocolSession.State.Transaction);
- OutputStream out = env.getMessageOutputStream();
+ MailEnvelope env = session.getAttachment(DataCmdHandler.MAILENV, ProtocolSession.State.Transaction)
+ .orElseThrow(() -> new RuntimeException("'" + DataCmdHandler.MAILENV.asString() + "' has not been filled."));
+
+ OutputStream out = getMessageOutputStream(env);
try {
// 46 is "."
// Stream terminated
@@ -95,6 +97,14 @@ public class DataLineMessageHookHandler implements DataLineFilter, ExtensibleHan
return null;
}
+ private OutputStream getMessageOutputStream(MailEnvelope env) {
+ try {
+ return env.getMessageOutputStream();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
private byte[] readBytes(ByteBuffer line) {
line.rewind();
byte[] bline;
@@ -107,10 +117,10 @@ public class DataLineMessageHookHandler implements DataLineFilter, ExtensibleHan
return bline;
}
- protected Response processExtensions(SMTPSession session, MailEnvelopeImpl mail) {
+ protected Response processExtensions(SMTPSession session, MailEnvelope mail) {
- if (mail != null && messageHandlers != null) {
+ if (messageHandlers != null) {
for (Object messageHandler : messageHandlers) {
MessageHook rawHandler = (MessageHook) messageHandler;
LOGGER.debug("executing message handler {}", rawHandler);
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/MailCmdHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/MailCmdHandler.java
index a9853e4..5f837e7 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/MailCmdHandler.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/MailCmdHandler.java
@@ -87,7 +87,7 @@ public class MailCmdHandler extends AbstractHookableCmdHandler<MailHook> {
// Check if the response was not ok
if (response.getRetCode().equals(SMTPRetCode.MAIL_OK) == false) {
// cleanup the session
- session.setAttachment(SMTPSession.SENDER, null, State.Transaction);
+ session.removeAttachment(SMTPSession.SENDER, State.Transaction);
}
return response;
@@ -99,16 +99,14 @@ public class MailCmdHandler extends AbstractHookableCmdHandler<MailHook> {
*
* @param session
* SMTP session object
- * @param argument
- * the argument passed in with the command by the SMTP client
*/
- private Response doMAIL(SMTPSession session, String argument) {
+ private Response doMAIL(SMTPSession session) {
StringBuilder responseBuffer = new StringBuilder();
- MaybeSender sender = (MaybeSender) session.getAttachment(SMTPSession.SENDER, State.Transaction);
+ MaybeSender sender = session.getAttachment(SMTPSession.SENDER, State.Transaction).orElse(MaybeSender.nullSender());
responseBuffer.append(
DSNStatus.getStatus(DSNStatus.SUCCESS, DSNStatus.ADDRESS_OTHER))
.append(" Sender <");
- if (sender != null) {
+ if (!sender.isNullSender()) {
responseBuffer.append(sender.asString());
}
responseBuffer.append("> OK");
@@ -123,7 +121,7 @@ public class MailCmdHandler extends AbstractHookableCmdHandler<MailHook> {
@Override
protected Response doCoreCmd(SMTPSession session, String command,
String parameters) {
- return doMAIL(session, parameters);
+ return doMAIL(session);
}
@Override
@@ -146,10 +144,10 @@ public class MailCmdHandler extends AbstractHookableCmdHandler<MailHook> {
sender = argument.substring(colonIndex + 1);
argument = argument.substring(0, colonIndex);
}
- if (session.getAttachment(SMTPSession.SENDER, State.Transaction) != null) {
+ if (session.getAttachment(SMTPSession.SENDER, State.Transaction).isPresent()) {
return SENDER_ALREADY_SPECIFIED;
- } else if (session.getAttachment(
- SMTPSession.CURRENT_HELO_MODE, State.Connection) == null
+ } else if (!session.getAttachment(
+ SMTPSession.CURRENT_HELO_MODE, State.Connection).isPresent()
&& session.getConfiguration().useHeloEhloEnforcement()) {
return EHLO_HELO_NEEDED;
} else if (argument == null
@@ -248,7 +246,7 @@ public class MailCmdHandler extends AbstractHookableCmdHandler<MailHook> {
@Override
protected HookResult callHook(MailHook rawHook, SMTPSession session, String parameters) {
- MaybeSender sender = (MaybeSender) session.getAttachment(SMTPSession.SENDER, State.Transaction);
+ MaybeSender sender = session.getAttachment(SMTPSession.SENDER, State.Transaction).orElse(MaybeSender.nullSender());
return rawHook.doMail(session, sender);
}
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/RcptCmdHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/RcptCmdHandler.java
index c5e8815..93ce9d6 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/RcptCmdHandler.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/RcptCmdHandler.java
@@ -21,6 +21,7 @@ package org.apache.james.protocols.smtp.core;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
@@ -29,6 +30,7 @@ import javax.inject.Inject;
import org.apache.james.core.MailAddress;
import org.apache.james.core.MaybeSender;
import org.apache.james.metrics.api.MetricFactory;
+import org.apache.james.protocols.api.ProtocolSession;
import org.apache.james.protocols.api.ProtocolSession.State;
import org.apache.james.protocols.api.Response;
import org.apache.james.protocols.api.handler.CommandHandler;
@@ -49,7 +51,7 @@ import com.google.common.collect.ImmutableSet;
public class RcptCmdHandler extends AbstractHookableCmdHandler<RcptHook> implements
CommandHandler<SMTPSession> {
private static final Logger LOGGER = LoggerFactory.getLogger(RcptCmdHandler.class);
- public static final String CURRENT_RECIPIENT = "CURRENT_RECIPIENT";
+ public static final ProtocolSession.AttachmentKey<MailAddress> CURRENT_RECIPIENT = ProtocolSession.AttachmentKey.of("CURRENT_RECIPIENT", MailAddress.class);
private static final Collection<String> COMMANDS = ImmutableSet.of("RCPT");
private static final Response MAIL_NEEDED = new SMTPResponse(SMTPRetCode.BAD_SEQUENCE, DSNStatus.getStatus(DSNStatus.PERMANENT, DSNStatus.DELIVERY_OTHER) + " Need MAIL before RCPT").immutable();
private static final Response SYNTAX_ERROR_ARGS = new SMTPResponse(SMTPRetCode.SYNTAX_ERROR_ARGUMENTS, DSNStatus.getStatus(DSNStatus.PERMANENT, DSNStatus.DELIVERY_SYNTAX) + " Usage: RCPT TO:<recipient>").immutable();
@@ -74,16 +76,9 @@ public class RcptCmdHandler extends AbstractHookableCmdHandler<RcptHook> impleme
* parameters passed in with the command by the SMTP client
*/
@Override
- @SuppressWarnings("unchecked")
- protected Response doCoreCmd(SMTPSession session, String command,
- String parameters) {
- Collection<MailAddress> rcptColl = (Collection<MailAddress>) session.getAttachment(
- SMTPSession.RCPT_LIST, State.Transaction);
- if (rcptColl == null) {
- rcptColl = new ArrayList<>();
- }
- MailAddress recipientAddress = (MailAddress) session.getAttachment(
- CURRENT_RECIPIENT, State.Transaction);
+ protected Response doCoreCmd(SMTPSession session, String command, String parameters) {
+ List<MailAddress> rcptColl = session.getAttachment(SMTPSession.RCPT_LIST, State.Transaction).orElseGet(ArrayList::new);
+ MailAddress recipientAddress = session.getAttachment(CURRENT_RECIPIENT, State.Transaction).orElse(MailAddress.nullSender());
rcptColl.add(recipientAddress);
session.setAttachment(SMTPSession.RCPT_LIST, rcptColl, State.Transaction);
StringBuilder response = new StringBuilder();
@@ -111,7 +106,7 @@ public class RcptCmdHandler extends AbstractHookableCmdHandler<RcptHook> impleme
recipient = argument.substring(colonIndex + 1);
argument = argument.substring(0, colonIndex);
}
- if (session.getAttachment(SMTPSession.SENDER, State.Transaction) == null) {
+ if (!session.getAttachment(SMTPSession.SENDER, State.Transaction).isPresent()) {
return MAIL_NEEDED;
} else if (argument == null
|| !argument.toUpperCase(Locale.US).equals("TO")
@@ -187,7 +182,7 @@ public class RcptCmdHandler extends AbstractHookableCmdHandler<RcptHook> impleme
optionTokenizer = null;
}
- session.setAttachment(CURRENT_RECIPIENT,recipientAddress, State.Transaction);
+ session.setAttachment(CURRENT_RECIPIENT, recipientAddress, State.Transaction);
return null;
}
@@ -199,8 +194,9 @@ public class RcptCmdHandler extends AbstractHookableCmdHandler<RcptHook> impleme
} else if (null != recipient) {
sb.append(" [to:").append(recipient).append(']');
}
- MaybeSender sender = (MaybeSender) session.getAttachment(SMTPSession.SENDER, State.Transaction);
- if (null != sender && !sender.isNullSender()) {
+
+ MaybeSender sender = session.getAttachment(SMTPSession.SENDER, State.Transaction).orElse(MaybeSender.nullSender());
+ if (!sender.isNullSender()) {
sb.append(" [from:").append(sender.asString()).append(']');
}
return sb.toString();
@@ -218,9 +214,8 @@ public class RcptCmdHandler extends AbstractHookableCmdHandler<RcptHook> impleme
@Override
protected HookResult callHook(RcptHook rawHook, SMTPSession session, String parameters) {
- MaybeSender sender = (MaybeSender) session.getAttachment(SMTPSession.SENDER, State.Transaction);
- return rawHook.doRcpt(session, sender,
- (MailAddress) session.getAttachment(CURRENT_RECIPIENT, State.Transaction));
+ MaybeSender sender = session.getAttachment(SMTPSession.SENDER, State.Transaction).orElse(MaybeSender.nullSender());
+ return rawHook.doRcpt(session, sender, session.getAttachment(CURRENT_RECIPIENT, State.Transaction).orElse(MailAddress.nullSender()));
}
protected String getDefaultDomain() {
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/ReceivedDataLineFilter.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/ReceivedDataLineFilter.java
index 48b0a73..3c24277 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/ReceivedDataLineFilter.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/ReceivedDataLineFilter.java
@@ -25,11 +25,14 @@ import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Locale;
+import java.util.Optional;
import org.apache.james.core.MailAddress;
import org.apache.james.protocols.api.ProtocolSession.State;
import org.apache.james.protocols.smtp.SMTPSession;
+import com.google.common.collect.ImmutableList;
+
/**
* {@link AbstractAddHeadersFilter} which adds the Received header for the message.
*/
@@ -85,30 +88,31 @@ public class ReceivedDataLineFilter extends AbstractAddHeadersFilter {
StringBuilder headerLineBuffer = new StringBuilder();
- String heloMode = (String) session.getAttachment(SMTPSession.CURRENT_HELO_MODE, State.Connection);
- String heloName = (String) session.getAttachment(SMTPSession.CURRENT_HELO_NAME, State.Connection);
+ Optional<String> heloMode = session.getAttachment(SMTPSession.CURRENT_HELO_MODE, State.Connection);
+ Optional<String> heloName = session.getAttachment(SMTPSession.CURRENT_HELO_NAME, State.Connection);
// Put our Received header first
headerLineBuffer.append("from ").append(session.getRemoteAddress().getHostName());
- if (heloName != null) {
- headerLineBuffer.append(" (").append(heloMode).append(" ").append(heloName).append(")");
+ if (heloName.isPresent() && heloMode.isPresent()) {
+ headerLineBuffer.append(" (").append(heloMode.get()).append(" ").append(heloName.get()).append(")");
}
headerLineBuffer.append(" ([").append(session.getRemoteAddress().getAddress().getHostAddress()).append("])");
Header header = new Header("Received", headerLineBuffer.toString());
headerLineBuffer = new StringBuilder();
- headerLineBuffer.append("by ").append(session.getConfiguration().getHelloName()).append(" (").append(session.getConfiguration().getSoftwareName()).append(") with ").append(getServiceType(session, heloMode));
+ headerLineBuffer.append("by ").append(session.getConfiguration().getHelloName()).append(" (").append(session.getConfiguration().getSoftwareName()).append(") with ").append(getServiceType(session, heloMode.orElse("NOT-DEFINED")));
headerLineBuffer.append(" ID ").append(session.getSessionID());
- if (((Collection<?>) session.getAttachment(SMTPSession.RCPT_LIST, State.Transaction)).size() == 1) {
+ List<MailAddress> rcptList = session.getAttachment(SMTPSession.RCPT_LIST, State.Transaction).orElse(ImmutableList.of());
+ if (rcptList.size() == 1) {
// Only indicate a recipient if they're the only recipient
// (prevents email address harvesting and large headers in
// bulk email)
header.add(headerLineBuffer.toString());
headerLineBuffer = new StringBuilder();
- headerLineBuffer.append("for <").append(((List<MailAddress>) session.getAttachment(SMTPSession.RCPT_LIST, State.Transaction)).get(0).toString()).append(">;");
+ headerLineBuffer.append("for <").append(rcptList.get(0).toString()).append(">;");
} else {
// Put the ; on the end of the 'by' line
headerLineBuffer.append(";");
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/SeparatingDataLineFilter.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/SeparatingDataLineFilter.java
index 4e03460..2b18f3a 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/SeparatingDataLineFilter.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/SeparatingDataLineFilter.java
@@ -20,6 +20,7 @@ package org.apache.james.protocols.smtp.core;
import java.nio.ByteBuffer;
+import org.apache.james.protocols.api.ProtocolSession;
import org.apache.james.protocols.api.ProtocolSession.State;
import org.apache.james.protocols.api.Response;
import org.apache.james.protocols.api.handler.LineHandler;
@@ -46,11 +47,11 @@ import org.apache.james.protocols.smtp.SMTPSession;
*/
public abstract class SeparatingDataLineFilter implements DataLineFilter {
- private static final String HEADERS_COMPLETE = "HEADERS_COMPLETE";
+ private static final ProtocolSession.AttachmentKey<Boolean> HEADERS_COMPLETE = ProtocolSession.AttachmentKey.of("HEADERS_COMPLETE", Boolean.class);
@Override
public final Response onLine(SMTPSession session, ByteBuffer line, LineHandler<SMTPSession> next) {
- if (session.getAttachment(HEADERS_COMPLETE, State.Transaction) == null) {
+ if (!session.getAttachment(HEADERS_COMPLETE, State.Transaction).isPresent()) {
if (line.remaining() == 2) {
if (line.get() == '\r' && line.get() == '\n') {
line.rewind();
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/UnknownCmdHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/UnknownCmdHandler.java
index bc0c414..f50e03b 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/UnknownCmdHandler.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/UnknownCmdHandler.java
@@ -26,6 +26,7 @@ import java.util.Collection;
import javax.inject.Inject;
import org.apache.james.metrics.api.MetricFactory;
+import org.apache.james.protocols.api.ProtocolSession;
import org.apache.james.protocols.api.ProtocolSession.State;
import org.apache.james.protocols.api.Response;
import org.apache.james.protocols.api.handler.UnknownCommandHandler;
@@ -47,6 +48,8 @@ public class UnknownCmdHandler extends AbstractHookableCmdHandler<UnknownHook> {
* The name of the command handled by the command handler
*/
private static final Collection<String> COMMANDS = ImmutableSet.of(UnknownCommandHandler.COMMAND_IDENTIFIER);
+ private static final String MISSING_CURR_COMMAND = "";
+ public static final ProtocolSession.AttachmentKey<String> CURR_COMMAND = ProtocolSession.AttachmentKey.of("CURR_COMMAND", String.class);
@Inject
public UnknownCmdHandler(MetricFactory metricFactory) {
@@ -67,13 +70,13 @@ public class UnknownCmdHandler extends AbstractHookableCmdHandler<UnknownHook> {
@Override
protected Response doFilterChecks(SMTPSession session, String command, String parameters) {
- session.setAttachment("CURR_COMMAND", command, State.Transaction);
+ session.setAttachment(CURR_COMMAND, command, State.Transaction);
return null;
}
@Override
protected HookResult callHook(UnknownHook rawHook, SMTPSession session, String parameters) {
- return rawHook.doUnknown(session, (String) session.getAttachment("CURR_COMMAND", State.Transaction));
+ return rawHook.doUnknown(session, session.getAttachment(CURR_COMMAND, State.Transaction).orElse(MISSING_CURR_COMMAND));
}
@Override
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/esmtp/MailSizeEsmtpExtension.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/esmtp/MailSizeEsmtpExtension.java
index e951d71..16a54e9 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/esmtp/MailSizeEsmtpExtension.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/esmtp/MailSizeEsmtpExtension.java
@@ -23,8 +23,10 @@ import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Optional;
import org.apache.james.core.MaybeSender;
+import org.apache.james.protocols.api.ProtocolSession;
import org.apache.james.protocols.api.ProtocolSession.State;
import org.apache.james.protocols.api.Response;
import org.apache.james.protocols.api.handler.LineHandler;
@@ -48,8 +50,9 @@ public class MailSizeEsmtpExtension implements MailParametersHook, EhloExtension
private static final Logger LOGGER = LoggerFactory.getLogger(MailSizeEsmtpExtension.class);
- private static final String MESG_SIZE = "MESG_SIZE"; // The size of the
- private static final String MESG_FAILED = "MESG_FAILED"; // Message failed flag
+ private static final ProtocolSession.AttachmentKey<Integer> MESG_SIZE = ProtocolSession.AttachmentKey.of("MESG_SIZE", Integer.class); // The size of the
+ private static final ProtocolSession.AttachmentKey<Boolean> MESG_FAILED = ProtocolSession.AttachmentKey.of("MESG_FAILED", Boolean.class); // Message failed flag
+ public static final ProtocolSession.AttachmentKey<Long> CURRENT_SIZE = ProtocolSession.AttachmentKey.of("CURRENT_SIZE", Long.class);
private static final String[] MAIL_PARAMS = { "SIZE" };
private static final HookResult SYNTAX_ERROR = HookResult.builder()
@@ -68,7 +71,7 @@ public class MailSizeEsmtpExtension implements MailParametersHook, EhloExtension
@Override
public HookResult doMailParameter(SMTPSession session, String paramName,
String paramValue) {
- MaybeSender tempSender = (MaybeSender) session.getAttachment(SMTPSession.SENDER, State.Transaction);
+ MaybeSender tempSender = session.getAttachment(SMTPSession.SENDER, State.Transaction).orElse(MaybeSender.nullSender());
return doMailSize(session, paramValue, tempSender);
}
@@ -134,10 +137,10 @@ public class MailSizeEsmtpExtension implements MailParametersHook, EhloExtension
@Override
public Response onLine(SMTPSession session, ByteBuffer line, LineHandler<SMTPSession> next) {
- Boolean failed = (Boolean) session.getAttachment(MESG_FAILED, State.Transaction);
+ Optional<Boolean> failed = session.getAttachment(MESG_FAILED, State.Transaction);
// If we already defined we failed and sent a reply we should simply
// wait for a CRLF.CRLF to be sent by the client.
- if (failed != null && failed) {
+ if (failed.isPresent() && failed.get()) {
if (isDataTerminated(line)) {
line.rewind();
next.onLine(session, line);
@@ -151,15 +154,11 @@ public class MailSizeEsmtpExtension implements MailParametersHook, EhloExtension
return next.onLine(session, line);
} else {
line.rewind();
- Long currentSize = (Long) session.getAttachment("CURRENT_SIZE", State.Transaction);
- Long newSize;
- if (currentSize == null) {
- newSize = Long.valueOf(line.remaining());
- } else {
- newSize = Long.valueOf(currentSize.intValue() + line.remaining());
- }
+ Long newSize = session.getAttachment(CURRENT_SIZE, State.Transaction)
+ .map(currentSize -> Long.valueOf(currentSize.intValue() + line.remaining()))
+ .orElseGet(() -> Long.valueOf(line.remaining()));
- session.setAttachment("CURRENT_SIZE", newSize, State.Transaction);
+ session.setAttachment(CURRENT_SIZE, newSize, State.Transaction);
if (session.getConfiguration().getMaxMessageSize() > 0 && newSize.intValue() > session.getConfiguration().getMaxMessageSize()) {
// Add an item to the state to suppress
@@ -183,8 +182,8 @@ public class MailSizeEsmtpExtension implements MailParametersHook, EhloExtension
@Override
public HookResult onMessage(SMTPSession session, MailEnvelope mail) {
- Boolean failed = (Boolean) session.getAttachment(MESG_FAILED, State.Transaction);
- if (failed != null && failed) {
+ Optional<Boolean> failed = session.getAttachment(MESG_FAILED, State.Transaction);
+ if (failed.isPresent() && failed.get()) {
LOGGER.error("Rejected message from {} from {} exceeding system maximum message size of {}", session.getAttachment(SMTPSession.SENDER, State.Transaction), session.getRemoteAddress().getAddress().getHostAddress(), session.getConfiguration().getMaxMessageSize());
return QUOTA_EXCEEDED;
} else {
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/DNSRBLHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/DNSRBLHandler.java
index 2439de8..68d3181 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/DNSRBLHandler.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/DNSRBLHandler.java
@@ -22,10 +22,12 @@ import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.Collections;
+import java.util.Optional;
import java.util.StringTokenizer;
import org.apache.james.core.MailAddress;
import org.apache.james.core.MaybeSender;
+import org.apache.james.protocols.api.ProtocolSession;
import org.apache.james.protocols.api.ProtocolSession.State;
import org.apache.james.protocols.smtp.SMTPSession;
import org.apache.james.protocols.smtp.dsn.DSNStatus;
@@ -49,11 +51,9 @@ public class DNSRBLHandler implements RcptHook {
private boolean getDetail = false;
- private final String blocklistedDetail = null;
+ public static final ProtocolSession.AttachmentKey<Boolean> RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME = ProtocolSession.AttachmentKey.of("org.apache.james.smtpserver.rbl.blocklisted", Boolean.class);
- public static final String RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME = "org.apache.james.smtpserver.rbl.blocklisted";
-
- public static final String RBL_DETAIL_MAIL_ATTRIBUTE_NAME = "org.apache.james.smtpserver.rbl.detail";
+ public static final ProtocolSession.AttachmentKey<String> RBL_DETAIL_MAIL_ATTRIBUTE_NAME = ProtocolSession.AttachmentKey.of("org.apache.james.smtpserver.rbl.detail", String.class);
/**
* Set the whitelist array
@@ -154,7 +154,7 @@ public class DNSRBLHandler implements RcptHook {
}
}
- session.setAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, "true", State.Connection);
+ session.setAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, true, State.Connection);
return;
} else {
// if it is unknown, it isn't blocked
@@ -171,10 +171,11 @@ public class DNSRBLHandler implements RcptHook {
checkDNSRBL(session, session.getRemoteAddress().getAddress().getHostAddress());
if (!session.isRelayingAllowed()) {
- String blocklisted = (String) session.getAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, State.Connection);
-
- if (blocklisted != null) { // was found in the RBL
- if (blocklistedDetail == null) {
+ Optional<Boolean> blocklisted = session.getAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, State.Connection);
+ Optional<String> blocklistedDetail = session.getAttachment(RBL_DETAIL_MAIL_ATTRIBUTE_NAME, State.Connection);
+
+ if (blocklisted.isPresent()) { // was found in the RBL
+ if (!blocklistedDetail.isPresent()) {
return HookResult.builder()
.hookReturnCode(HookReturnCode.deny())
.smtpDescription(DSNStatus.getStatus(DSNStatus.PERMANENT, DSNStatus.SECURITY_AUTH)
@@ -185,7 +186,7 @@ public class DNSRBLHandler implements RcptHook {
return HookResult.builder()
.hookReturnCode(HookReturnCode.deny())
- .smtpDescription(DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH) + " " + blocklistedDetail)
+ .smtpDescription(DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH) + " " + blocklistedDetail.get())
.build();
}
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/MaxUnknownCmdHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/MaxUnknownCmdHandler.java
index 1461a8f..f8729ec 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/MaxUnknownCmdHandler.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/MaxUnknownCmdHandler.java
@@ -20,6 +20,7 @@
package org.apache.james.protocols.smtp.core.fastfail;
+import org.apache.james.protocols.api.ProtocolSession;
import org.apache.james.protocols.api.ProtocolSession.State;
import org.apache.james.protocols.smtp.SMTPSession;
import org.apache.james.protocols.smtp.hook.HookResult;
@@ -33,7 +34,7 @@ public class MaxUnknownCmdHandler implements UnknownHook {
public static final int DEFAULT_MAX_UNKOWN = 5;
- private static final String UNKOWN_COMMAND_COUNT = "UNKNOWN_COMMAND_COUNT";
+ private static final ProtocolSession.AttachmentKey<Integer> UNKOWN_COMMAND_COUNT = ProtocolSession.AttachmentKey.of("UNKNOWN_COMMAND_COUNT", Integer.class);
private int maxUnknown = DEFAULT_MAX_UNKOWN;
public void setMaxUnknownCmdCount(int maxUnknown) {
@@ -42,12 +43,10 @@ public class MaxUnknownCmdHandler implements UnknownHook {
@Override
public HookResult doUnknown(SMTPSession session, String command) {
- Integer count = (Integer) session.getAttachment(UNKOWN_COMMAND_COUNT, State.Transaction);
- if (count == null) {
- count = 1;
- } else {
- count++;
- }
+ Integer count = session.getAttachment(UNKOWN_COMMAND_COUNT, State.Transaction)
+ .map(fetchedCount -> fetchedCount + 1)
+ .orElse(1);
+
session.setAttachment(UNKOWN_COMMAND_COUNT, count, State.Transaction);
if (count > maxUnknown) {
return HookResult.builder()
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/ResolvableEhloHeloHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/ResolvableEhloHeloHandler.java
index 403490a..1abce80 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/ResolvableEhloHeloHandler.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/ResolvableEhloHeloHandler.java
@@ -24,6 +24,7 @@ import java.net.UnknownHostException;
import org.apache.james.core.MailAddress;
import org.apache.james.core.MaybeSender;
+import org.apache.james.protocols.api.ProtocolSession;
import org.apache.james.protocols.api.ProtocolSession.State;
import org.apache.james.protocols.smtp.SMTPRetCode;
import org.apache.james.protocols.smtp.SMTPSession;
@@ -39,7 +40,7 @@ import org.apache.james.protocols.smtp.hook.RcptHook;
*/
public class ResolvableEhloHeloHandler implements RcptHook, HeloHook {
- public static final String BAD_EHLO_HELO = "BAD_EHLO_HELO";
+ public static final ProtocolSession.AttachmentKey<Boolean> BAD_EHLO_HELO = ProtocolSession.AttachmentKey.of("BAD_EHLO_HELO", Boolean.class);
/**
* Check if EHLO/HELO is resolvable
@@ -50,9 +51,8 @@ public class ResolvableEhloHeloHandler implements RcptHook, HeloHook {
* The argument
*/
protected void checkEhloHelo(SMTPSession session, String argument) {
-
if (isBadHelo(session, argument)) {
- session.setAttachment(BAD_EHLO_HELO, "true", State.Transaction);
+ session.setAttachment(BAD_EHLO_HELO, true, State.Transaction);
}
}
@@ -74,11 +74,7 @@ public class ResolvableEhloHeloHandler implements RcptHook, HeloHook {
protected boolean check(SMTPSession session,MailAddress rcpt) {
// not reject it
- if (session.getAttachment(BAD_EHLO_HELO, State.Transaction) == null) {
- return false;
- }
-
- return true;
+ return session.getAttachment(BAD_EHLO_HELO, State.Transaction).isPresent();
}
@Override
diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/SupressDuplicateRcptHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/SupressDuplicateRcptHandler.java
index bd4cf71..f3782f6 100644
--- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/SupressDuplicateRcptHandler.java
+++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/SupressDuplicateRcptHandler.java
@@ -19,8 +19,6 @@
package org.apache.james.protocols.smtp.core.fastfail;
-import java.util.Collection;
-
import org.apache.james.core.MailAddress;
import org.apache.james.core.MaybeSender;
import org.apache.james.protocols.api.ProtocolSession.State;
@@ -40,25 +38,23 @@ public class SupressDuplicateRcptHandler implements RcptHook {
private static final Logger LOGGER = LoggerFactory.getLogger(SupressDuplicateRcptHandler.class);
@Override
- @SuppressWarnings("unchecked")
public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
- Collection<MailAddress> rcptList = (Collection<MailAddress>) session.getAttachment(SMTPSession.RCPT_LIST, State.Transaction);
-
- // Check if the recipient is already in the rcpt list
- if (rcptList != null && rcptList.contains(rcpt)) {
- StringBuilder responseBuffer = new StringBuilder();
-
- responseBuffer.append(DSNStatus.getStatus(DSNStatus.SUCCESS, DSNStatus.ADDRESS_VALID))
- .append(" Recipient <")
- .append(rcpt.toString())
- .append("> OK");
- LOGGER.debug("Duplicate recipient not add to recipient list: {}", rcpt);
- return HookResult.builder()
- .hookReturnCode(HookReturnCode.ok())
- .smtpReturnCode(SMTPRetCode.MAIL_OK)
- .smtpDescription(responseBuffer.toString())
- .build();
- }
- return HookResult.DECLINED;
+ return session.getAttachment(SMTPSession.RCPT_LIST, State.Transaction)
+ .filter(rcptList -> rcptList.contains(rcpt))
+ .map(rcptList -> {
+ StringBuilder responseBuffer = new StringBuilder();
+
+ responseBuffer.append(DSNStatus.getStatus(DSNStatus.SUCCESS, DSNStatus.ADDRESS_VALID))
+ .append(" Recipient <")
+ .append(rcpt.toString())
+ .append("> OK");
+ LOGGER.debug("Duplicate recipient not add to recipient list: {}", rcpt);
+ return HookResult.builder()
+ .hookReturnCode(HookReturnCode.ok())
+ .smtpReturnCode(SMTPRetCode.MAIL_OK)
+ .smtpDescription(responseBuffer.toString())
+ .build();
+ })
+ .orElse(HookResult.DECLINED);
}
}
diff --git a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/DNSRBLHandlerTest.java b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/DNSRBLHandlerTest.java
index 87c30c4..2265aad 100644
--- a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/DNSRBLHandlerTest.java
+++ b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/DNSRBLHandlerTest.java
@@ -21,6 +21,8 @@
package org.apache.james.protocols.smtp.core.fastfail;
import static org.apache.james.protocols.api.ProtocolSession.State.Connection;
+import static org.apache.james.protocols.smtp.core.fastfail.DNSRBLHandler.RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME;
+import static org.apache.james.protocols.smtp.core.fastfail.DNSRBLHandler.RBL_DETAIL_MAIL_ATTRIBUTE_NAME;
import static org.assertj.core.api.Assertions.assertThat;
import java.net.InetSocketAddress;
@@ -29,6 +31,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import org.apache.james.core.MailAddress;
import org.apache.james.core.MaybeSender;
@@ -38,6 +41,8 @@ import org.apache.james.protocols.smtp.utils.BaseFakeSMTPSession;
import org.junit.Before;
import org.junit.Test;
+import com.google.common.base.Preconditions;
+
public class DNSRBLHandlerTest {
private SMTPSession mockedSMTPSession;
@@ -45,10 +50,6 @@ public class DNSRBLHandlerTest {
private String remoteIp = "127.0.0.2";
private boolean relaying = false;
-
- public static final String RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME = "org.apache.james.smtpserver.rbl.blocklisted";
-
- public static final String RBL_DETAIL_MAIL_ATTRIBUTE_NAME = "org.apache.james.smtpserver.rbl.detail";
@Before
public void setUp() throws Exception {
@@ -114,8 +115,8 @@ public class DNSRBLHandlerTest {
*/
private void setupMockedSMTPSession(MailAddress rcpt) {
mockedSMTPSession = new BaseFakeSMTPSession() {
- HashMap<String,Object> sessionState = new HashMap<>();
- HashMap<String,Object> connectionState = new HashMap<>();
+ HashMap<AttachmentKey<?>,Object> sessionState = new HashMap<>();
+ HashMap<AttachmentKey<?>,Object> connectionState = new HashMap<>();
@Override
public InetSocketAddress getRemoteAddress() {
@@ -127,7 +128,7 @@ public class DNSRBLHandlerTest {
}
@Override
- public Map<String,Object> getState() {
+ public Map<AttachmentKey<?>,Object> getState() {
return sessionState;
}
@@ -147,28 +148,34 @@ public class DNSRBLHandlerTest {
}
@Override
- public Object setAttachment(String key, Object value, State state) {
+ public <T> Optional<T> setAttachment(AttachmentKey<T> key, T value, State state) {
+ Preconditions.checkNotNull(key, "key cannot be null");
+ Preconditions.checkNotNull(value, "value cannot be null");
+
+ if (state == State.Connection) {
+ return key.convert(connectionState.put(key, value));
+ } else {
+ return key.convert(sessionState.put(key, value));
+ }
+ }
+
+ @Override
+ public <T> Optional<T> removeAttachment(AttachmentKey<T> key, State state) {
+ Preconditions.checkNotNull(key, "key cannot be null");
+
if (state == State.Connection) {
- if (value == null) {
- return connectionState.remove(key);
- } else {
- return connectionState.put(key, value);
- }
+ return key.convert(connectionState.remove(key));
} else {
- if (value == null) {
- return sessionState.remove(key);
- } else {
- return sessionState.put(key, value);
- }
+ return key.convert(sessionState.remove(key));
}
}
@Override
- public Object getAttachment(String key, State state) {
+ public <T> Optional<T> getAttachment(AttachmentKey<T> key, State state) {
if (state == State.Connection) {
- return connectionState.get(key);
+ return key.convert(connectionState.get(key));
} else {
- return sessionState.get(key);
+ return key.convert(sessionState.get(key));
}
}
@@ -185,8 +192,8 @@ public class DNSRBLHandlerTest {
rbl.setBlacklist(new String[] { "bl.spamcop.net." });
rbl.setGetDetail(true);
rbl.doRcpt(mockedSMTPSession, MaybeSender.nullSender(), new MailAddress("test@localhost"));
- assertThat(mockedSMTPSession.getAttachment(RBL_DETAIL_MAIL_ATTRIBUTE_NAME, State.Connection)).describedAs("Details").isEqualTo("Blocked - see http://www.spamcop.net/bl.shtml?127.0.0.2");
- assertThat(mockedSMTPSession.getAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("Blocked").isNotNull();
+ assertThat(mockedSMTPSession.getAttachment(RBL_DETAIL_MAIL_ATTRIBUTE_NAME, State.Connection)).describedAs("Details").contains("Blocked - see http://www.spamcop.net/bl.shtml?127.0.0.2");
+ assertThat(mockedSMTPSession.getAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("Blocked").isPresent();
}
// ip is blacklisted and has txt details but we don'T want to retrieve the txt record
@@ -198,8 +205,8 @@ public class DNSRBLHandlerTest {
rbl.setBlacklist(new String[] { "bl.spamcop.net." });
rbl.setGetDetail(false);
rbl.doRcpt(mockedSMTPSession, MaybeSender.nullSender(), new MailAddress("test@localhost"));
- assertThat(mockedSMTPSession.getAttachment(RBL_DETAIL_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("No details").isNull();
- assertThat(mockedSMTPSession.getAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("Blocked").isNotNull();
+ assertThat(mockedSMTPSession.getAttachment(RBL_DETAIL_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("No details").isEmpty();
+ assertThat(mockedSMTPSession.getAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("Blocked").isPresent();
}
// ip is allowed to relay
@@ -212,8 +219,8 @@ public class DNSRBLHandlerTest {
rbl.setBlacklist(new String[] { "bl.spamcop.net." });
rbl.setGetDetail(true);
rbl.doRcpt(mockedSMTPSession, MaybeSender.nullSender(), new MailAddress("test@localhost"));
- assertThat(mockedSMTPSession.getAttachment(RBL_DETAIL_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("No details").isNull();
- assertThat(mockedSMTPSession.getAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("Not blocked").isNull();
+ assertThat(mockedSMTPSession.getAttachment(RBL_DETAIL_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("No details").isEmpty();
+ assertThat(mockedSMTPSession.getAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("Not blocked").isEmpty();
}
// ip not on blacklist
@@ -227,8 +234,8 @@ public class DNSRBLHandlerTest {
rbl.setBlacklist(new String[] { "bl.spamcop.net." });
rbl.setGetDetail(true);
rbl.doRcpt(mockedSMTPSession, MaybeSender.nullSender(), new MailAddress("test@localhost"));
- assertThat(mockedSMTPSession.getAttachment(RBL_DETAIL_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("No details").isNull();
- assertThat(mockedSMTPSession.getAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("Not blocked").isNull();
+ assertThat(mockedSMTPSession.getAttachment(RBL_DETAIL_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("No details").isEmpty();
+ assertThat(mockedSMTPSession.getAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("Not blocked").isEmpty();
}
// ip on blacklist without txt details
@@ -242,8 +249,8 @@ public class DNSRBLHandlerTest {
rbl.setBlacklist(new String[] { "bl.spamcop.net." });
rbl.setGetDetail(true);
rbl.doRcpt(mockedSMTPSession, MaybeSender.nullSender(), new MailAddress("test@localhost"));
- assertThat(mockedSMTPSession.getAttachment(RBL_DETAIL_MAIL_ATTRIBUTE_NAME, Connection)).isNull();
- assertThat(mockedSMTPSession.getAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("Blocked").isNotNull();
+ assertThat(mockedSMTPSession.getAttachment(RBL_DETAIL_MAIL_ATTRIBUTE_NAME, Connection)).isEmpty();
+ assertThat(mockedSMTPSession.getAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("Blocked").isPresent();
}
// ip on whitelist
@@ -257,8 +264,8 @@ public class DNSRBLHandlerTest {
rbl.setWhitelist(new String[] { "bl.spamcop.net." });
rbl.setGetDetail(true);
rbl.doRcpt(mockedSMTPSession, MaybeSender.nullSender(), new MailAddress("test@localhost"));
- assertThat(mockedSMTPSession.getAttachment(RBL_DETAIL_MAIL_ATTRIBUTE_NAME, Connection)).isNull();
- assertThat(mockedSMTPSession.getAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("Not blocked").isNull();
+ assertThat(mockedSMTPSession.getAttachment(RBL_DETAIL_MAIL_ATTRIBUTE_NAME, Connection)).isEmpty();
+ assertThat(mockedSMTPSession.getAttachment(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, Connection)).withFailMessage("Not blocked").isEmpty();
}
diff --git a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/MaxRcptHandlerTest.java b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/MaxRcptHandlerTest.java
index c9eb470..72ee259 100644
--- a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/MaxRcptHandlerTest.java
+++ b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/MaxRcptHandlerTest.java
@@ -35,10 +35,10 @@ public class MaxRcptHandlerTest {
private SMTPSession setupMockedSession(final int rcptCount) {
return new BaseFakeSMTPSession() {
- HashMap<String,Object> state = new HashMap<>();
+ HashMap<AttachmentKey<?>, Object> state = new HashMap<>();
@Override
- public Map<String,Object> getState() {
+ public Map<AttachmentKey<?>, Object> getState() {
return state;
}
diff --git a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/MaxUnknownCmdHandlerTest.java b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/MaxUnknownCmdHandlerTest.java
index 128ce7d..98f9412 100644
--- a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/MaxUnknownCmdHandlerTest.java
+++ b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/MaxUnknownCmdHandlerTest.java
@@ -24,45 +24,57 @@ import static org.assertj.core.api.Assertions.assertThat;
import java.util.HashMap;
import java.util.Map;
+import java.util.Optional;
import org.apache.james.protocols.smtp.SMTPSession;
import org.apache.james.protocols.smtp.hook.HookReturnCode;
import org.apache.james.protocols.smtp.utils.BaseFakeSMTPSession;
import org.junit.Test;
+import com.google.common.base.Preconditions;
+
public class MaxUnknownCmdHandlerTest {
@Test
public void testRejectAndClose() throws Exception {
SMTPSession session = new BaseFakeSMTPSession() {
- private final HashMap<String,Object> map = new HashMap<>();
+ private final HashMap<AttachmentKey<?>, Object> map = new HashMap<>();
@Override
- public Map<String,Object> getState() {
+ public Map<AttachmentKey<?>, Object> getState() {
return map;
}
@Override
- public Object setAttachment(String key, Object value, State state) {
+ public <T> Optional<T> setAttachment(AttachmentKey<T> key, T value, State state) {
+ Preconditions.checkNotNull(key, "key cannot be null");
+ Preconditions.checkNotNull(value, "value cannot be null");
+
if (state == State.Connection) {
throw new UnsupportedOperationException();
+ } else {
+ return key.convert(map.put(key, value));
+ }
+ }
+ @Override
+ public <T> Optional<T> removeAttachment(AttachmentKey<T> key, State state) {
+ Preconditions.checkNotNull(key, "key cannot be null");
+
+ if (state == State.Connection) {
+ throw new UnsupportedOperationException();
} else {
- if (value == null) {
- return map.remove(key);
- } else {
- return map.put(key, value);
- }
+ return key.convert(map.remove(key));
}
}
@Override
- public Object getAttachment(String key, State state) {
+ public <T> Optional<T> getAttachment(AttachmentKey<T> key, State state) {
if (state == State.Connection) {
throw new UnsupportedOperationException();
} else {
- return map.get(key);
+ return key.convert(map.get(key));
}
}
};
diff --git a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/ResolvableEhloHeloHandlerTest.java b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/ResolvableEhloHeloHandlerTest.java
index 320f6a1..cf2052b 100644
--- a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/ResolvableEhloHeloHandlerTest.java
+++ b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/ResolvableEhloHeloHandlerTest.java
@@ -27,6 +27,7 @@ import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
+import java.util.Optional;
import org.apache.james.core.MailAddress;
import org.apache.james.core.MaybeSender;
@@ -36,6 +37,8 @@ import org.apache.james.protocols.smtp.hook.HookReturnCode;
import org.apache.james.protocols.smtp.utils.BaseFakeSMTPSession;
import org.junit.Test;
+import com.google.common.base.Preconditions;
+
public class ResolvableEhloHeloHandlerTest {
public static final String INVALID_HOST = "foo.bar";
@@ -48,8 +51,8 @@ public class ResolvableEhloHeloHandlerTest {
return new BaseFakeSMTPSession() {
- HashMap<String,Object> connectionMap = new HashMap<>();
- HashMap<String,Object> map = new HashMap<>();
+ HashMap<AttachmentKey<?>, Object> connectionMap = new HashMap<>();
+ HashMap<AttachmentKey<?>, Object> map = new HashMap<>();
@Override
public boolean isAuthSupported() {
@@ -62,7 +65,7 @@ public class ResolvableEhloHeloHandlerTest {
}
@Override
- public Map<String,Object> getConnectionState() {
+ public Map<AttachmentKey<?>, Object> getConnectionState() {
return connectionMap;
}
@@ -72,33 +75,39 @@ public class ResolvableEhloHeloHandlerTest {
}
@Override
- public Map<String,Object> getState() {
+ public Map<AttachmentKey<?>, Object> getState() {
return map;
}
@Override
- public Object setAttachment(String key, Object value, State state) {
+ public <T> Optional<T> setAttachment(AttachmentKey<T> key, T value, State state) {
+ Preconditions.checkNotNull(key, "key cannot be null");
+ Preconditions.checkNotNull(value, "value cannot be null");
+
+ if (state == State.Connection) {
+ return key.convert(connectionMap.put(key, value));
+ } else {
+ return key.convert(map.put(key, value));
+ }
+ }
+
+ @Override
+ public <T> Optional<T> removeAttachment(AttachmentKey<T> key, State state) {
+ Preconditions.checkNotNull(key, "key cannot be null");
+
if (state == State.Connection) {
- if (value == null) {
- return connectionMap.remove(key);
- } else {
- return connectionMap.put(key, value);
- }
+ return key.convert(connectionMap.remove(key));
} else {
- if (value == null) {
- return map.remove(key);
- } else {
- return connectionMap.put(key, value);
- }
+ return key.convert(map.remove(key));
}
}
@Override
- public Object getAttachment(String key, State state) {
+ public <T> Optional<T> getAttachment(AttachmentKey<T> key, State state) {
if (state == State.Connection) {
- return connectionMap.get(key);
+ return key.convert(connectionMap.get(key));
} else {
- return connectionMap.get(key);
+ return key.convert(map.get(key));
}
}
@@ -122,11 +131,11 @@ public class ResolvableEhloHeloHandlerTest {
@Test
public void testRejectInvalidHelo() throws Exception {
MailAddress mailAddress = new MailAddress("test@localhost");
- SMTPSession session = setupMockSession(INVALID_HOST,false,false,null,mailAddress);
+ SMTPSession session = setupMockSession(INVALID_HOST, false, false, null, mailAddress);
ResolvableEhloHeloHandler handler = createHandler();
handler.doHelo(session, INVALID_HOST);
- assertThat(session.getAttachment(BAD_EHLO_HELO, Transaction)).withFailMessage("Invalid HELO").isNotNull();
+ assertThat(session.getAttachment(BAD_EHLO_HELO, Transaction)).withFailMessage("Invalid HELO").isPresent();
HookReturnCode result = handler.doRcpt(session, MaybeSender.nullSender(), mailAddress).getResult();
assertThat(HookReturnCode.deny()).describedAs("Reject").isEqualTo(result);
@@ -135,12 +144,12 @@ public class ResolvableEhloHeloHandlerTest {
@Test
public void testNotRejectValidHelo() throws Exception {
MailAddress mailAddress = new MailAddress("test@localhost");
- SMTPSession session = setupMockSession(VALID_HOST,false,false,null,mailAddress);
+ SMTPSession session = setupMockSession(VALID_HOST, false, false, null, mailAddress);
ResolvableEhloHeloHandler handler = createHandler();
handler.doHelo(session, VALID_HOST);
- assertThat(session.getAttachment(BAD_EHLO_HELO, Transaction)).withFailMessage("Valid HELO").isNull();
+ assertThat(session.getAttachment(BAD_EHLO_HELO, Transaction)).withFailMessage("Valid HELO").isEmpty();
HookReturnCode result = handler.doRcpt(session, MaybeSender.nullSender(), mailAddress).getResult();
assertThat(HookReturnCode.declined()).describedAs("Not reject").isEqualTo(result);
@@ -154,7 +163,7 @@ public class ResolvableEhloHeloHandlerTest {
handler.doHelo(session, INVALID_HOST);
- assertThat(session.getAttachment(BAD_EHLO_HELO, Transaction)).withFailMessage("Value stored").isNotNull();
+ assertThat(session.getAttachment(BAD_EHLO_HELO, Transaction)).withFailMessage("Value stored").isPresent();
HookReturnCode result = handler.doRcpt(session, MaybeSender.nullSender(), mailAddress).getResult();
@@ -165,16 +174,15 @@ public class ResolvableEhloHeloHandlerTest {
@Test
public void testRejectRelay() throws Exception {
MailAddress mailAddress = new MailAddress("test@localhost");
- SMTPSession session = setupMockSession(INVALID_HOST,true,false,null,mailAddress);
+ SMTPSession session = setupMockSession(INVALID_HOST, true, false, null, mailAddress);
ResolvableEhloHeloHandler handler = createHandler();
handler.doHelo(session, INVALID_HOST);
- assertThat(session.getAttachment(BAD_EHLO_HELO, Transaction)).withFailMessage("Value stored").isNotNull();
+ assertThat(session.getAttachment(BAD_EHLO_HELO, Transaction)).withFailMessage("Value stored").isPresent();
HookReturnCode result = handler.doRcpt(session, MaybeSender.nullSender(), mailAddress).getResult();
assertThat(HookReturnCode.deny()).describedAs("Reject").isEqualTo(result);
}
}
-
diff --git a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/ValidSenderDomainHandlerTest.java b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/ValidSenderDomainHandlerTest.java
index 407f1ca..685b4f2 100644
--- a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/ValidSenderDomainHandlerTest.java
+++ b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/core/fastfail/ValidSenderDomainHandlerTest.java
@@ -23,6 +23,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import java.util.HashMap;
import java.util.Map;
+import java.util.Optional;
import org.apache.james.core.MailAddress;
import org.apache.james.core.MaybeSender;
@@ -32,6 +33,8 @@ import org.apache.james.protocols.smtp.hook.HookReturnCode;
import org.apache.james.protocols.smtp.utils.BaseFakeSMTPSession;
import org.junit.Test;
+import com.google.common.base.Preconditions;
+
public class ValidSenderDomainHandlerTest {
private ValidSenderDomainHandler createHandler() {
@@ -48,11 +51,10 @@ public class ValidSenderDomainHandlerTest {
private SMTPSession setupMockedSession(final MailAddress sender) {
return new BaseFakeSMTPSession() {
- HashMap<String,Object> map = new HashMap<>();
+ Map<AttachmentKey<?>, Object> map = new HashMap<>();
@Override
- public Map<String,Object> getState() {
-
+ public Map<AttachmentKey<?>, Object> getState() {
map.put(SMTPSession.SENDER, MaybeSender.of(sender));
return map;
@@ -64,25 +66,34 @@ public class ValidSenderDomainHandlerTest {
}
@Override
- public Object setAttachment(String key, Object value, State state) {
+ public <T> Optional<T> setAttachment(AttachmentKey<T> key, T value, State state) {
+ Preconditions.checkNotNull(key, "key cannot be null");
+ Preconditions.checkNotNull(value, "value cannot be null");
+
if (state == State.Connection) {
throw new UnsupportedOperationException();
+ } else {
+ return key.convert(getState().put(key, value));
+ }
+ }
+
+ @Override
+ public <T> Optional<T> removeAttachment(AttachmentKey<T> key, State state) {
+ Preconditions.checkNotNull(key, "key cannot be null");
+ if (state == State.Connection) {
+ throw new UnsupportedOperationException();
} else {
- if (value == null) {
- return getState().remove(key);
- } else {
- return getState().put(key, value);
- }
+ return key.convert(getState().remove(key));
}
}
@Override
- public Object getAttachment(String key, State state) {
+ public <T> Optional<T> getAttachment(AttachmentKey<T> key, State state) {
if (state == State.Connection) {
throw new UnsupportedOperationException();
} else {
- return getState().get(key);
+ return key.convert(getState().get(key));
}
}
@@ -103,7 +114,7 @@ public class ValidSenderDomainHandlerTest {
public void testInvalidSenderDomainReject() throws Exception {
ValidSenderDomainHandler handler = createHandler();
SMTPSession session = setupMockedSession(new MailAddress("invalid@invalid"));
- MaybeSender sender = (MaybeSender) session.getAttachment(SMTPSession.SENDER, State.Transaction);
+ MaybeSender sender = session.getAttachment(SMTPSession.SENDER, State.Transaction).get();
HookReturnCode response = handler.doMail(session, sender).getResult();
assertThat(HookReturnCode.deny()).describedAs("Blocked cause we use reject action").isEqualTo(response);
diff --git a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/utils/BaseFakeSMTPSession.java b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/utils/BaseFakeSMTPSession.java
index a6c8af1..af819ee 100644
--- a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/utils/BaseFakeSMTPSession.java
+++ b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/utils/BaseFakeSMTPSession.java
@@ -23,6 +23,7 @@ package org.apache.james.protocols.smtp.utils;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.Map;
+import java.util.Optional;
import org.apache.james.core.Username;
import org.apache.james.protocols.api.ProtocolSession;
@@ -52,7 +53,7 @@ public class BaseFakeSMTPSession implements SMTPSession {
}
@Override
- public Map<String, Object> getConnectionState() {
+ public Map<AttachmentKey<?>, Object> getConnectionState() {
throw new UnsupportedOperationException("Unimplemented Stub Method");
}
@@ -67,7 +68,7 @@ public class BaseFakeSMTPSession implements SMTPSession {
}
@Override
- public Map<String, Object> getState() {
+ public Map<AttachmentKey<?>, Object> getState() {
throw new UnsupportedOperationException("Unimplemented Stub Method");
}
@@ -147,12 +148,17 @@ public class BaseFakeSMTPSession implements SMTPSession {
}
@Override
- public Object setAttachment(String key, Object value, State state) {
+ public <T> Optional<T> setAttachment(AttachmentKey<T> key, T value, State state) {
throw new UnsupportedOperationException("Unimplemented Stub Method");
}
@Override
- public Object getAttachment(String key, State state) {
+ public <T> Optional<T> removeAttachment(AttachmentKey<T> key, State state) {
+ throw new UnsupportedOperationException("Unimplemented Stub Method");
+ }
+
+ @Override
+ public <T> Optional<T> getAttachment(AttachmentKey<T> key, State state) {
throw new UnsupportedOperationException("Unimplemented Stub Method");
}
diff --git a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/DataLineJamesMessageHookHandler.java b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/DataLineJamesMessageHookHandler.java
index 67c1125..fe3ac7c 100644
--- a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/DataLineJamesMessageHookHandler.java
+++ b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/DataLineJamesMessageHookHandler.java
@@ -74,7 +74,8 @@ public class DataLineJamesMessageHookHandler implements DataLineFilter, Extensib
byte[] line = new byte[lineByteBuffer.remaining()];
lineByteBuffer.get(line, 0, line.length);
- MimeMessageInputStreamSource mmiss = (MimeMessageInputStreamSource) session.getAttachment(SMTPConstants.DATA_MIMEMESSAGE_STREAMSOURCE, State.Transaction);
+ MimeMessageInputStreamSource mmiss = session.getAttachment(SMTPConstants.DATA_MIMEMESSAGE_STREAMSOURCE, State.Transaction)
+ .orElseThrow(() -> new RuntimeException("'" + SMTPConstants.DATA_MIMEMESSAGE_STREAMSOURCE.asString() + "' has not been filled."));
try {
OutputStream out = mmiss.getWritableOutputStream();
@@ -85,9 +86,8 @@ public class DataLineJamesMessageHookHandler implements DataLineFilter, Extensib
out.flush();
out.close();
- @SuppressWarnings("unchecked")
- List<MailAddress> recipientCollection = (List<MailAddress>) session.getAttachment(SMTPSession.RCPT_LIST, State.Transaction);
- MaybeSender sender = (MaybeSender) session.getAttachment(SMTPSession.SENDER, State.Transaction);
+ List<MailAddress> recipientCollection = session.getAttachment(SMTPSession.RCPT_LIST, State.Transaction).orElse(ImmutableList.of());
+ MaybeSender sender = session.getAttachment(SMTPSession.SENDER, State.Transaction).orElse(MaybeSender.nullSender());
MailImpl mail = MailImpl.builder()
.name(MailImpl.getId())
@@ -140,7 +140,8 @@ public class DataLineJamesMessageHookHandler implements DataLineFilter, Extensib
protected Response processExtensions(SMTPSession session, Mail mail) {
if (mail != null && messageHandlers != null) {
try {
- MimeMessageInputStreamSource mmiss = (MimeMessageInputStreamSource) session.getAttachment(SMTPConstants.DATA_MIMEMESSAGE_STREAMSOURCE, State.Transaction);
+ MimeMessageInputStreamSource mmiss = session.getAttachment(SMTPConstants.DATA_MIMEMESSAGE_STREAMSOURCE, State.Transaction)
+ .orElseThrow(() -> new RuntimeException("'" + SMTPConstants.DATA_MIMEMESSAGE_STREAMSOURCE.asString() + "' has not been filled."));
OutputStream out;
out = mmiss.getWritableOutputStream();
for (MessageHook rawHandler : mHandlers) {
diff --git a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/SMTPConstants.java b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/SMTPConstants.java
index b401721..3b062e3 100644
--- a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/SMTPConstants.java
+++ b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/SMTPConstants.java
@@ -19,12 +19,16 @@
package org.apache.james.smtpserver;
+import org.apache.james.protocols.api.ProtocolSession;
+import org.apache.james.server.core.MimeMessageInputStreamSource;
+import org.apache.mailet.Mail;
+
/**
* Constants which are used within SMTP Session
*/
public interface SMTPConstants {
- String DATA_MIMEMESSAGE_STREAMSOURCE = "org.apache.james.core.DataCmdHandler.DATA_MIMEMESSAGE_STREAMSOURCE";
- String MAIL = "MAIL";
+ ProtocolSession.AttachmentKey<MimeMessageInputStreamSource> DATA_MIMEMESSAGE_STREAMSOURCE = ProtocolSession.AttachmentKey.of("org.apache.james.core.DataCmdHandler.DATA_MIMEMESSAGE_STREAMSOURCE", MimeMessageInputStreamSource.class);
+ ProtocolSession.AttachmentKey<Mail> MAIL = ProtocolSession.AttachmentKey.of("MAIL", Mail.class);
}
diff --git a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SPFHandler.java b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SPFHandler.java
index ee4edf9..f7c0e5c 100644
--- a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SPFHandler.java
+++ b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SPFHandler.java
@@ -18,6 +18,8 @@
****************************************************************/
package org.apache.james.smtpserver.fastfail;
+import java.util.Optional;
+
import javax.inject.Inject;
import org.apache.commons.configuration2.Configuration;
@@ -29,6 +31,7 @@ import org.apache.james.jspf.core.exceptions.SPFErrorConstants;
import org.apache.james.jspf.executor.SPFResult;
import org.apache.james.jspf.impl.DefaultSPF;
import org.apache.james.jspf.impl.SPF;
+import org.apache.james.protocols.api.ProtocolSession;
import org.apache.james.protocols.api.ProtocolSession.State;
import org.apache.james.protocols.api.handler.ProtocolHandler;
import org.apache.james.protocols.smtp.SMTPRetCode;
@@ -59,13 +62,13 @@ public class SPFHandler implements JamesMessageHook, MailHook, RcptHook, Protoco
*/
private final Logger serviceLog = FALLBACK_LOG;
- private static final String SPF_BLOCKLISTED = "SPF_BLOCKLISTED";
+ private static final ProtocolSession.AttachmentKey<Boolean> SPF_BLOCKLISTED = ProtocolSession.AttachmentKey.of("SPF_BLOCKLISTED", Boolean.class);
- private static final String SPF_DETAIL = "SPF_DETAIL";
+ private static final ProtocolSession.AttachmentKey<String> SPF_DETAIL = ProtocolSession.AttachmentKey.of("SPF_DETAIL", String.class);
- private static final String SPF_TEMPBLOCKLISTED = "SPF_TEMPBLOCKLISTED";
+ private static final ProtocolSession.AttachmentKey<Boolean> SPF_TEMPBLOCKLISTED = ProtocolSession.AttachmentKey.of("SPF_TEMPBLOCKLISTED", Boolean.class);
- private static final String SPF_HEADER = "SPF_HEADER";
+ private static final ProtocolSession.AttachmentKey<String> SPF_HEADER = ProtocolSession.AttachmentKey.of("SPF_HEADER", String.class);
private static final AttributeName SPF_HEADER_MAIL_ATTRIBUTE_NAME = AttributeName.of("org.apache.james.spf.header");
@@ -114,16 +117,16 @@ public class SPFHandler implements JamesMessageHook, MailHook, RcptHook, Protoco
* SMTP session object
*/
private void doSPFCheck(SMTPSession session, MaybeSender sender) {
- String heloEhlo = (String) session.getAttachment(SMTPSession.CURRENT_HELO_NAME, State.Transaction);
+ Optional<String> heloEhlo = session.getAttachment(SMTPSession.CURRENT_HELO_NAME, State.Transaction);
// We have no Sender or HELO/EHLO yet return false
- if (sender.isNullSender() || heloEhlo == null) {
+ if (sender.isNullSender() || !heloEhlo.isPresent()) {
LOGGER.info("No Sender or HELO/EHLO present");
} else {
String ip = session.getRemoteAddress().getAddress().getHostAddress();
- SPFResult result = spf.checkSPF(ip, sender.asString(), heloEhlo);
+ SPFResult result = spf.checkSPF(ip, sender.asString(), heloEhlo.get());
String spfResult = result.getResult();
@@ -141,10 +144,10 @@ public class SPFHandler implements JamesMessageHook, MailHook, RcptHook, Protoco
explanation = "Block caused by an invalid SPF record";
}
session.setAttachment(SPF_DETAIL, explanation, State.Transaction);
- session.setAttachment(SPF_BLOCKLISTED, "true", State.Transaction);
+ session.setAttachment(SPF_BLOCKLISTED, true, State.Transaction);
} else if (spfResult.equals(SPFErrorConstants.TEMP_ERROR_CONV)) {
- session.setAttachment(SPF_TEMPBLOCKLISTED, "true", State.Transaction);
+ session.setAttachment(SPF_TEMPBLOCKLISTED, true, State.Transaction);
}
}
@@ -155,13 +158,13 @@ public class SPFHandler implements JamesMessageHook, MailHook, RcptHook, Protoco
public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
if (!session.isRelayingAllowed()) {
// Check if session is blocklisted
- if (session.getAttachment(SPF_BLOCKLISTED, State.Transaction) != null) {
+ if (session.getAttachment(SPF_BLOCKLISTED, State.Transaction).isPresent()) {
return HookResult.builder()
.hookReturnCode(HookReturnCode.deny())
- .smtpDescription(DSNStatus.getStatus(DSNStatus.PERMANENT, DSNStatus.SECURITY_AUTH) + " " + session.getAttachment(SPF_TEMPBLOCKLISTED, State.Transaction))
+ .smtpDescription(DSNStatus.getStatus(DSNStatus.PERMANENT, DSNStatus.SECURITY_AUTH) + " " + session.getAttachment(SPF_TEMPBLOCKLISTED, State.Transaction).orElse(false))
.build();
- } else if (session.getAttachment(SPF_TEMPBLOCKLISTED, State.Transaction) != null) {
+ } else if (session.getAttachment(SPF_TEMPBLOCKLISTED, State.Transaction).isPresent()) {
return HookResult.builder()
.hookReturnCode(HookReturnCode.denySoft())
.smtpReturnCode(SMTPRetCode.LOCAL_ERROR)
@@ -277,7 +280,7 @@ public class SPFHandler implements JamesMessageHook, MailHook, RcptHook, Protoco
@Override
public HookResult onMessage(SMTPSession session, Mail mail) {
// Store the spf header as attribute for later using
- mail.setAttribute(new Attribute(SPF_HEADER_MAIL_ATTRIBUTE_NAME, AttributeValue.of((String) session.getAttachment(SPF_HEADER, State.Transaction))));
+ mail.setAttribute(new Attribute(SPF_HEADER_MAIL_ATTRIBUTE_NAME, AttributeValue.of(session.getAttachment(SPF_HEADER, State.Transaction).get())));
return null;
}
diff --git a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/URIRBLHandler.java b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/URIRBLHandler.java
index d2b9dc6..c48d3a2 100644
--- a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/URIRBLHandler.java
+++ b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/URIRBLHandler.java
@@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.Optional;
import javax.inject.Inject;
import javax.mail.MessagingException;
@@ -35,6 +36,7 @@ import javax.mail.internet.MimePart;
import org.apache.commons.configuration2.Configuration;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.james.dnsservice.api.DNSService;
+import org.apache.james.protocols.api.ProtocolSession;
import org.apache.james.protocols.api.ProtocolSession.State;
import org.apache.james.protocols.api.handler.ProtocolHandler;
import org.apache.james.protocols.smtp.SMTPSession;
@@ -55,9 +57,9 @@ public class URIRBLHandler implements JamesMessageHook, ProtocolHandler {
/** This log is the fall back shared by all instances */
private static final Logger LOGGER = LoggerFactory.getLogger(URIRBLHandler.class);
- private static final String LISTED_DOMAIN = "LISTED_DOMAIN";
+ private static final ProtocolSession.AttachmentKey<String> LISTED_DOMAIN = ProtocolSession.AttachmentKey.of("LISTED_DOMAIN", String.class);
- private static final String URBLSERVER = "URBL_SERVER";
+ private static final ProtocolSession.AttachmentKey<String> URBLSERVER = ProtocolSession.AttachmentKey.of("URBL_SERVER", String.class);
private DNSService dnsService;
@@ -108,13 +110,13 @@ public class URIRBLHandler implements JamesMessageHook, ProtocolHandler {
@Override
public HookResult onMessage(SMTPSession session, Mail mail) {
if (check(session, mail)) {
- String uRblServer = (String) session.getAttachment(URBLSERVER, State.Transaction);
- String target = (String) session.getAttachment(LISTED_DOMAIN, State.Transaction);
+ Optional<String> uRblServer = session.getAttachment(URBLSERVER, State.Transaction);
+ Optional<String> target = session.getAttachment(LISTED_DOMAIN, State.Transaction);
String detail = null;
// we should try to retrieve details
- if (getDetail) {
- Collection<String> txt = dnsService.findTXTRecords(target + "." + uRblServer);
+ if (uRblServer.isPresent() && target.isPresent() && getDetail) {
+ Collection<String> txt = dnsService.findTXTRecords(target.get() + "." + uRblServer.get());
// Check if we found a txt record
if (!txt.isEmpty()) {
@@ -127,12 +129,12 @@ public class URIRBLHandler implements JamesMessageHook, ProtocolHandler {
if (detail != null) {
return HookResult.builder()
.hookReturnCode(HookReturnCode.deny())
- .smtpDescription(DSNStatus.getStatus(DSNStatus.PERMANENT, DSNStatus.SECURITY_OTHER) + "Rejected: message contains domain " + target + " listed by " + uRblServer + " . Details: " + detail)
+ .smtpDescription(DSNStatus.getStatus(DSNStatus.PERMANENT, DSNStatus.SECURITY_OTHER) + "Rejected: message contains domain " + target.get() + " listed by " + uRblServer + " . Details: " + detail)
.build();
} else {
return HookResult.builder()
.hookReturnCode(HookReturnCode.deny())
- .smtpDescription(DSNStatus.getStatus(DSNStatus.PERMANENT, DSNStatus.SECURITY_OTHER) + " Rejected: message contains domain " + target + " listed by " + uRblServer)
+ .smtpDescription(DSNStatus.getStatus(DSNStatus.PERMANENT, DSNStatus.SECURITY_OTHER) + " Rejected: message contains domain " + target.orElse("[target not set]") + " listed by " + uRblServer)
.build();
}
diff --git a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/netty/SMTPChannelUpstreamHandler.java b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/netty/SMTPChannelUpstreamHandler.java
index 6ad881d..6933c2b 100644
--- a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/netty/SMTPChannelUpstreamHandler.java
+++ b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/netty/SMTPChannelUpstreamHandler.java
@@ -76,8 +76,8 @@ public class SMTPChannelUpstreamHandler extends BasicChannelUpstreamHandler {
SMTPSession smtpSession = (SMTPSession) ctx.getAttachment();
if (smtpSession != null) {
- LifecycleUtil.dispose(smtpSession.getAttachment(SMTPConstants.MAIL, State.Transaction));
- LifecycleUtil.dispose(smtpSession.getAttachment(SMTPConstants.DATA_MIMEMESSAGE_STREAMSOURCE, State.Transaction));
+ smtpSession.getAttachment(SMTPConstants.MAIL, State.Transaction).ifPresent(LifecycleUtil::dispose);
+ smtpSession.getAttachment(SMTPConstants.DATA_MIMEMESSAGE_STREAMSOURCE, State.Transaction).ifPresent(LifecycleUtil::dispose);
}
super.cleanup(ctx);
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SPFHandlerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SPFHandlerTest.java
index 9db776b..9349d6d 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SPFHandlerTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SPFHandlerTest.java
@@ -23,6 +23,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.util.Optional;
import org.apache.james.core.MailAddress;
import org.apache.james.core.MaybeSender;
@@ -36,6 +37,8 @@ import org.apache.james.smtpserver.fastfail.SPFHandler;
import org.junit.Before;
import org.junit.Test;
+import com.google.common.base.Preconditions;
+
public class SPFHandlerTest {
private DNSService mockedDnsService;
@@ -128,32 +131,40 @@ public class SPFHandlerTest {
private void setupMockedSMTPSession(String ip, final String helo) {
mockedSMTPSession = new BaseFakeSMTPSession() {
- private final HashMap<String, Object> sstate = new HashMap<>();
- private final HashMap<String, Object> connectionState = new HashMap<>();
+ private final HashMap<AttachmentKey<?>, Object> sessionState = new HashMap<>();
+ private final HashMap<AttachmentKey<?>, Object> connectionState = new HashMap<>();
@Override
- public Object setAttachment(String key, Object value, State state) {
+ public <T> Optional<T> setAttachment(AttachmentKey<T> key, T value, State state) {
+ Preconditions.checkNotNull(key, "key cannot be null");
+ Preconditions.checkNotNull(value, "value cannot be null");
+
+ if (state == State.Connection) {
+ return key.convert(connectionState.put(key, value));
+ } else {
+ return key.convert(sessionState.put(key, value));
+ }
+ }
+
+ @Override
+ public <T> Optional<T> removeAttachment(AttachmentKey<T> key, State state) {
+ Preconditions.checkNotNull(key, "key cannot be null");
+
if (state == State.Connection) {
- if (value == null) {
- return connectionState.remove(key);
- }
- return connectionState.put(key, value);
+ return key.convert(connectionState.remove(key));
} else {
- if (value == null) {
- return sstate.remove(key);
- }
- return sstate.put(key, value);
+ return key.convert(sessionState.remove(key));
}
}
@Override
- public Object getAttachment(String key, State state) {
- sstate.put(SMTPSession.CURRENT_HELO_NAME, helo);
+ public <T> Optional<T> getAttachment(AttachmentKey<T> key, State state) {
+ sessionState.put(SMTPSession.CURRENT_HELO_NAME, helo);
if (state == State.Connection) {
- return connectionState.get(key);
+ return key.convert(connectionState.get(key));
} else {
- return sstate.get(key);
+ return key.convert(sessionState.get(key));
}
}
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java
index e650611..6fe930e 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java
@@ -22,6 +22,7 @@ import static org.apache.james.spamassassin.SpamAssassinResult.STATUS_MAIL;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.HashMap;
+import java.util.Optional;
import javax.mail.MessagingException;
import javax.mail.internet.AddressException;
@@ -46,6 +47,8 @@ import org.apache.mailet.base.test.FakeMail;
import org.junit.Rule;
import org.junit.Test;
+import com.google.common.base.Preconditions;
+
public class SpamAssassinHandlerTest {
private static final String SPAMD_HOST = "localhost";
@@ -59,36 +62,44 @@ public class SpamAssassinHandlerTest {
return new BaseFakeSMTPSession() {
- private final HashMap<String, Object> sstate = new HashMap<>();
- private final HashMap<String, Object> connectionState = new HashMap<>();
+ private final HashMap<AttachmentKey<?>, Object> sessionState = new HashMap<>();
+ private final HashMap<AttachmentKey<?>, Object> connectionState = new HashMap<>();
private boolean relayingAllowed;
@Override
- public Object setAttachment(String key, Object value, State state) {
+ public <T> Optional<T> setAttachment(AttachmentKey<T> key, T value, State state) {
+ Preconditions.checkNotNull(key, "key cannot be null");
+ Preconditions.checkNotNull(value, "value cannot be null");
+
+ if (state == State.Connection) {
+ return key.convert(connectionState.put(key, value));
+ } else {
+ return key.convert(sessionState.put(key, value));
+ }
+ }
+
+ @Override
+ public <T> Optional<T> removeAttachment(AttachmentKey<T> key, State state) {
+ Preconditions.checkNotNull(key, "key cannot be null");
+
if (state == State.Connection) {
- if (value == null) {
- return connectionState.remove(key);
- }
- return connectionState.put(key, value);
+ return key.convert(connectionState.remove(key));
} else {
- if (value == null) {
- return sstate.remove(key);
- }
- return sstate.put(key, value);
+ return key.convert(sessionState.remove(key));
}
}
@Override
- public Object getAttachment(String key, State state) {
+ public <T> Optional<T> getAttachment(AttachmentKey<T> key, State state) {
try {
- sstate.put(SMTPSession.SENDER, MaybeSender.of(new MailAddress("sender@james.apache.org")));
+ sessionState.put(SMTPSession.SENDER, MaybeSender.of(new MailAddress("sender@james.apache.org")));
} catch (AddressException e) {
throw new RuntimeException(e);
}
if (state == State.Connection) {
- return connectionState.get(key);
+ return key.convert(connectionState.get(key));
} else {
- return sstate.get(key);
+ return key.convert(sessionState.get(key));
}
}
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/URIRBLHandlerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/URIRBLHandlerTest.java
index b8890aa..af14370 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/URIRBLHandlerTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/URIRBLHandlerTest.java
@@ -27,6 +27,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
+import java.util.Optional;
import javax.mail.MessagingException;
import javax.mail.internet.AddressException;
@@ -46,6 +47,8 @@ import org.apache.mailet.Mail;
import org.apache.mailet.base.test.FakeMail;
import org.junit.Test;
+import com.google.common.base.Preconditions;
+
public class URIRBLHandlerTest {
private static final String BAD_DOMAIN1 = "bad.domain.de";
@@ -61,36 +64,44 @@ public class URIRBLHandlerTest {
private boolean relayingAllowed;
- private final HashMap<String, Object> sstate = new HashMap<>();
- private final HashMap<String, Object> connectionState = new HashMap<>();
+ private final HashMap<AttachmentKey<?>, Object> sessionState = new HashMap<>();
+ private final HashMap<AttachmentKey<?>, Object> connectionState = new HashMap<>();
@Override
- public Object setAttachment(String key, Object value, State state) {
+ public <T> Optional<T> setAttachment(AttachmentKey<T> key, T value, State state) {
+ Preconditions.checkNotNull(key, "key cannot be null");
+ Preconditions.checkNotNull(value, "value cannot be null");
+
+ if (state == State.Connection) {
+ return key.convert(connectionState.put(key, value));
+ } else {
+ return key.convert(sessionState.put(key, value));
+ }
+ }
+
+ @Override
+ public <T> Optional<T> removeAttachment(AttachmentKey<T> key, State state) {
+ Preconditions.checkNotNull(key, "key cannot be null");
+
if (state == State.Connection) {
- if (value == null) {
- return connectionState.remove(key);
- }
- return connectionState.put(key, value);
+ return key.convert(connectionState.remove(key));
} else {
- if (value == null) {
- return sstate.remove(key);
- }
- return sstate.put(key, value);
+ return key.convert(sessionState.remove(key));
}
}
@Override
- public Object getAttachment(String key, State state) {
+ public <T> Optional<T> getAttachment(AttachmentKey<T> key, State state) {
try {
- sstate.put(SMTPSession.SENDER, MaybeSender.of(new MailAddress("sender@james.apache.org")));
+ sessionState.put(SMTPSession.SENDER, MaybeSender.of(new MailAddress("sender@james.apache.org")));
} catch (AddressException e) {
throw new RuntimeException(e);
}
if (state == State.Connection) {
- return connectionState.get(key);
+ return key.convert(connectionState.get(key));
} else {
- return sstate.get(key);
+ return key.convert(sessionState.get(key));
}
}
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java
index 97ee1a1..45bc31b 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java
@@ -23,6 +23,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import java.util.HashMap;
+import java.util.Optional;
import org.apache.james.core.Domain;
import org.apache.james.core.MailAddress;
@@ -43,6 +44,8 @@ import org.apache.james.user.memory.MemoryUsersRepository;
import org.junit.Before;
import org.junit.Test;
+import com.google.common.base.Preconditions;
+
public class ValidRcptHandlerTest {
private static final Username VALID_USER = Username.of("postmaster");
private static final String INVALID_USER = "invalid";
@@ -85,30 +88,38 @@ public class ValidRcptHandlerTest {
return relayingAllowed;
}
- private final HashMap<String, Object> sstate = new HashMap<>();
- private final HashMap<String, Object> connectionState = new HashMap<>();
+ private final HashMap<AttachmentKey<?>, Object> sessionState = new HashMap<>();
+ private final HashMap<AttachmentKey<?>, Object> connectionState = new HashMap<>();
@Override
- public Object setAttachment(String key, Object value, State state) {
+ public <T> Optional<T> setAttachment(AttachmentKey<T> key, T value, State state) {
+ Preconditions.checkNotNull(key, "key cannot be null");
+ Preconditions.checkNotNull(value, "value cannot be null");
+
+ if (state == State.Connection) {
+ return key.convert(connectionState.put(key, value));
+ } else {
+ return key.convert(sessionState.put(key, value));
+ }
+ }
+
+ @Override
+ public <T> Optional<T> removeAttachment(AttachmentKey<T> key, State state) {
+ Preconditions.checkNotNull(key, "key cannot be null");
+
if (state == State.Connection) {
- if (value == null) {
- return connectionState.remove(key);
- }
- return connectionState.put(key, value);
+ return key.convert(connectionState.remove(key));
} else {
- if (value == null) {
- return sstate.remove(key);
- }
- return sstate.put(key, value);
+ return key.convert(sessionState.remove(key));
}
}
@Override
- public Object getAttachment(String key, State state) {
+ public <T> Optional<T> getAttachment(AttachmentKey<T> key, State state) {
if (state == State.Connection) {
- return connectionState.get(key);
+ return key.convert(connectionState.get(key));
} else {
- return sstate.get(key);
+ return key.convert(sessionState.get(key));
}
}
};
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptMXTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptMXTest.java
index be784d7..ee29e3f 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptMXTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptMXTest.java
@@ -21,6 +21,7 @@ package org.apache.james.smtpserver;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.HashMap;
+import java.util.Optional;
import org.apache.james.core.MailAddress;
import org.apache.james.core.MaybeSender;
@@ -32,6 +33,7 @@ import org.apache.james.protocols.smtp.utils.BaseFakeSMTPSession;
import org.apache.james.smtpserver.fastfail.ValidRcptMX;
import org.junit.Test;
+import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
public class ValidRcptMXTest {
@@ -41,30 +43,38 @@ public class ValidRcptMXTest {
private SMTPSession setupMockedSMTPSession(MailAddress rcpt) {
return new BaseFakeSMTPSession() {
- private final HashMap<String, Object> sstate = new HashMap<>();
- private final HashMap<String, Object> connectionState = new HashMap<>();
+ private final HashMap<AttachmentKey<?>, Object> sessionState = new HashMap<>();
+ private final HashMap<AttachmentKey<?>, Object> connectionState = new HashMap<>();
@Override
- public Object setAttachment(String key, Object value, State state) {
+ public <T> Optional<T> setAttachment(AttachmentKey<T> key, T value, State state) {
+ Preconditions.checkNotNull(key, "key cannot be null");
+ Preconditions.checkNotNull(value, "value cannot be null");
+
+ if (state == State.Connection) {
+ return key.convert(connectionState.put(key, value));
+ } else {
+ return key.convert(sessionState.put(key, value));
+ }
+ }
+
+ @Override
+ public <T> Optional<T> removeAttachment(AttachmentKey<T> key, State state) {
+ Preconditions.checkNotNull(key, "key cannot be null");
+
if (state == State.Connection) {
- if (value == null) {
- return connectionState.remove(key);
- }
- return connectionState.put(key, value);
+ return key.convert(connectionState.remove(key));
} else {
- if (value == null) {
- return sstate.remove(key);
- }
- return sstate.put(key, value);
+ return key.convert(sessionState.remove(key));
}
}
@Override
- public Object getAttachment(String key, State state) {
+ public <T> Optional<T> getAttachment(AttachmentKey<T> key, State state) {
if (state == State.Connection) {
- return connectionState.get(key);
+ return key.convert(connectionState.get(key));
} else {
- return sstate.get(key);
+ return key.convert(sessionState.get(key));
}
}
};
diff --git a/upgrade-instructions.md b/upgrade-instructions.md
index aa2ade8..0853760 100644
--- a/upgrade-instructions.md
+++ b/upgrade-instructions.md
@@ -30,7 +30,25 @@ Change list:
- [UidValidity and maildir](#uid-validity-and-maildir)
- [UidValidity and JPA or Cassandra](#uid-validity-and-jpa-or-cassandra)
- [Differentiation between domain alias and domain mapping](#differentiation-between-domain-alias-and-domain-mapping)
+ - [ProtocolSession storng typing](#protocolsession-storng-typing)
+### ProtocolSession storng typing
+
+Date 19/03/2020
+
+SHA-1 XXX
+
+JIRA: https://issues.apache.org/jira/browse/JAMES-3119
+
+`ProtocolSession` have been reworked in order to increase type strengh
+and reduce errors.
+
+Now `setAttachment` and `getAttachment` are expecting an `AttachmentKey` as key
+and return an `Optional` instead of a `null`-able value.
+
+Moreover `setAttachment` do not allow `null` values and `removeAttachment`
+should be use now to remove elements.
+
### Differentiation between domain alias and domain mapping
Date 10/03/2020
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org