Enviando E-mail com Spring Boot

Em muitas aplicações, o envio de e-mails é uma funcionalidade essencial — seja para notificar usuários, confirmar cadastros ou acompanhar eventos internos da aplicação. Neste post, vamos ver como integrar esse recurso de forma prática e eficiente usando o Spring Boot.
Primeiro, precisamos incluir a dependência Spring Boot Starter Mail no arquivo pom.xml
para habilitar o suporte ao envio de e-mails na aplicação.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
Em seguida, vamos configurar a conta de e-mail que será usada para o envio das mensagens. Para este tutorial, utilizaremos o Mailtrap, uma ferramenta ideal para testes, que permite capturar e visualizar e-mails de forma segura e prática, sem enviá-los de fato para destinatários reais. Nosso application.properties
ficará assim.
spring.mail.host=sandbox.smtp.mailtrap.io
spring.mail.port=587
spring.mail.username=user
spring.mail.password=*********
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
Com as configurações prontas, é hora de criar um controller responsável por disparar o envio da mensagem.
@RestController
public class MailController {
private JavaMailSender mailSender;
public MailController(JavaMailSender mailSender) {
this.mailSender = mailSender;
}
@GetMapping("/mail")
public ResponseEntity<Void> send(){
SimpleMailMessage message = new SimpleMailMessage();
message.setTo("rodrigo@botecodigital.dev.br");
message.setSubject("Mensagem de teste");
message.setText("Esta é uma mensagem de teste!");
message.setFrom("contato@botecodigital.dev.br");
mailSender.send(message);
return ResponseEntity.ok().build();
}
}
Neste trecho de código, utilizamos a injeção de dependência para receber uma instância de JavaMailSender
via construtor (linha 6), que será responsável por enviar os e-mails. Na linha 12, instanciamos um SimpleMailMessage
, que representa a mensagem que será enviada. Esse objeto oferece métodos para configurar os principais campos do e-mail: setTo()
para o destinatário, setSubject()
para o assunto, setText()
para o corpo da mensagem, setFrom()
para o remetente, além de setCc()
e setBcc()
para cópia e cópia oculta, respectivamente. Por fim, o envio é feito através do método send()
, passando o objeto da mensagem, na linha 18.
Utilizando Thymeleaf para o corpo do e-mail
Para criar e-mails com conteúdo em HTML de forma dinâmica, podemos utilizar o Template Engine Thymeleaf, aproveitando todo o poder das suas diretivas. O primeiro passo é criar um template HTML. Vamos adicionar esse arquivo em resources/templates/mail/message.html
.
<!DOCTYPE html>
<html lang="pt-BR" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Seja bem-vindo</title>
</head>
<body>
<p>Olá <th:block th:text="${nome}"></th:block>!</p>
<p>Você se cadastrou em <th:block th:text="${#temporals.format(data,'dd/MM/yyyy hh:mm')}" /></p>
<p>Com os itens: </p>
<ul>
<li th:each="item : ${itens}" th:text="${item}"></li>
</ul>
</body>
</html>
Em seguida, vamos criar o método no controller responsável por enviar a mensagem.
@Autowired
private TemplateEngine templateEngine;
@GetMapping("/mail-template")
public ResponseEntity<Void> sendTemplate(){
try{
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper message = new MimeMessageHelper(mimeMessage);
message.setTo("rodrigo@botecodigital.dev.br");
message.setFrom("contato@botecodigital.dev.br");
message.setSubject("Mensagem de teste");
Context ctx = new Context();
ctx.setVariable("nome", "Rodrigo Aramburu");
ctx.setVariable("data", LocalDateTime.now());
ctx.setVariable("itens", Arrays.asList("Item 1", "Item 2", "Item 3"));
String body = templateEngine.process("mail/message", ctx);
message.setText(body, true);
mailSender.send(mimeMessage);
}catch( MessagingException e){
e.printStackTrace();
}
return ResponseEntity.ok().build();
}
Começamos injetando o objeto TemplateEngine
com a anotação @Autowired
. Ele será responsável por processar o nosso template HTML e gerar o conteúdo da mensagem a ser enviada.
No método do controller, em vez de utilizar um SimpleMailMessage
, criamos um MimeMessage
usando o método createMimeMessage
do JavaMailSender
. Em seguida, instanciamos um MimeMessageHelper
, passando o MimeMessage
como parâmetro. É nesse objeto MimeMessageHelper
que vamos configurar os campos do e-mail, assim como fizemos anteriormente com o SimpleMailMessage
.
Na linha 14, criamos um objeto Context
, onde vamos adicionar as variáveis que serão utilizadas no nosso template. Usamos o método setVariable
para incluir valores como um nome, uma data e uma lista de itens que serão exibidos no template.
Para gerar o corpo do e-mail, chamamos o método templateEngine.process()
na linha 18, passando o caminho do arquivo HTML e o objeto Context
que contém as variáveis. Esse método retorna uma String
com o conteúdo processado, que é então passado para o método setText
, com o segundo parâmetro definido como true
para indicar que o conteúdo está em formato HTML.
Por fim, chamamos o método mailSender.send()
, passando o objeto MimeMessage
para enviar o e-mail.
Enviando um e-mail com anexo
Enviar um arquivo anexado é bem simples: basta utilizar o método addAttachment
do objeto MimeMessageHelper
, passando o nome do arquivo e um objeto File
.
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true);
message.setTo("rodrigo@botecodigital.dev.br");
message.setFrom("contato@botecodigital.dev.br");
message.setSubject("Mensagem de teste");
message.setText("Segue arquivo anexo");
File file = ResourceUtils.getFile("classpath:texto.txt");
message.addAttachment(file.getName(), file);
mailSender.send(mimeMessage);
Enviando um e-mail com uma imagem inline
Para enviar um e-mail com uma imagem inline no corpo da mensagem é bastante simples. Utilizaremos um template Thymeleaf para escrever nosso HTML.
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>E-mail com imagem inline</title>
</head>
<body>
<img th:src="|cid:imageDuke|" alt="Duke segurando uma taça">
</body>
</html>
Perceba que na tag de imagem, no atributo src
, utilizamos cid:imageDuke
. O nome imageDuke
é o identificador que vamos atribuir à imagem quando a adicionarmos ao objeto de imagem no código Java.
Agora, vamos ao código que adiciona a imagem à mensagem.
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true);
message.setTo("rodrigo@botecodigital.dev.br");
message.setFrom("contato@botecodigital.dev.br");
message.setSubject("Mensagem de teste");
Context ctx = new Context();
byte[] imageBytes = Files.readAllBytes(ResourceUtils.getFile("classpath:duke.png").toPath());
InputStreamSource imageSource = new ByteArrayResource(imageBytes);
message.addInline("imageDuke", imageSource, "image/png");
String body = templateEngine.process("mail/inline", ctx);
message.setText(body, true);
mailSender.send(mimeMessage);
Primeiro, lemos o arquivo de imagem para um array de bytes (linha 9). Em seguida, criamos um InputStream
a partir desses bytes e adicionamos a imagem usando o método addInline
. Esse método recebe o identificador da imagem (o mesmo nome que usamos no atributo src
da tag <img>
no HTML), o InputStream
da imagem e o MIME type do arquivo. E pronto, é só enviar o e-mail.
A abstração fornecida pelo Spring Boot Starter Mail torna o envio de e-mails muito simples, como vimos neste post. Espero que tenha sido útil. T++!