diff --git a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/ValidRcptHandler.java b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/ValidRcptHandler.java index f435f305715..ca31b879881 100644 --- a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/ValidRcptHandler.java +++ b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/ValidRcptHandler.java @@ -18,13 +18,14 @@ ****************************************************************/ package org.apache.james.smtpserver.fastfail; +import java.util.EnumSet; + import jakarta.inject.Inject; import org.apache.commons.configuration2.Configuration; import org.apache.commons.configuration2.ex.ConfigurationException; import org.apache.james.core.Domain; import org.apache.james.core.MailAddress; -import org.apache.james.core.Username; import org.apache.james.domainlist.api.DomainList; import org.apache.james.domainlist.api.DomainListException; import org.apache.james.protocols.api.handler.ProtocolHandler; @@ -33,7 +34,7 @@ import org.apache.james.rrt.api.RecipientRewriteTable; import org.apache.james.rrt.api.RecipientRewriteTable.ErrorMappingException; import org.apache.james.rrt.api.RecipientRewriteTableException; -import org.apache.james.rrt.lib.Mappings; +import org.apache.james.rrt.lib.Mapping; import org.apache.james.user.api.UsersRepository; import org.apache.james.user.api.UsersRepositoryException; import org.slf4j.Logger; @@ -64,28 +65,44 @@ public void setSupportsRecipientRewriteTable(boolean supportsRecipientRewriteTab @Override protected boolean isValidRecipient(SMTPSession session, MailAddress recipient) throws UsersRepositoryException, RecipientRewriteTableException { - Username username = users.getUsername(recipient); - - if (users.contains(username)) { + // Check existence of mailbox early to use RRT less often. + if (mailboxExists(recipient)) { return true; - } else { - return supportsRecipientRewriteTable && isRedirected(recipient, username.asString()); } + + // Check whether there is at least one valid mailbox after + // resolving the recipient using the RRT. + return isResolvableToAtLeastOneMailbox(recipient); + } + + protected boolean mailboxExists(MailAddress recipient) throws UsersRepositoryException { + return users.contains(users.getUsername(recipient)); } - private boolean isRedirected(MailAddress recipient, String username) throws RecipientRewriteTableException { - LOGGER.debug("Unknown user {} check if it's an alias", username); + private boolean isResolvableToAtLeastOneMailbox(MailAddress recipient) throws RecipientRewriteTableException { + if (!supportsRecipientRewriteTable) { + return false; + } + LOGGER.debug("Unknown recipient {}, resolving it via RRT", recipient); try { - Mappings targetString = recipientRewriteTable.getResolvedMappings(recipient.getLocalPart(), recipient.getDomain()); - - if (!targetString.isEmpty()) { - return true; - } + return recipientRewriteTable + // Error mappings are only used to forbid sending from the source address and can be ignored here. + .getResolvedMappings(recipient.getLocalPart(), recipient.getDomain(), EnumSet.complementOf(EnumSet.of(Mapping.Type.Error))) + .asStream() + .flatMap(mapping -> mapping.asMailAddress().stream()) + .anyMatch(address -> { + try { + return mailboxExists(address); + } catch (UsersRepositoryException e) { + return false; + } + }); } catch (ErrorMappingException e) { - return true; + // As we filter the mappings above, this case should never happen. + LOGGER.error("Unexpexted mapping of type Error: ", e); + return false; } - return false; } @Override