1. Обзор
В этом руководстве мы рассмотрим шаги, необходимые для отправки электронных писем как из простого ванильного приложения Spring, так и из приложения Spring Boot. В первом случае мы будем использовать библиотеку JavaMail , а во втором — зависимость spring-boot-starter-mail .
2. Зависимости Maven
Во-первых, нам нужно добавить зависимости в наш pom.xml
.
2.1. Весна
Вот что мы добавим для использования в простом ванильном фреймворке Spring:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
Последнюю версию можно найти здесь .
2.2. Весенний ботинок
И для весенней загрузки:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>2.5.6</version>
</dependency>
Последняя версия доступна в репозитории Maven Central .
3. Свойства почтового сервера
Интерфейсы и классы для поддержки почты Java в среде Spring организованы следующим образом:
Интерфейс MailSender
: интерфейс верхнего уровня, предоставляющий базовые функции для отправки простых электронных писем.- `
Интерфейс
JavaMailSender` : субинтерфейс вышеупомянутогоMailSender
. Он поддерживает сообщения MIME и в основном используется вместе склассом MimeMessageHelper
для созданияMimeMessage
. С этим интерфейсом рекомендуется использоватьмеханизм MimeMessagePreparator .
- `
Класс
JavaMailSenderImpl` предоставляет реализацию интерфейсаJavaMailSender .
Он поддерживаетMimeMessage
иSimpleMailMessage
. - `
Класс
SimpleMailMessage` : используется для создания простого почтового сообщения, включая поля «от», «кому», «копия», «тема» и «текст». Интерфейс MimeMessagePreparator
предоставляет интерфейс обратного вызова для подготовки сообщений MIME.- `
Класс
MimeMessageHelper` : вспомогательный класс для создания сообщений MIME. Он предлагает поддержку изображений, типичных почтовых вложений и текстового содержимого в макете HTML.
В следующих разделах мы покажем, как использовать эти интерфейсы и классы.
3.1. Свойства почтового сервера Spring
Свойства почты, необходимые для указания, например, SMTP-сервера, могут быть определены с помощью JavaMailSenderImpl
.
Для Gmail это можно настроить, как показано ниже:
@Bean
public JavaMailSender getJavaMailSender() {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost("smtp.gmail.com");
mailSender.setPort(587);
mailSender.setUsername("my.gmail@gmail.com");
mailSender.setPassword("password");
Properties props = mailSender.getJavaMailProperties();
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.debug", "true");
return mailSender;
}
3.2. Свойства почтового сервера Spring Boot
После создания зависимости следующим шагом будет указание свойств почтового сервера в файле application.properties
с использованием пространства имен spring.mail.* .
Мы можем указать свойства для SMTP-сервера Gmail следующим образом:
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=<login user to smtp server>
spring.mail.password=<login password to smtp server>
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
Некоторым SMTP-серверам требуется TLS-соединение, поэтому мы используем свойство spring.mail.properties.mail.smtp.starttls.enable
, чтобы включить TLS-защищенное соединение.
3.2.1. Свойства SMTP Gmail
Мы можем отправить электронное письмо через SMTP-сервер Gmail. Просмотрите документацию , чтобы увидеть свойства SMTP-сервера исходящей почты Gmail.
Наш файл application.properties
уже настроен на использование SMTP Gmail (см. предыдущий раздел).
Обратите внимание, что пароль для нашей учетной записи должен быть не обычным паролем, а паролем приложения, сгенерированным для нашей учетной записи Google. Перейдите по этой ссылке , чтобы просмотреть подробности и сгенерировать пароль для приложения Google.
3.2.2. Свойства SES SMTP
Чтобы отправлять электронные письма с помощью Amazon SES, мы устанавливаем наш application.properties
:
spring.mail.host=email-smtp.us-west-2.amazonaws.com
spring.mail.username=username
spring.mail.password=password
spring.mail.properties.mail.transport.protocol=smtp
spring.mail.properties.mail.smtp.port=25
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
Имейте в виду, что Amazon требует от нас проверки наших учетных данных перед их использованием. Перейдите по ссылке , чтобы подтвердить свое имя пользователя и пароль.
4. Отправка электронной почты
После того, как управление зависимостями и настройка настроены, мы можем использовать вышеупомянутый JavaMailSender
для отправки электронной почты.
Поскольку как обычная ванильная среда Spring, так и ее загрузочная версия одинаково обрабатывают создание и отправку электронных писем, нам не придется различать их в подразделах ниже.
4.1. Отправка простых писем
Давайте сначала составим и отправим простое сообщение электронной почты без каких-либо вложений:
@Component
public class EmailServiceImpl implements EmailService {
@Autowired
private JavaMailSender emailSender;
public void sendSimpleMessage(
String to, String subject, String text) {
...
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom("noreply@foreach.com");
message.setTo(to);
message.setSubject(subject);
message.setText(text);
emailSender.send(message);
...
}
}
Обратите внимание, что хотя указывать адрес отправителя не обязательно ,
многие SMTP-серверы будут отклонять такие сообщения. Вот почему мы используем адрес электронной почты noreply@foreach.com в нашей реализации EmailService
. ``
4.2. Отправка писем с вложениями
Иногда простого обмена сообщениями Spring недостаточно для наших случаев использования.
Например, мы хотим отправить электронное письмо с подтверждением заказа с прикрепленным счетом-фактурой. В этом случае мы должны использовать составное сообщение MIME из библиотеки
JavaMail
вместо SimpleMailMessage
. Spring поддерживает обмен сообщениями JavaMail
с классом org.springframework.mail.javamail.MimeMessageHelper
.
Прежде всего, мы добавим в EmailServiceImpl
метод для отправки электронных писем с вложениями:
@Override
public void sendMessageWithAttachment(
String to, String subject, String text, String pathToAttachment) {
// ...
MimeMessage message = emailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom("noreply@foreach.com");
helper.setTo(to);
helper.setSubject(subject);
helper.setText(text);
FileSystemResource file
= new FileSystemResource(new File(pathToAttachment));
helper.addAttachment("Invoice", file);
emailSender.send(message);
// ...
}
4.3. Простой шаблон электронной почты
Класс SimpleMailMessage
поддерживает форматирование текста.
Мы можем создать шаблон для электронных писем, определив bean-компонент шаблона в нашей конфигурации:
@Bean
public SimpleMailMessage templateSimpleMessage() {
SimpleMailMessage message = new SimpleMailMessage();
message.setText(
"This is the test email template for your email:\n%s\n");
return message;
}
Теперь мы можем использовать этот bean-компонент в качестве шаблона для электронной почты, и нам нужно только указать необходимые параметры для шаблона:
@Autowired
public SimpleMailMessage template;
...
String text = String.format(template.getText(), templateArgs);
sendSimpleMessage(to, subject, text);
5. Обработка ошибок отправки
JavaMail
предоставляет SendFailedException
для обработки ситуаций, когда сообщение не может быть отправлено. Но возможно, что мы не получим это исключение при отправке письма на неправильный адрес. Причина в следующем:
Спецификации протокола для SMTP в RFC 821 определяют код возврата 550, который SMTP-сервер должен возвращать при попытке отправить электронное письмо на неправильный адрес. Но большинство общедоступных SMTP-серверов этого не делают. Вместо этого они отправляют электронное письмо «ошибка доставки» или вообще не дают отзывов.
Например, SMTP-сервер Gmail отправляет сообщение «ошибка доставки». И у нас нет исключений в нашей программе.
Итак, у нас есть несколько вариантов решения этой проблемы:
Перехватите SendFailedException
, которое никогда не может быть выброшено.- Проверьте наш почтовый ящик отправителя на наличие сообщения «доставка не удалась» в течение некоторого периода времени. Это не просто, и период времени не определен.
- Если наш почтовый сервер не дает никакой обратной связи, мы ничего не можем сделать.
6. Заключение
В этой быстрой статье мы показали, как настраивать и отправлять электронные письма из приложения Spring Boot.
Реализацию всех этих примеров и фрагментов кода можно найти на GitHub .