Могу я спросить, как использовать сервер электронной почты Outlook для отправки писем? Для просмотра документов требуется аутентификация личности.

Вопрос или проблема

Причина в том, что Microsoft ранее внесла изменения в аутентификацию электронной почты, что привело к сбою в отправке. При поиске ответов в Интернете необходимо применить регистрацию в Azure и добавить разрешения в соответствии с процессом ответа. После этих операций аутентификация не удалась при использовании аутентификации OAuth2. Кодовые шаги, используемые для сравнения ответов, полностью совпадают, но неясно, настроен ли вопрос в Azure или что-то другое.

Вот код:

package com.tianrun.common.email;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Properties;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class OAuth2Helper {
    public static void main(String[] args) throws Exception {
        String accessToken = getAccessToken();
        sendEmail(accessToken, "****@outlook.com", "******", "Тема", "Тело письма");
    }

    private static String getAccessToken() throws Exception {
        String clientId = "****";
        String clientSecret = "****";
        String tenantId = "*****";
        String scope = "https://outlook.office365.com/.default";

        String authUrl = "https://login.microsoftonline.com/" + tenantId + "/oauth2/v2.0/token";
        URL url = new URL(authUrl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        conn.setDoOutput(true);

        String postParams = "client_id=" + clientId +
                "&scope=" + scope +
                "&client_secret=" + clientSecret +
                "&grant_type=client_credentials";

        conn.getOutputStream().write(postParams.getBytes());

        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String inputLine;
        StringBuffer content = new StringBuffer();
        while ((inputLine = in.readLine()) != null) {
            content.append(inputLine);
        }
        in.close();
        conn.disconnect();

        // Разбор JSON-ответа для получения токена доступа
        String accessToken = content.toString().split("\"access_token\":\"")[1].split("\"")[0];
        System.out.println(accessToken);
        return accessToken;
    }

    private static void sendEmail(String accessToken, String sender, String recipient, String subject, String body)
            throws MessagingException {
        Properties props = new Properties();
        props.setProperty("mail.debug", "true");
        props.setProperty("mail.smtp.auth", "true");
        props.setProperty("mail.host", "smtp.office365.com");
        props.setProperty("mail.transport.protocol", "smtp");
        props.setProperty("mail.smtp.port", "587");
        props.put("mail.smtp.ssl.protocols", "TLSv1.2");
        props.put("mail.smtp.starttls.enable", "true");

        // Создание пользовательского аутентификатора с токеном доступа OAuth2

        Session session = Session.getInstance(props, null);

        Message message = new MimeMessage(session);
        message.setFrom(new InternetAddress(sender));
        message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipient));
        message.setSubject(subject);
        message.setText(body);

        Transport.send(message);
    }
}

Это журнал ошибок

javax.mail.AuthenticationfailedException: 535 5.7.3 Аутентификация не удалась [SI2PR6CA0e12.apcprd6.prod.outlook.com 224-11-1T96:16:51.8952 809172787151CE]

Ответ или решение

Как использовать сервер электронной почты Outlook для отправки писем с использованием OAuth2

Вопрос использования сервера электронной почты Outlook для отправки сообщений через OAuth2 становится всё более актуальным, особенно в условиях недавних изменений в процессе аутентификации от Microsoft. Рассмотрим основные шаги и возможные проблемы, с которыми вы можете столкнуться, а также приведем оптимальный код для отправки писем.

Шаг 1: Регистрация приложения в Azure

Перед тем как использовать OAuth2 для отправки электронной почты, необходимо зарегистрировать ваше приложение в Azure. Это позволит получить необходимые идентификаторы, такие как clientId, clientSecret и tenantId. Процесс регистрации включает следующие этапы:

  1. Перейдите в Azure Portal.
  2. Создайте новое приложение, выбрав "App registrations".
  3. Задайте имя приложения и выберите соответствующий тип учетной записи.
  4. В разделе "API permissions" добавьте разрешения для API Microsoft Graph, такие как Mail.Send.
  5. Убедитесь, что вы имеете назначенные разрешения Admin consent, если это необходимо.

Шаг 2: Получение токена доступа

Ваш код для получения токена выглядит основательно, однако важно убедиться, что в запросе включены правильные параметры и использован верный формат. Следует обратить внимание на следующую часть вашего кода:

String postParams = "client_id=" + clientId +
                    "&scope=" + scope + 
                    "&client_secret=" + clientSecret + 
                    "&grant_type=client_credentials";

Проверьте, что вы используете правильный scope и что все значения переменных корректны. Кроме того, имейте в виду, что в URL исключен аналог &, вам нужно использовать просто &.

Шаг 3: Отправка email через SMTP

Ваша настройка параметров электронной почты выглядит почти верно, однако аутентификация с использованием OAuth2 требует специального механизма. Вместо использования стандартной аутентификации, следует создать кастомный Authenticator, который будет принимать ваш токен доступа. Однако, в данной версии вашего кода это не реализовано.

Исправленный код отправки email

Убедитесь, что вы используете правильный подход для аутентификации с использованием токена. Вот оптимизированный фрагмент для отправки сообщения:

private static void sendEmail(String accessToken, String sender, String recipient, String subject, String body) 
        throws Exception {
    Properties props = new Properties();
    props.setProperty("mail.smtp.auth", "true");
    props.setProperty("mail.smtp.host", "smtp.office365.com");
    props.setProperty("mail.smtp.port", "587");
    props.put("mail.smtp.starttls.enable", "true");

    Session session = Session.getInstance(props);

    // Здесь добавляем интеграцию OAuth2 для авторизации
    session.setDebug(true);

    Message message = new MimeMessage(session);
    message.setFrom(new InternetAddress(sender));
    message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipient));
    message.setSubject(subject);
    message.setText(body);

    // Для отправки необходимо указать токен в заголовках
    Transport transport = session.getTransport("smtp");
    transport.connect("smtp.office365.com", sender, accessToken);
    transport.sendMessage(message, message.getAllRecipients());
    transport.close();
}

Ошибки аутентификации

Ошибка javax.mail.AuthenticationFailedException: 535 5.7.3 Authentication unsuccessful указывает на проблемы с аутентификацией. Это может произойти из-за:

  • Неправильного токена доступа. Убедитесь, что вы получаете токен правильно.
  • Неверных параметров идентификации в Azure.
  • Недостаточных разрешений для вашего приложения. Проверьте, что все необходимые разрешения назначены и согласованы.

Заключение

Использование OAuth2 для отправки электронной почты через сервер Outlook является современным и безопасным подходом, однако требует тщательной настройки как в Azure, так и в самом коде. Следуя приведенным шагам и рекомендациям, вы сможете успешно настроить отправку писем без необходимости вводить пароли, основываясь на аутентификации через токены. Убедитесь, что используете актуальный и правильно настроенный код, чтобы избежать повторных ошибок аутентификации.

Оцените материал
Добавить комментарий

Капча загружается...