fix(ses): sign in to the SMTP relay with the password, not as an OAuth token

Vert.x mail prefers XOAUTH2 whenever the server offers it, so against Gmail the
app password was sent as an OAuth token and refused (535 5.7.8). Limit the
relay to the password-based SASL methods.
This commit is contained in:
Zakaria
2026-10-25 07:52:52 -04:00
parent 327173c8f6
commit 2486869b6b
2 changed files with 7 additions and 1 deletions
@@ -57,6 +57,8 @@ public class SmtpRelay {
private static final Logger LOG = Logger.getLogger(SmtpRelay.class); private static final Logger LOG = Logger.getLogger(SmtpRelay.class);
private static final long RELAY_TIMEOUT_SECONDS = 30; private static final long RELAY_TIMEOUT_SECONDS = 30;
/** Every SASL method the mail client supports except XOAUTH2, which expects a token. */
static final String PASSWORD_AUTH_METHODS = "CRAM-SHA256 CRAM-SHA1 CRAM-MD5 DIGEST-MD5 LOGIN PLAIN";
/** SES control header naming the configuration set to apply to a raw send. */ /** SES control header naming the configuration set to apply to a raw send. */
public static final String HEADER_CONFIGURATION_SET = "X-SES-CONFIGURATION-SET"; public static final String HEADER_CONFIGURATION_SET = "X-SES-CONFIGURATION-SET";
@@ -118,6 +120,9 @@ public class SmtpRelay {
.filter(u -> !u.isBlank()) .filter(u -> !u.isBlank())
.ifPresent(u -> { .ifPresent(u -> {
mailConfig.setUsername(u); mailConfig.setUsername(u);
// smtp-pass is a password, never an OAuth token: without this the client prefers
// XOAUTH2 whenever the server offers it (Gmail does) and the login is refused.
mailConfig.setAuthMethods(PASSWORD_AUTH_METHODS);
config.services().ses().smtpPass() config.services().ses().smtpPass()
.filter(p -> !p.isBlank()) .filter(p -> !p.isBlank())
.ifPresent(mailConfig::setPassword); .ifPresent(mailConfig::setPassword);
@@ -287,7 +287,8 @@ class SmtpRelayServerTest {
String command = line.toUpperCase(Locale.ROOT); String command = line.toUpperCase(Locale.ROOT);
if (command.startsWith("EHLO")) { if (command.startsWith("EHLO")) {
reply(out, "250-floci-stub"); reply(out, "250-floci-stub");
reply(out, "250 AUTH PLAIN"); // Gmail also offers OAuth sign-in, which a password must never be sent as.
reply(out, "250 AUTH PLAIN XOAUTH2 OAUTHBEARER");
} else if (command.startsWith("HELO")) { } else if (command.startsWith("HELO")) {
reply(out, "250 floci-stub"); reply(out, "250 floci-stub");
} else if (command.startsWith("AUTH")) { } else if (command.startsWith("AUTH")) {