diff --git a/src/main/java/io/github/hectorvent/floci/services/ses/SmtpRelay.java b/src/main/java/io/github/hectorvent/floci/services/ses/SmtpRelay.java index 9826ab1..f943c5e 100644 --- a/src/main/java/io/github/hectorvent/floci/services/ses/SmtpRelay.java +++ b/src/main/java/io/github/hectorvent/floci/services/ses/SmtpRelay.java @@ -57,6 +57,8 @@ public class SmtpRelay { private static final Logger LOG = Logger.getLogger(SmtpRelay.class); 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. */ public static final String HEADER_CONFIGURATION_SET = "X-SES-CONFIGURATION-SET"; @@ -118,6 +120,9 @@ public class SmtpRelay { .filter(u -> !u.isBlank()) .ifPresent(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() .filter(p -> !p.isBlank()) .ifPresent(mailConfig::setPassword); diff --git a/src/test/java/io/github/hectorvent/floci/services/ses/SmtpRelayServerTest.java b/src/test/java/io/github/hectorvent/floci/services/ses/SmtpRelayServerTest.java index b64335c..2d2df11 100644 --- a/src/test/java/io/github/hectorvent/floci/services/ses/SmtpRelayServerTest.java +++ b/src/test/java/io/github/hectorvent/floci/services/ses/SmtpRelayServerTest.java @@ -287,7 +287,8 @@ class SmtpRelayServerTest { String command = line.toUpperCase(Locale.ROOT); if (command.startsWith("EHLO")) { 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")) { reply(out, "250 floci-stub"); } else if (command.startsWith("AUTH")) {