Главная » Spring » Создание электронных писем Spring

0

По условиям задачи нам требуется организовать отправку поль- зователям приложения Spitter электронных писем, чтобы известить их о появлении новых сообщений, поэтому нам необходим некото- рый метод, который будет получать адрес электронной почты и объ- ект Spittle и отправлять электронное письмо. Таким методом будет sendSimpleSpittleEmail(), представленный в листинге 17.1.

Листинг 17.1. Отправка электронной почты с использованием реализации MailSender

public  void  sendSimpleSpittleEmail(String  to, Spittle spittle) { SimpleMailMessage message = new SimpleMailMessage();  // Создать письмо

String  spitterName  =  spittle.getSpitter().getFullName(); message.setFrom("noreply@spitter.com");                    // Обратный адрес message.setTo(to);

message.setSubject("New  spittle  from  "  +  spitterName);

message.setText(spitterName  +  "  says:  "  +                      // Текст  письма spittle.getText());

mailSender.send(message);                                             // Отправить

}

Первое, что делает метод sendSimpleSpittleEmail(), – конструирует экземпляр класса SimpleMailMessage. Это объект электронного пись- ма, как следует из его имени, прекрасно подходящий для отправки деловых сообщений.

Далее он определяет параметры сообщения. Адреса отправителя и получателя определяются с помощью методов setFrom() и setTo() объ- екта письма. После определения темы вызовом метода setSubject() виртуальный «конверт» готов к отправке. Остается только вызвать метод setText(), чтобы добавить текстовое содержимое.

В заключение выполняется отправка письма вызовом метода

send() компонента, отвечающего за отправку.

Простые электронные письма великолепно подходят на началь- ном этапе. Но как быть, если позднее потребуется добавлять в них вложения? Или что, если у вас появится желание придать тексту письма более привлекательное оформление? Посмотрим, как с по- мощью Spring можно принарядить наши электронные письма, начав с добавления вложений.

Добавление вложений

Вся хитрость отправки электронных писем с вложениями за- ключается в создании составных сообщений – электронных писем, содержащих несколько частей, одна из которых играет роль тела письма, а остальные являются вложениями.

Класс SimpleMailMessage слишком… как бы это сказать… слишком прост, чтобы с его помощью отправлять вложения. Чтобы отпра- вить составное электронное письмо, необходимо создать MIME- сообщение (Multipurpose Internet Mail Extensions – многоцелевые расширения электронной почты Интернета). Для этого можно вос- пользоваться методом createMimeMessage() объекта, реализующего от- правку электронной почты:

MimeMessage message = mailSender.createMimeMessage();

Поехали! Теперь у нас есть заготовка MIME-сообщения. На пер- вый взгляд может показаться, что достаточно просто определить адреса отправителя и получателя, тему сообщения, добавить неко- торый текст и вложения. В принципе, так оно и есть, но не все так просто. Прикладной интерфейс класса javax.mail.internet.MimeMessage слишком сложен, чтобы его можно было использовать без посто- ронней помощи. К счастью, в Spring имеется класс MimeMessageHelper, оказывающий такую помощь.

Чтобы воспользоваться услугами класса MimeMessageHelper, необ- ходимо создать его экземпляр, передав его конструктору объект MimeMessage:

MimeMessageHelper  helper  =  new  MimeMessageHelper(message,  true);

Значение true, передаваемое конструктору во втором параметре, сообщает ему, что это сообщение является составным сообщением.

Получив экземпляр MimeMessageHelper, можно приступать к сборке электронного письма. Единственное существенное отличие состоит в том, что конструирование выполняется с помощью метода вспо- могательного объекта, а не самого сообщения:

String   spitterName   =   spittle.getSpitter().getFullName(); helper.setFrom("noreply@spitter.com");

helper.setTo(to);

helper.setSubject("New  spittle  from  "  +  spitterName); helper.setText(spitterName   +   "   says:   "   +   spittle.getText());

Единственное, что осталось сделать перед отправкой письма, – вложить изображение купона. Для этого необходимо загрузить изо- бражение как ресурс и передать его методу addAttachment() вспомо- гательного объекта:

FileSystemResource   couponImage   =

new      FileSystemResource("/collateral/coupon.png"); helper.addAttachment("Coupon.png", couponImage);

Здесь сначала выполняется загрузка файла coupon.png из библио- теки классов приложения (classpath) с помощью объекта FileSystem- Resource, а затем вызывается метод addAttachment(). В первом парамет- ре методу передается имя вложения, а во втором – ресурс с изо- бражением.

Составное электронное письмо сконструировано. Теперь его мож- но отправить. Полная версия метода sendSpittleEmailWithAttachment() представлена в листинге 17.2.

Листинг 17.2. Класс MimeMessageHelper упрощает создание электронных писем с вложениями

public void sendSpittleEmailWithAttachment(

String  to,  Spittle  spittle)  throws  MessagingException  { MimeMessage message = mailSender.createMimeMessage(); MimeMessageHelper helper =

new MimeMessageHelper(message, true);            // Создание письма

String   spitterName   =   spittle.getSpitter().getFullName(); helper.setFrom("noreply@spitter.com");

helper.setTo(to);

helper.setSubject("New  spittle  from  "  +  spitterName); helper.setText(spitterName   +   "   says:   "   +   spittle.getText());

FileSystemResource   couponImage   =

new  FileSystemResource("/collateral/coupon.png"); helper.addAttachment("Coupon.png", couponImage);   // Вложение

mailSender.send(message);

}

Добавление вложений в электронные письма – это лишь одна из возможностей, поддерживаемых составными сообщениями. Поми- мо этого, они позволяют определять тело письма в формате HTML,

имеющем более привлекательное оформление, чем простой текст. Посмотрим, как отправлять письма с текстом в формате HTML с помощью объекта MimeMessageHelper.

Отправка электронных писем с текстом в формате HTML

Отправка электронных писем с содержимым в формате HTML практически не отличается от отправки писем с содержимым в прос- том текстовом формате. Для этого необходимо лишь записать текст письма в формате HTML, просто передав строку с разметкой HTML методу setText() вспомогательного объекта и значения true во вто- ром параметре:

helper.setText("<html><body><img   src=’cid:spitterLogo’>"   +

"<h4>"   +   spittle.getSpitter().getFullName()   +   "   says…</h4>"   + "<i>"   +   spittle.getText()   +   "</i>"   +

"</body></html>",  true);

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

Обратите внимание, что разметка HTML в данном примере содер- жит тег <img>, отображающий логотип приложения Spitter в тексте письма. Чтобы получить логотип из Всемирной паутины, в атрибуте src можно указать полный URL http:. Но в данном случае в текст письма внедряется сам логотип. Значение cid:spitterLogo указывает, что изображение содержится в одной из частей письма, с иденти- фикатором spitterLogo.

Добавление встроенного изображения в сообщение во многом на- поминает добавление вложения. Только вместо метода addAttachment() вспомогательного объекта вызывается метод addInline():

ClassPathResource  image  =  new  ClassPathResource("spitter_logo_50.png"); helper.addInline("spitterLogo",        image);

Первый параметр метода addInline() определяет идентификатор встроенного изображения, совпадающий с идентификатором, ука- занным в атрибуте src тега <img>. Во втором параметре передается ссылка на ресурс с изображением, созданным здесь с помощью объ- екта ClassPathResource, который извлекает изображение из библиоте- ки классов приложения.

Кроме немного отличающегося вызова метода setText() и исполь- зования метода addInline(), отправка писем с текстом в формате HTML ничем не отличается от отправки простых текстовых писем с вложениями. Для сравнения ниже представлена новая версия ме- тода   sendRichSpitterEmail().

public  void  sendRichSpitterEmail(String  to,  Spittle  spittle) throws MessagingException {

MimeMessage message = mailSender.createMimeMessage(); MimeMessageHelper  helper  =  new  MimeMessageHelper(message,  true); helper.setFrom("noreply@spitter.com"); helper.setTo("craig@habuma.com");

helper.setSubject("New  spittle  from  "  + spittle.getSpitter().getFullName());

helper.setText("<html><body><img src=’cid:spitterLogo’>" + // HTML-текст "<h4>"  +  spittle.getSpitter().getFullName()  +  "  says…</h4>"  + "<i>"  +  spittle.getText()  +  "</i>"  +

"</body></html>",  true);

ClassPathResource  image  =  new  ClassPathResource("spitter_logo_50.png"); helper.addInline("spitterLogo",  image);          // Встроенное  изображение mailSender.send(message);

}

Теперь у вас есть возможность отправлять электронные письма с текстом в формате HTML и встроенными изображениями! На этом можно остановиться и объявить о завершении реализации от- правки электронных писем. Но мне кажется ошибкой составление тела письма с применением операции конкатенации строк. Прежде чем оставить тему электронной почты, посмотрим, как избавиться от операций конкатенации строк с помощью шаблонов сообщений.

Создание шаблонов электронных писем

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

Нам необходим способ, позволяющий выразить форматирование письма в виде HTML-шаблона и затем преобразовать этот шаблон в строку для передачи методу setText() вспомогательного объекта. Когда речь заходит о преобразовании шаблонов в строки, в числе од- них из лучших инструментов называют процессор шаблонов Apache Velocity1.

Чтобы задействовать процессор Velocity для форматирования электронных писем, сначала необходимо внедрить объект Velocity- Engine в компонент SpitterEmailServiceImpl. Для этой цели в Spring имеется удобный фабричный компонент VelocityEngineFactoryBean, создающий объекты VelocityEngine в контексте приложения Spring. Объявление VelocityEngineFactoryBean выглядит, как показано ниже:

<bean  id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">

<property name="velocityProperties">

<value>

resource.loader=class class.resource.loader.class=

org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader

</value>

</property>

</bean>

Единственное свойство, требующее настройки в компоненте VelocityEngineFactoryBean, – это свойство velocityProperties. В данном случае он настраивается на загрузку шаблонов Velocity из библио- теки классов (за более подробной информацией о настройке про- цессора Velocity обращайтесь к документации).

Теперь процессор Velocity можно внедрить в SpitterEmailServiceImpl. Поскольку компонент SpitterEmailServiceImpl автоматически регист- рируется сканером компонентов, для автоматического связывания его  свойства  velocityEngine    можно  воспользоваться  аннотацией

@Autowired:

@Autowired

VelocityEngine velocityEngine;

После настройки свойства velocityEngine с его помощью можно выполнить преобразование шаблона Velocity в строку для отправки

1   http://velocity.apache.org.

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

Map<String, String> model = new HashMap<String, String>(); model.put("spitterName",  spitterName); model.put("spittleText",         spittle.getText());

String   emailText   =   VelocityEngineUtils.mergeTemplateIntoString( velocityEngine,  "emailTemplate.vm",  model  );

Подготовка к обработке шаблона начинается с создания отобра- жения (Map) для хранения данных модели, используемой шаблоном. В предыдущей версии, использующей конкатенацию строк, нам не- обходимы были полное имя пользователя и текст его сообщения, следовательно, эта же информация потребуется и здесь. После этого, чтобы сконструировать текст электронного письма, достаточно прос- то вызвать метод mergeTemplateIntoString() класса VelocityEngineUtils, передав ему процессор Velocity, путь к шаблону (относительно кор- ня библиотеки классов) и отображение модели.

Все, что осталось сделать, – передать получившийся текст письма методу setText()  вспомогательного объекта:

helper.setText(emailText, true);

Сам шаблон хранится в корневом каталоге библиотеки классов (classpath), в файле с именем emailTemplate.vm, содержащем следую- щие строки:

<html>

<body>

<img   src=’cid:spitterLogo’>

<h4>${spitterName}  says…</h4>

<i>${spittleText}</i>

</body>

</html>

Как видите, содержимое файла шаблона читается намного про- ще, чем его версия в программном коде на Java. Следовательно, его проще будет сопровождать и изменять. На рис. 17.5 показано, как выглядит электронное письмо, созданное с его помощью.

Рис. 17.5. С помощью шаблона Velocity

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

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

У нас осталась еще одна весьма привлекательная особенность фреймворка Spring, которую я оставил на сладкое! Посмотрим, как с помощью Spring организовать выполнение коротких заданий в фо- новом режиме.

Источник:   Уоллс К., Spring в действии. – М.: ДМК Пресс, 2013. – 752 с.: ил.

По теме:

  • Комментарии