javaMail не работает с OAuth gmail отправить письмо

javaMail: отправка почты с использованием google oauth вызвала исключение javax.mail.AuthenticationFailedException.

      Properties props = new Properties();
props.put("mail.smtp.ssl.enable", "true"); // required for Gmail
props.put("mail.smtp.auth.mechanisms", "XOAUTH2");

Session session = Session.getInstance(props);
Transport transport = session.getTransport("smtps");
transport.connect("smtp.gmail.com", 465, xyz@gmail.com, oauth_access_token);

Токен доступа oauth действителен, только что обновлен, примерно за 20 секунд до запуска кода.

Ошибка:

      javax.mail.AuthenticationFailedException: 535-5.7.8 Username and Password not accepted. Learn more at
535 5.7.8  https://support.google.com/mail/?p=BadCredentials s136sm158338qka.106 - gsmtp

        at com.sun.mail.smtp.SMTPTransport$Authenticator.authenticate(SMTPTransport.java:965)
        at com.sun.mail.smtp.SMTPTransport.authenticate(SMTPTransport.java:876)
        at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:780)
        at javax.mail.Service.connect(Service.java:366)

Из журнала кажется, что auth использует имя пользователя / пароль, а не OAUTH. руководство: https://javaee.github.io/javamail/OAuth2

Логирование:

      DEBUG: JavaMail version 1.6.2
DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle]
DEBUG SMTP: useEhlo true, useAuth false
DEBUG SMTP: trying to connect to host "smtp.gmail.com", port 465, isSSL true
220 smtp.gmail.com ESMTP s136sm158338qka.106 - gsmtp
DEBUG SMTP: connected to host "smtp.gmail.com", port: 465
250-8BITMIME
250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-CHUNKING
250 SMTPUTF8
DEBUG SMTP: Found extension "SIZE", arg "35882577"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH"
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "CHUNKING", arg ""
DEBUG SMTP: Found extension "SMTPUTF8", arg ""
DEBUG SMTP: protocolConnect login, host=smtp.gmail.com, user=xyz@gmail.com, password=<non-null>
DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM XOAUTH2
DEBUG SMTP: Using mechanism LOGIN
DEBUG SMTP: AUTH LOGIN command trace suppressed
DEBUG SMTP: AUTH LOGIN failed

3 ответа

На случай, если кто-то наткнется на эту страницу: JavaMail работает с аутентификацией Gmail OAuth2. Вот как это работает на моей кодовой базе Kotlin:

  1. Реквизит, необходимый дляпоказано ниже (это в формате yaml, но вы поняли идею):
      javamail:
  config:
    "mail.smtp.host": smtp.gmail.com
    "mail.smtp.port": 587
    "mail.smtp.starttls.enable": true
    "mail.smtp.starttls.required": true
    "mail.smtp.auth.mechanisms": XOAUTH2
  1. При создании электронного письма (состоящего из нескольких частей или нет) прилагаемое MIME-сообщение должно быть привязано к Sessionкоторый имеет все вышеперечисленные реквизиты. Это можно легко пропустить при использовании класса из библиотеки для создания электронного письма (например,SimpleEmail):
      val session = Session.getInstance(javamail.config().toProperties())

val email = SimpleEmail().apply {
    setMailSession(session) // do not forget this line
    setCharset("utf-8")
    setFrom(credInfo.email())
    addTo("someone@somewhere.com")
    setSubject("Test email")
    setMsg("This is the test.")

    buildMimeMessage()
}
  1. Вызов статического методаTransport.send(msg, username, password), куда usernameваша электронная почта, и passwordваш новый токен доступа. Нет необходимости создавать экземпляр Transport, ни необходимости звонить transport.connect():
      Transport.send(email.mimeMessage, gmail, accessToken)

Пробуем следующий код:

              Properties props = new Properties()
            props.setProperty("mail.smtp.host", "smtp.gmail.com")
            props.setProperty("mail.smtp.port", "587")
            props.put("mail.smtp.auth","true")
            props.put("mail.smtp.starttls.enable", "true")
            props.put("mail.smtp.starttls.required", "true")
            props.put("mail.smtp.auth.mechanisms", "XOAUTH2")
            props.put("mail.smtp.auth.login.disable", "true")
            props.put("mail.smtp.auth.plain.disable", "true")
            props.put("mail.smtp.auth.ntlm.disable", "true")
            props.put("mail.debug", "true")
            props.put("mail.debug.auth", "true")
            Session session = Session.getInstance(props)
            String emptyPassword = ""
            final URLName unusedUrlName = null
            SMTPTransport transport = new SMTPTransport(session, unusedUrlName)
            transport.connect("smtp.gmail.com", googleEmail, googleAccessToken)\
            Multipart multipart = new MimeMultipart()
            BodyPart messageBodyPart = new MimeBodyPart()
            def from = googleEmail
            def to = "test@test.com"
            def subj = "TestOath2Gmail"
            def body = "TTT"
            message.setFrom(new InternetAddress(googleEmail))
            message.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(to))
            Date sentDate = new Date()
            message.setSentDate(sentDate)
            message.setSubject(subj)
            messageBodyPart.setContent(body, "text/html")
            multipart.addBodyPart(messageBodyPart)
            message.setContent(multipart)
            transport.send(message)

Получение ошибки: DEBUG SMTP: Использование механизма XOAUTH2AUTH XOAUTH2 235 2.7.0 Принято DEBUG: getProvider() возвращает javax.mail.Provider[TRANSPORT, smtp, com.sun.mail.smtp.SMTPTransport,Oracle]DEBUG SMTP: требуется имя пользователя и пароль для аутентификации DEBUG SMTP: protocolConnect возвращает false, host = smtp.gmail.com, user = username, password =

Я думаю, вам нужно отключить обычную аутентификацию, чтобы Jakarta Mail использовала XOAUTH2.

props.put("mail.smtp.auth.plain.disable", "true");

Другие вопросы по тегам