Рубрики
Без рубрики

Получайте электронные письма с помощью SubEthaSMTP и Spring Boot

Несколько лет назад мне нужно было написать Java-приложение, которое получает электронные письма и обрабатывает некоторые бизнес-запросы… Помеченный java, subethasmtp, springboot, электронная почта.

Несколько лет назад мне нужно было написать Java-приложение, которое получает электронные письма и обрабатывает в них некоторые бизнес-материалы. Это была непростая задача, так как я не нашел много информации. Из-за этого я решил, что однажды напишу об этом и, может быть, это могло бы помочь..

Доступен полный исходный код здесь .

Почему?

Вы бы спросили, зачем вам это нужно? Я бы сказал:

Бизнес-требования могут удивлять вас каждый день

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

  • Тестирование: Может быть хорошим вариантом для интеграционного тестирования возможностей электронной почты ваших сервисов/приложений ( Старый FakeSMTP является хорошим примером графического интерфейса)
  • Проанализируйте полученные электронные письма и извлеките некоторую конкретную информацию

Что?

SubEthaSMTP – это низкоуровневый API для написания практически любого приложения для приема почты SMTP.

Чтобы избежать долгой презентации истории, самая обновленная версия subethaedit SMTP – это форк от Davidmoten (большое спасибо ему за отличную работу и обновление этой библиотеки). Мы будем использовать эту вилку в этом посте.

Я думаю, что нет необходимости описывать, что такое Весенний ботинок в наши дни.

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

Отправить электронное письмо с помощью cURL

Ниже приведен пример отправки электронной почты на определенный почтовый сервер с такими параметрами, как от, получатель, авторизация и содержимое электронной почты.

curl --url 'smtp://localhost:25000' \                                     
  --mail-from 'customer-address@mail.com' \
  --mail-rcpt 'info@marketing.company.com' \
  --user 'superus3r:passw0rd' \
  -T <(echo -e 'From: customer-address@mail.com\nTo: info@marketing.company.com\nSubject: cURL Test\n\nHello, this is the content')

Зависимость от Субэта

Здесь мы добавляем зависимость maven от SMTP SubEtha.


    com.github.davidmoten
    subethasmtp
    5.2.4

Запустите встроенный SMTP-сервер

С помощью библиотеки очень легко запустить простой SMTP-сервер. Просто создайте/создайте экземпляр SMTP-сервера с правильными параметрами, такими как порт, и запустите этот экземпляр.

// Build the embedded SMTP server
SMTPServer smtpServer = SMTPServer.port(25000).build();
// Start server asynchronously 
smtpServer.start();

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

Для этого мы можем реализовать интерфейс SimpleMessageListener :

public class MarketingMailListener implements SimpleMessageListener {

    private static final String MARKETING_DOMAIN = "@marketing.company.com";

    /**
     * Do some business logic here
     */
    @Override
    public boolean accept(String from, String recipient) {
        return recipient != null && recipient.endsWith(MARKETING_DOMAIN);
    }

    @Override
    public void deliver(String from, String recipient, InputStream data) 
    throws TooMuchDataException, IOException {
        System.out.println("deliver message of MARKETING department");
        System.out.println("From : "+from);
        System.out.println("Recipient : "+recipient);
    }

Как вы можете видеть здесь, я добавил простое бизнес-правило внутри метода принять для обработки только электронных писем, отправленных в отдел маркетинга.

Метод accept отвечает за определение того, будет ли полученное сообщение обработано этим слушателем или нет.

Метод доставки отвечает за извлечение:

  • От : Адрес отправителя
  • Получатель : Адрес получателя
  • Данные : Это тип входного потока, из которого мы можем извлекать содержимое и соответствующую информацию, связанную с полученным электронным письмом, например: тема, текст, CC, вложения и прочее.

Давайте посмотрим, как мы можем извлечь содержимое электронного письма:

Преобразовать в MimeMessage

Мы можем извлекать содержимое из составного сообщения с типизированным содержимым, используя экземпляр MimeMessage.

public MimeMessage convertToMimeMessage(InputStream data) 
throws MessagingException {
        Session session = Session.getDefaultInstance(new Properties());
        try {
            return new MimeMessage(session, data);
        }catch (MessagingException e){
            throw new MessagingException();
        }
    }

Извлечение содержимого электронной почты

Чтобы извлечь содержимое электронной почты, мы создадим модель Полученное электронное письмо для облегчения обработки.

public class ReceivedEmail {

    private String subject;
    private String senderAddress;
    private String senderName;
    private String recipientAddress;
    private String recipientName;
    private String cc;
    private String bcc;
    private String contentType;
    private List attachments = new ArrayList();

    // Getters and setters
    // ...
}

Для простоты я использовал Строка для адреса получателя, CC и BCC но это может быть список адресов (пример в коде ).

Мы создаем специальный сервис для извлечения содержимого электронной почты, и метод извлечения может выглядеть следующим образом:

public ReceivedEmail extractReceivedEmail(InputStream data) throws Exception {
        ReceivedEmail receivedEmail = new ReceivedEmail();
        MimeMessage message;
        try {
            message = this.convertToMimeMessage(data);
            receivedEmail.setSubject(message.getSubject());
            receivedEmail.setSenderAddress(InternetAddress.toString(message.getFrom()));
            InternetAddress[] recipientAddresses = InternetAddress.parse(InternetAddress.toString(message.getAllRecipients()));
            receivedEmail.setRecipientAddress(InternetAddress.toString(recipientAddresses));
            receivedEmail.setRecipientName(recipientAddresses[0].getPersonal());
            receivedEmail.setContentType(message.getContentType());
            // Use here Apache library for parsing
            MimeMessageParser messageParser = new MimeMessageParser(message);
            messageParser.parse(); // very important to parse before getting data
            receivedEmail.setCc(messageParser.getCc().toString());
            receivedEmail.setBcc(messageParser.getBcc().toString());
            receivedEmail.setAttachments(messageParser.getAttachmentList());
            System.out.println(receivedEmail);
            return receivedEmail;
        } catch (Exception e) {
            throw new Exception();
        }
    }

Теперь у нас есть полноценный приемник электронной почты с минимальными строками кода.

Защищенный SMTP-сервер

Давайте сделаем еще один шаг, чтобы узнать, как мы можем защитить наш почтовый сервер.

Первое, что нужно сделать, это указать, что требуется аутентификация, и реализовать базовую аутентификацию с помощью имени пользователя и пароля.

this.smtpServer = SMTPServer
                .port(25000)
                .simpleMessageListener(marketingMsgListener)
                .requireAuth(true) // auth required
                .authenticationHandlerFactory(easyAuth) // implement type of auth
                .build();

Могут быть выполнены различные реализации authenticationhandlerfactory , я выбрал здесь, опять же для простоты, класс EasyAuthenticationHandlerFactory , для которого требуется реализация интерфейса UserNamePasswordValidator .

@Configuration
public class SimpleAuthValidatorImpl implements UsernamePasswordValidator {

    private final String CREDENTIALS_LOGIN = "superus3r";
    private final String CREDENTIALS_PASSWORD = "passw0rd";

    @Override
    public void login(String username, String password, MessageContext context) throws LoginFailedException {
        if(CREDENTIALS_LOGIN.equals(username) && CREDENTIALS_PASSWORD.equals(password)){
            System.out.println("Authenticated successfully");
        }else{
            System.err.println("Invalid authentication !");
            throw new LoginFailedException();
        }
    }
}

И вот как выглядит наша конфигурация SMTP-сервера :

@Configuration
public class SMTPServerConfig {

    private final SMTPServer smtpServer;
    private final SimpleMessageListener marketingMsgListener;
    private final UsernamePasswordValidator authValidator;
    private final EasyAuthenticationHandlerFactory easyAuth;

    public SMTPServerConfig(SimpleMessageListener marketingMsgListener) {
        authValidator = new SimpleAuthValidatorImpl();
        easyAuth = new EasyAuthenticationHandlerFactory(authValidator);
        this.marketingMsgListener = marketingMsgListener;

        this.smtpServer = SMTPServer
                .port(25000)
                .simpleMessageListener(this.marketingMsgListener)
                .requireAuth(true)
                .authenticationHandlerFactory(easyAuth)
                .build();

        this.smtpServer.start();
    }
}

Дополнительные параметры могут быть настроены в соответствии с вашими потребностями и улучшением вашего сервера SubEtha, я перечисляю их ниже, и вы можете попробовать изучить их, чтобы улучшить реализацию вашего почтового получателя.:

  • Максимальное количество подключений и время ожидания подключения
  • Поддержка TLS
  • Размер сообщений
  • Завершение работы SMTP-сервера
  • Тестирование

Я представил, как мы можем с помощью небольших строк кода написать приложение, которое может получать электронные письма, обрабатывать их и применять к ним некоторую магию с помощью SubEtha SMTP и Spring Boot.

Если у вас есть какие-либо вопросы или предложения, пожалуйста, оставьте свои комментарии ниже.

Спасибо за чтение и счастливого кодирования.

Исходный код: https://github.com/redamessoudi/subethasmtp-springboot .

Фотография в заголовке Лиам Труонг на Unsplash

Оригинал: “https://dev.to/reda/receive-emails-with-subetha-smtp-and-spring-boot-2b8”