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++!
