В этом разделе описано, как отправлять электронную почту с помощью Spring Framework.
Spring Framework предоставляет вспомогательную библиотеку для отправки электронной почты, которая ограждает от специфики базовой почтовой системы и отвечает за низкоуровневую обработку ресурсов в пространстве клиента.
Пакет org.springframework.mail
– это пакет корневого уровня для средств поддержки электронной почты в Spring Framework. Центральным интерфейсом для отправки электронных писем является интерфейс MailSender
. Простой объект-значение, который инкапсулирует свойства простого электронного письма, такие как from
и to
(плюс многие другие) – это класс SimpleMailMessage
. Этот пакет также содержит иерархию проверяемых исключений, которые обеспечивают более высокий уровень абстракции поверх исключений почтовой системы более низкого уровня, при этом корневым исключением является MailException
. См. соответствующий javadoc для получения дополнительной информации о полнофункциональной иерархии почтовых исключений.
Интерфейс org.springframework.mail.javamail.JavaMailSender
привносит специализированные функции JavaMail, такие как поддержка MIME-сообщений, в интерфейс MailSender
(от которого он наследуется). JavaMailSender
также предусматривает интерфейс обратного вызова org.springframework.mail.javamail.MimeMessagePreparator
для подготовки MimeMessage
.
Использование
Предположим, что у нас есть бизнес-интерфейс под названием OrderManager
, как показано в следующем примере:
public interface OrderManager {
void placeOrder(Order order);
}
Далее предположим, что у нас есть требование, согласно которому необходимо создать сообщение электронной почты с номером заказа и отправить его клиенту, который разместил соответствующий заказ.
Базовое использование MailSender
и SimpleMailMessage
В следующем примере показано, как использовать MailSender
и SimpleMailMessage
для отправки электронного письма при оформлении заказа:
import org.springframework.mail.MailException;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
public class SimpleOrderManager implements OrderManager {
private MailSender mailSender;
private SimpleMailMessage templateMessage;
public void setMailSender(MailSender mailSender) {
this.mailSender = mailSender;
}
public void setTemplateMessage(SimpleMailMessage templateMessage) {
this.templateMessage = templateMessage;
}
public void placeOrder(Order order) {
// Проводим бизнес-расчеты...
// Вызываем взаимодействующие объекты для сохранения заказа...
/// Создаем безопасную для потока "копию" шаблонного сообщения и настраиваем ее
SimpleMailMessage msg = new SimpleMailMessage(this.templateMessage);
msg.setTo(order.getCustomer().getEmailAddress());
msg.setText(
"Dear " + order.getCustomer().getFirstName()
+ order.getCustomer().getLastName()
+ ", thank you for placing order. Your order number is "
+ order.getOrderNumber());
try {
this.mailSender.send(msg);
}
catch (MailException ex) {
// просто заносим в журнал и двигаемся дальше...
System.err.println(ex.getMessage());
}
}
}
В следующем примере показаны определения бинов для предыдущего кода:
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="mail.mycompany.example"/>
</bean>
<!-- это шаблонное сообщение, которое можно предварительно загрузить с состоянием по умолчанию -->
<bean id="templateMessage" class="org.springframework.mail.SimpleMailMessage">
<property name="from" value="customerservice@mycompany.example"/>
<property name="subject" value="Your order"/>
</bean>
<bean id="orderManager" class="com.mycompany.businessapp.support.SimpleOrderManager">
<property name="mailSender" ref="mailSender"/>
<property name="templateMessage" ref="templateMessage"/>
</bean>
Использование JavaMailSender
и MimeMessagePreparator
В этом разделе описана другая реализация OrderManager
, которая использует интерфейс обратного вызова MimeMessagePreparator
. В следующем примере свойство mailSender
имеет тип JavaMailSender
, что позволяет использовать JavaMail-класс MimeMessage
:
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessagePreparator;
public class SimpleOrderManager implements OrderManager {
private JavaMailSender mailSender;
public void setMailSender(JavaMailSender mailSender) {
this.mailSender = mailSender;
}
public void placeOrder(final Order order) {
// Проводим бизнес-расчеты...
// Вызываем взаимодействующие объекты для сохранения заказа...
MimeMessagePreparator preparator = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage) throws Exception {
mimeMessage.setRecipient(Message.RecipientType.TO,
new InternetAddress(order.getCustomer().getEmailAddress()));
mimeMessage.setFrom(new InternetAddress("mail@mycompany.example"));
mimeMessage.setText("Dear " + order.getCustomer().getFirstName() + " " +
order.getCustomer().getLastName() + ", thanks for your order. " +
"Your order number is " + order.getOrderNumber() + ".");
}
};
try {
this.mailSender.send(preparator);
}
catch (MailException ex) {
// просто заносим в журнал и двигаемся дальше...
System.err.println(ex.getMessage());
}
}
}
OrderManager
.Средства поддержки почты в Spring Framework поставляются со стандартной реализацией интерфейса JavaMail. Для получения дополнительной информации см. соответствующий javadoc.
Использование MimeMessageHelper
из JavaMail
Класс, который может пригодиться при работе с JavaMail-сообщениями, – это org.springframework.mail.javamail.MimeMessageHelper
, который избавляет от необходимости использовать перегруженный API JavaMail. Используя MimeMessageHelper
, довольно легко создать MimeMessage
, как показано в следующем примере:
// безусловно, в любых случаях реального применения будет использоваться внедрение зависимостей
JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setHost("mail.host.com");
MimeMessage message = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message);
helper.setTo("test@host.com");
helper.setText("Thank you for ordering!");
sender.send(message);
Отправка вложений и встроенных ресурсов
Многокомпонентные сообщения электронной почты позволяют использовать как вложения, так и встроенные ресурсы. Примеры встроенных ресурсов включают изображение или таблицу стилей, которые вы хотите использовать в своем сообщении, но не хотите, чтобы они отображались как вложение.
Вложения
В следующем примере показано, как использовать MimeMessageHelper
для отправки электронного письма с одним вложением изображения в формате JPEG:
JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setHost("mail.host.com");
MimeMessage message = sender.createMimeMessage();
// используем флаг true, чтобы указать, что вам требуется многокомпонентное сообщение
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo("test@host.com");
helper.setText("Check out this image!");
// прикрепляем пресловутый файл Sample (на этот раз скопированный в c:/)
FileSystemResource file = new FileSystemResource(new File("c:/Sample.jpg"));
helper.addAttachment("CoolImage.jpg", file);
sender.send(message);
Встроенные ресурсы
В следующем примере показано, как использовать MimeMessageHelper
для отправки электронного письма со встроенным изображением:
JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setHost("mail.host.com");
MimeMessage message = sender.createMimeMessage();
// используем флаг true, чтобы указать, что вам требуется многокомпонентное сообщение
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo("test@host.com");
// используем флаг true, чтобы указать, что включенный текст является HTML
helper.setText("<html><body><img src='cid:identifier1234'></body></html>", true);
// давайте используем пресловутый файл Sample (на этот раз скопированный в c:/)
FileSystemResource res = new FileSystemResource(new File("c:/Sample.jpg"));
helper.addInline("identifier1234", res);
sender.send(message);
MimeMessage
с помощью указанного Content-ID
(identifier1234
в приведенном выше примере). Порядок, в котором добавляется текст и ресурс, крайне важен. Обязательно добавляйте сначала текст, а затем ресурсы. Если сделать все наоборот, то ничего не сработает.Создание содержимого электронной почты с помощью библиотеки шаблонов
Код в примерах, показанных в предыдущих разделах, явным образом создавал содержимое почтового сообщения, используя вызовы методов, таких как message.setText(..)
. Это нормально для простых случаев, и это нормально в контексте вышеупомянутых примеров, где целью было показать самые основы API-интерфейса.
Однако в типичном корпоративном приложении разработчики зачастую не создают содержимое почтовых сообщений с помощью показанного ранее подхода по ряду причин:
-
Создание почтового контента на основе HTML в коде Java является громоздким и чревато ошибками.
-
Нет четкого разделения между логикой вывода на экран и бизнес-логикой.
-
Изменение структуры отображения содержимого электронной почты требует написания Java-кода, перекомпиляции, повторного развертывания и так далее.
Обычно для решения этих проблем используется библиотека шаблонов (например, FreeMarker) для определения структуры вывода на экран содержимого электронной почты. Задачей кода остается лишь создание данных, которые будут визуализированы в шаблоне электронной почты, и отправка письма. Это определенно наиболее оптимальный метод, если содержание почтовых сообщений становится даже умеренно сложным, и с помощью вспомогательных классов FreeMarker в Spring Framework сделать все становится довольно просто.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ