Spring Mail + Spring Boot – łatwe wysyłanie maili z aplikacji w Javie

Spring Mail

Duża ilość tworzonych aplikacji potrzebuje w którymś momencie wysłać maila do użytkownika. Czy to maila rejestracyjnego, czy jakieś inne powiadomienie dla użytkownika. W Spring Boocie jest do tego odpowiedni moduł (Spring Boot Starter Mail) który nam to bardzo ułatwia. W tym poście przedstawię jak go skonfigurować i użyć w przykładowym projekcie.

Kod użyty w postach dostępny jest w repozytorium GitHub pod adresem:

https://github.com/mloza/spring-boot-mail

Przygotowanie

Aby móc zacząć wysyłać wiadomości e-mail potrzebujemy dodać do naszych zależności spring-boot-starter-mail. Następnie musimy skonfigurować dostęp do serwera pocztowego, możemy użyć własnego konta pocztowego na przykład na GMailu lub usługi takiej jak Amazon SES (Simple Email Service).

Zależności

Aby zacząć pracę z mailami, dodajemy do pom.xml spring-boot-starter-mail. Będę wykorzystywał też RESTa do uruchomienia przykładów więc od razu dodałem również spring-boot-starter-web. Cały pom.xml wygląda następująco:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>pl.mloza</groupId>
<artifactId>spring-mail</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<type>pom</type>
<version>2.1.6.RELEASE</version>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.2</version>
<configuration>
<source>10</source>
<target>10</target>
<release>10</release>
</configuration>
</plugin>
</plugins>
</build>
</project>
view raw pom.xml hosted with ❤ by GitHub

Konfiguracja

Aby połączyć się do serwera pocztowego musimy dodać konfigurację w application.properties. Podajemy tam adres serwera, użytkownika oraz hasło. Dodatkowo powinniśmy ustawić aby połączenie było szyfrowane.

Konfiguracja Gmaila

Przykładowa konfiguracja dla gmaila wygląda następująco:

spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=<twój e-mail>
spring.mail.password=<hasło aplikacji>
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true

Jeśli używasz podwójnej weryfikacji w google, musisz wygenerować hasło aplikacji. Instrukcję jak to zrobić, możesz znaleźć na stronie pomocy Google: https://support.google.com/mail/answer/185833?hl=pl. W takim przypadku podajesz wygenerowane hasło zamiast hasła do Twojej skrzynki pocztowej.

Konfiguracja Amazon SES

Dla Amazon SES konfiguracja wygląda podobnie:

spring.mail.host=email-smtp.us-east-1.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

Należy pamiętać o wybraniu odpowiedniego regionu w polu host. Nazwę użytkownika i hasło generujemy w konsoli Amazonowej, która od razu nada odpowiednie uprawnienia dla wygenerowanego użytkownika. Jeśli chcemy wysyłać e-maile z różnych regionów, musimy wygenerować unikalne dane dla każdego regionu. Więcej na temat generowania danych użytkownika możesz przeczytać na stronie amazona pod adresem: https://docs.aws.amazon.com/ses/latest/DeveloperGuide/smtp-credentials.html

Wysyłanie prostego maila tekstowego

Aby wysłać maila musimy stworzyć odpowiedni serwis oraz kontroler który wywoła dla nas odpowiednią metodę serwisu po przejściu na wskazany URL.

Tworzymy email serwis

Cały kod serwisu możesz zobaczyć poniżej:

@Service
public class MailService {
private JavaMailSender javaMailSender; // 1
public MailService(JavaMailSender javaMailSender) {
this.javaMailSender = javaMailSender;
}
public void sendSimpleEmail(String to, String subject, String content) {
SimpleMailMessage msg = new SimpleMailMessage();
msg.setTo(to);
msg.setFrom("Blog Example <from@email.com>");
msg.setSubject(subject);
msg.setText(content);
javaMailSender.send(msg);
}
}
view raw MailService.java hosted with ❤ by GitHub

Do naszego serwisu zostaje automatycznie wstrzyknięty skonfigurowany już JavaMailSender. Następnie tworzymy sobie SimpleMailMessage, ustawiamy tytuł, adresata, zawartość wiadomości i wywołujemy send(msg). I to wystarczy aby wysłać prostą wiadomość email.

Kontroler wykorzystujący email serwis

Aby sprawdzić działanie naszego serwisu, stworzymy sobie kontroler który wywoła nam metodę sendSimpleEmail naszego serwisu i wyśle do nas wiadomość.

@RestController
public class MailController {
private MailService mailService;
public MailController(MailService mailService) {
this.mailService = mailService;
}
@GetMapping("/sendemail")
public String sendEmail() {
mailService.sendSimpleEmail("Odbiorca <odbiorca@maila.pl>", "Test e-mail", "Testing email functionality");
return "E-mail sent!";
}
}
view raw MailController.java hosted with ❤ by GitHub

Tutaj już nie ma żadnej magii. Wstrzykujemy wcześniej stworzony serwis i wywołujemy metodę wysyłającą podając adresata, temat i zawartość emaila. Zauważ tylko, że adres możesz podać w formacie: nazwa odbiorcy <adres@email.pl>. Tak samo możesz podać adres nadawcy, dzięki temu w skrzynce odbiorczej adresata będzie widoczna podana nazwa, a nie tylko adres. Odbiorca będzie mógł też zobaczyć swoją nazwę w wiadomości 😉

Po uruchomieniu aplikacji i przejściu na stronę http://localhost:8080/sendemail wiadomość zostanie wysłana. W skrzynce odbiorczej powinna wyglądać mniej więcej tak jak na poniższym obrazku.

Spring Mail
Mail wysłany przez Spring Boot Mail

Wysyłanie maili w formacie HTML

Wysyłanie maili w formacie HTML jest tylko nieco bardziej skomplikowane niż wysyłanie prostych maili. Dodajmy do naszego serwisu kolejną metodę: sendHtmlEmail.

public void sendHtmlEmail(String to, String subject, String content) {
MimeMessage mail = javaMailSender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(mail, true);
helper.setTo(to);
helper.setFrom("Blog example <from@email.com>");
helper.setSubject(subject);
helper.setText(content, true);
} catch (MessagingException e) {
e.printStackTrace();
}
javaMailSender.send(mail);
}
view raw HtmlMailService.java hosted with ❤ by GitHub

Zamiast SimpleMailMessage używamy Message i przy wstawianiu zawartości w metodzie setText jako 2 argument podajemy true, co mówi nam, że będzie to wiadomość HTML. Musimy również obsłużyć wyjątek MesaagingException. Po tych zabiegach możemy wysłać wiadomość HTML.

Szablony HTML JTwig

Umiemy już wysyłać wiadomości w formacie HTML. Jednak jeśli chcemy stworzyć większą wiadomość, nie chcemy jej trzymać w kodzie klasy. Dodatkowo fajnie by było jakoś łatwo podmieniać zmienne w treści wiadomości. Ja do tego celu używam silnika szablonów JTwig. (Pisałem o nim szerzej w poście o widokach Springowych). Tutaj pokażę jak go wykorzystać przy wysyłaniu e-maili.

Zależności Mavena

Przed przystąpieniem do pracy z szablonami, musimy dodać odpowiednie zależności do pom.xml.

<dependency>
<groupId>org.jtwig</groupId>
<artifactId>jtwig-core</artifactId>
<version>5.87.0.RELEASE</version>
</dependency>
view raw pom2.xml hosted with ❤ by GitHub

Szablon HTML

Mając już zależności na miejscu, możemy przygotować sobie wiadomość którą będziemy chcieli wysyłać. Załóżmy, że znamy imię naszego użytkownika i chcielibyśmy go użyć aby się przywitać. Następnie dodamy ładny przycisk i podpis. Musimy pamiętać, że większość klientów pocztowych obsługuje tylko część HTML, do tego narzuca spore ograniczenia jeśli chodzi o style itp. Jeśli będziesz chciał tworzyć skomplikowane wiadomości polecam doczytać więcej na ten temat. Mój szablon wygląda następująco.

<h1>Cześć {{ username }}</h1>
<p>To jest przykładowy e-mail!</p>
<p>
<a href="https://blog.mloza.pl" target="_blank" style="display: inline-block; color: #ffffff; background-color: #3498db;
border: solid 1px #3498db; border-radius: 5px; box-sizing: border-box; cursor: pointer; text-decoration: none;
font-size: 14px; font-weight: bold; margin: 0 auto; padding: 12px 25px; border-color: #3498db;">Podoba mi siÄ™!</a>
</p>
--<br>
Pozdrawiam!<br>
Michał z blog.mloza.pl
view raw email.html hosted with ❤ by GitHub

Najważniejszą rzeczą na którą powinieneś zwrócić uwagę jest fragment: {{ username }}. W ten sposób możemy wstawiać zmienne do szablonu. Wiadomość zapisujemy w katalogu resources, stamtąd będziemy ją mogli łatwo odczytać. Teraz musimy dodać do kontrolera kod, który wczyta nam szablon, ustawi zmienne i wygeneruje wiadomość.

Wysyłanie wiadomości

Dodajmy kolejną funkcję na nowym endpoincie która wyśle naszą wiadomość. Będzie ona wyglądać jak poniżej.

@GetMapping("/sendhtmlemail")
public String sendHtmlEmail() {
JtwigTemplate emailTemplate = JtwigTemplate.classpathTemplate("email/htmlEmail.twig");
JtwigModel model = JtwigModel.newModel()
.with("username", "Michał");
String emailMessage = emailTemplate.render(model);
mailService.sendHtmlEmail("Michal <michal@mloza.pl>", "Test e-mail", emailMessage);
return "E-mail sent!";
}
view raw SendHtmlEmail.java hosted with ❤ by GitHub

Kod jest bardzo krótki. Na początku wczytujemy nasz szablon podając lokalizację. Ja trzymam szablony w katalogu resources/email. Następnie tworzymy model który będzie przechowywał nasze zmienne do użycia w szablonie. Ostatnim elementem jest wywołanie funkcji render na wiadomości, która zwróci nam wiadomośc z podstawionymi zmiennymi. Możemy w tym momencie użyć naszej funkcji sendHtmlEmail z MailService do wysłania wiadomości. Otrzymana wiadomość powinna wyglądać jak na poniższym obrazku.

Wiadomość HTML
Wygenerowana wiadomość HTML

Podsumowanie

W ten prosty sposób możemy wysyłać wiadomości do naszych użytkowników. Użycie szablonów JTwig pomaga nam utrzymać porządek w kodzie i jest bardzo wygodne. Istnieje wiele alternatyw dla nich jak na przykład: Thymeleaf czy Mustache. Niestety trzeba bardzo uważać przy tworzeniu wiadomości ponieważ mamy wielu klientów pocztowych którzy bardzo różnie wyświetlają wiadomości i często w różny sposób obcinają HTML w nich zawartego, a przetestowanie czy wiadomość wyświetla się poprawnie wszędzie jest trudne i czasochłonne.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *