Не удается подключиться к SMTP-серверу Office 365 через Jakarta Mail с использованием OAuth 2


В настоящее время я пытаюсь интегрировать OAuth2 в существующую инфраструктуру электронной почты приложения Java. Приложение использует почту Джакарты, которая, согласно их документации, поддерживает OAuth2 (https://eclipse-ee4j.github.io/mail/OAuth2). По какой-то причине я изо всех сил пытаюсь подключиться к SMTP-серверу Office 365, в то время как подключение через IMAP работает отлично. Итак, вот что я делал до сих пор:
  1. Создайте учетную запись разработчика Office 365, заполните ее пользователями и пользовательскими данными.
  2. Войдите в серверную часть Azure, настройте регистрацию приложения, включая URL-адрес обратного вызова и т. д., и следующие права API: https://i.stack.imgur.com/lXjER.png
  3. Используйте следующий URL-адрес аутентификации для создания кода аутентификации:
https://login.microsoftonline.com/{my_tenant_id}/oauth2/v2.0/authorize?
client_id = {my_client_id}&
state=state_to_check&
redirect_uri=http://localhost:5555/callback/authorization&
scope=offline_access https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/POP.AccessAsUser.All https://outlook.office.com/SMTP.Send
&response_type=code

Как видите, я использую следующие области видимости:

offline_access 
https://outlook.office.com/IMAP.AccessAsUser.All 
https://outlook.office.com/POP.AccessAsUser.All 
https://outlook.office.com/SMTP.Send
  1. Получите код авторизации и используйте его для обновления и токена доступа, что дает мне следующий ответ:
{
    "token_type": "Bearer",
    "scope": "https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/Mail.Read https://outlook.office.com/Mail.Read.All https://outlook.office.com/Mail.Read.Shared https://outlook.office.com/Mail.ReadBasic https://outlook.office.com/Mail.ReadWrite https://outlook.office.com/Mail.Send https://outlook.office.com/Mail.Send.All https://outlook.office.com/Mail.Send.Shared https://outlook.office.com/POP.AccessAsUser.All https://outlook.office.com/SMTP.Send https://outlook.office.com/User.Read",
    "expires_in": 3599,
    "ext_expires_in": 3599,
    "access_token": ...,
    "refresh_token": ...
}

Итак, я бы сказал, что пока все работает, как и ожидалось, в отношении процесса аутентификации OAuth 2.0. Теперь, переходя к использованию токена доступа для получения доступа к учетной записи электронной почты пользователя, я добавил следующие несколько строк в логику электронной почты нашего приложения, чтобы активировать IMAP через OAuth:

[more props stuff here]

if (useOauth) {
    props.put("mail." + protocol + ".auth", "true");
    props.put("mail." + protocol + ".auth.mechanisms", "XOAUTH2");
    props.put("mail." + protocol + ".auth.login.disable", "true");
    props.put("mail." + protocol + ".auth.plain.disable", "true");
}

return Session.getInstance(props);

Это прекрасно работает, и я могу подключаться через IMAP, читать папки, сообщения и т. д. Моя проблема в том, что если я попытаюсь изменить наш код аналогичным образом для SMTP, я получу следующую ошибку:

Exception in thread "main" jakarta.mail.AuthenticationFailedException: 451 4.7.0 Temporary server error. Please try again later. PRX4  [AM9P191CA0011.EURP191.PROD.OUTLOOK.COM]

    at com.sun.mail.smtp.SMTPTransport$Authenticator.authenticate(SMTPTransport.java:947)
    at com.sun.mail.smtp.SMTPTransport.authenticate(SMTPTransport.java:858)
    at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:762)
    at jakarta.mail.Service.connect(Service.java:342)
    at jakarta.mail.Service.connect(Service.java:222)
    at jakarta.mail.Service.connect(Service.java:243)
    at Application.main(Application.java:52)

Я просмотрел следующий пример приложения, который нашел на github (https://github.com/eino-makitalo/vesa-mailtest/tree/master/src/main), и несколько ответов на stackoverflow на посмотрите, не пропустил ли я какие-либо свойства, которые нужно установить специально для SMTP, но я продолжаю сталкиваться с той же ошибкой, используя следующую конфигурацию:

        Properties props = new Properties();
        props.put("mail.smtp.auth.xoauth2.disable", "false");
        props.put("mail.smtp.auth.mechanisms", "XOAUTH2");
        props.put("mail.smtp.starttls.enable", "true");

        props.put("mail.smtp.host","smtp.office365.com");
        props.put("mail.smtp.port", "587");
        props.put("mail.transport.protocol","smtp");

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

        props.put("mail.debug.auth", "true");

        Session session = Session.getInstance(props);
        session.setDebug(true);

        Transport transport = session.getTransport("smtp");
        transport.connect( username, token);

Теперь я надеюсь, что, возможно, кто-то уже сталкивался с этой проблемой и может мне помочь. Единственные вопросы, которые я могу найти относительно сообщения об исключении выше, связаны с настройками пользовательских серверов обмена и тем, как вы должны настраивать настройку DNS на этих серверах. Но я не думаю, что это должно иметь значение для меня, так как я не пытаюсь подключиться к пользовательскому серверу обмена.

ОБНОВЛЯТЬ: Поэтому я попробовал ту же конфигурацию со службой Google, и она работает как для IMAP, так и для SMTP, так что это наверняка проблема со службами Microsoft. Но я все еще не уверен, что еще я могу попробовать, чтобы заставить его работать.

Привет, один вопрос: работает ли только серверная часть вашего Java-приложения или вы взаимодействуете с реальным пользователем при входе в систему для получения сообщений с использованием IMAP? Я имею дело с таким приложением, которое необходимо для получения почты с серверов Microsoft с использованием IMAP, работающего с почтой Джакарты, полностью бэкэнд без какого-либо взаимодействия с пользователем. Другое для любых конфигураций, с которыми я не хочу взаимодействовать с помощью Graph.

Michi 17.02.2021 08:13
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
1
2 883
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ладно, нашел проблему: Почему-то не догадался попробовать и явно запросить область действия openId. Не знаю почему, но мне почему-то пришло в голову, что он будет запрашиваться автоматически, если вы не укажете это явно. После явного запроса openId работают как SMTP, так и IMAP.

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