Pular para conteúdo

Envio de E-mails com Spring Boot e SMTP do Gmail

Este documento detalha o processo de configuração e envio de e-mails em uma aplicação Spring Boot, utilizando o servidor SMTP do Gmail.

1. Habilitando o SMTP do Gmail e Gerando uma Senha de App

Para usar o SMTP do Gmail em uma aplicação externa, você precisa de uma "Senha de app" (App Password) se tiver a verificação em duas etapas ativada. É altamente recomendável ter a verificação em duas etapas ativada para maior segurança.

Passo a Passo para Gerar uma Senha de App:

  1. Acesse sua Conta Google: Vá para myaccount.google.com.
  2. Vá para Segurança: No menu lateral esquerdo, clique em "Segurança".
  3. Verificação em Duas Etapas: Role para baixo até a seção "Como você faz login no Google" e clique em "Verificação em duas etapas". Se ainda não estiver ativada, siga as instruções para ativá-la.
  4. Senhas de app: Após ativar a verificação em duas etapas, volte à tela de "Segurança" e procure por "Senhas de app". Clique nela.
  5. Gerar Nova Senha de App:
    • Selecione "Correio" no menu suspenso "Selecionar app".
    • Selecione "Outro (nome personalizado)" no menu suspenso "Selecionar dispositivo" e digite um nome como "Spring Boot Email" (opcional, apenas para identificação).
    • Clique em "Gerar".
  6. Copie a Senha de App: Uma senha de 16 caracteres será exibida em uma caixa amarela. Copie essa senha e guarde-a em um local seguro. Esta será a senha que você usará na sua aplicação Spring Boot, e não a senha da sua conta Google.

Observação: Se você não quiser ativar a verificação em duas etapas, teria que ativar a opção "Acesso a apps menos seguros" (Less secure app access) nas configurações de segurança do Google. No entanto, essa opção é descontinuada para contas pessoais a partir de 30 de maio de 2022 e não é recomendada por razões de segurança. Sempre prefira usar as "Senhas de app".

2. Configurando o Projeto Spring Boot

2.1. Adicionar Dependência do Spring Mail

Adicione a dependência spring-boot-starter-mail ao seu arquivo pom.xml.

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>

2.2. Configurar as Propriedades do Gmail no application.properties

No arquivo src/main/resources/application.properties adicione as seguintes configurações:

application.properties:

# Propriedades do Servidor SMTP do Gmail
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=${EMAIL_USER} # Seu endereço de e-mail do Gmail em uma variável de ambiente
spring.mail.password=${EMAIL_SENHA} # A senha de app gerada anteriormente em uma variável de ambiente

# Propriedades adicionais para SMTP seguro (TLS)
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=5000
spring.mail.properties.mail.smtp.writetimeout=5000

organize suas variáveis de ambiente

3. Criando o Serviço de E-mail

Crie uma classe de serviço para lidar com o envio de e-mails.

// src/main/java/com/example/emaildemo/service/EmailService.java
package com.example.emaildemo.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

@Service
public class EmailService {

    @Autowired
    private JavaMailSender mailSender;

    /**
     * Envia um e-mail simples.
     * @param to O destinatário do e-mail.
     * @param subject O assunto do e-mail.
     * @param text O corpo do e-mail.
     */
    public void sendSimpleEmail(String to, String subject, String text) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom("seu_email@gmail.com"); // Pode ser lido da configuração do application.properties
        message.setTo(to);
        message.setSubject(subject);
        message.setText(text);
        mailSender.send(message);
        System.out.println("E-mail enviado com sucesso para: " + to);
    }

    // Você pode adicionar métodos para enviar e-mails com HTML, anexos, etc.
    // Exemplo de envio de e-mail com HTML (requer MimeMessageHelper)
    /*
    import jakarta.mail.internet.MimeMessage;
    import org.springframework.mail.javamail.MimeMessageHelper;

    public void sendHtmlEmail(String to, String subject, String htmlContent) {
        try {
            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); // true para multipart/mixed
            helper.setFrom("seu_email@gmail.com");
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(htmlContent, true); // true indica que o conteúdo é HTML
            mailSender.send(message);
            System.out.println("E-mail HTML enviado com sucesso para: " + to);
        } catch (jakarta.mail.MessagingException e) {
            e.printStackTrace();
            // Lide com a exceção
        }
    }
    */
}

ThymeLeaf: Adicionalmente, se quiser enviar emails em html rico, pode usar uma template engine como o Thymeleaf

5. Considerações Importantes e Melhores Práticas

  • Segurança das Credenciais:
    • Nunca coloque credenciais diretamente no código-fonte em um ambiente de produção.
    • Para ambientes de produção, utilize variáveis de ambiente, Spring Cloud Config, HashiCorp Vault ou outros serviços de gerenciamento de segredos para injetar as credenciais.
    • Se estiver usando Docker, você pode usar segredos do Docker.
  • Tratamento de Exceções: Implemente um tratamento de exceções robusto para lidar com falhas no envio de e-mails (ex: rede, autenticação, etc.).
  • Logs: Configure logs para registrar o status do envio de e-mails, incluindo sucesso e falhas, para fins de depuração e auditoria.
  • Assincronismo: Para evitar bloquear o thread principal da sua aplicação (especialmente em requisições web), considere enviar e-mails de forma assíncrona usando @Async e @EnableAsync em sua classe de configuração principal.
    • Adicione @EnableAsync na sua classe principal (a que tem @SpringBootApplication).
    • Adicione @Async no método sendSimpleEmail do EmailService.
  • Modelos de E-mail (Templates): Para e-mails mais complexos ou com formatação HTML, use bibliotecas de templates como Thymeleaf, FreeMarker ou Mustache para criar modelos de e-mail e preenchê-los dinamicamente.
  • Configurações de Produção: Em produção, verifique se seu firewall permite a saída de conexões na porta 587 (ou 465 para SSL).
  • Limites do Gmail: Esteja ciente dos limites de envio diários do Gmail (geralmente 500 e-mails por dia para contas pessoais). Para maiores volumes, considere serviços de e-mail transacionais como SendGrid, Mailgun, AWS SES, etc.

Configurando as variáveis de ambiente


Setar variáveis de ambiente é crucial para manter credenciais seguras e flexibilizar as configurações da sua aplicação Spring Boot em diferentes ambientes. Abaixo, uma explicação concisa de como fazer isso para EMAIL_USER e EMAIL_SENHA em Windows, macOS e Docker Compose.

Windows

No Windows, você pode definir variáveis de ambiente temporariamente via linha de comando ou permanentemente através das configurações do sistema.

Temporariamente (para a sessão do terminal atual):

Abra o Prompt de Comando ou PowerShell e use:

set EMAIL_USER=seu_email@gmail.com
set EMAIL_SENHA=sua_senha_de_app

Ou no PowerShell:

$env:EMAIL_USER="seu_email@gmail.com"
$env:EMAIL_SENHA="sua_senha_de_app"

Em seguida, execute sua aplicação Spring Boot a partir do mesmo terminal.

Permanentemente (Sistema):

  1. Pesquise por "Variáveis de Ambiente" no menu Iniciar e selecione "Editar as variáveis de ambiente do sistema".
  2. Na janela "Propriedades do Sistema", clique em "Variáveis de Ambiente...".
  3. Na seção "Variáveis de usuário para " ou "Variáveis do sistema", clique em "Novo..." para adicionar EMAIL_USER e EMAIL_SENHA com seus respectivos valores.
  4. Clique em "OK" em todas as janelas para salvar as alterações. Pode ser necessário reiniciar o sistema ou o terminal para que as alterações entrem em vigor.

macOS

No macOS, as variáveis de ambiente podem ser definidas temporariamente na sessão do terminal ou adicionadas aos arquivos de configuração do shell para serem persistentes.

Temporariamente (para a sessão do terminal atual):

Abra o Terminal e use:

export EMAIL_USER="seu_email@gmail.com"
export EMAIL_SENHA="sua_senha_de_app"

Em seguida, execute sua aplicação Spring Boot a partir do mesmo terminal.

Permanentemente (Perfil do Usuário):

Para que as variáveis sejam carregadas automaticamente a cada nova sessão do terminal, adicione as linhas export a um dos seguintes arquivos no seu diretório home:

  • ~/.bash_profile (se você usa Bash como shell padrão)
  • ~/.zshrc (se você usa Zsh como shell padrão, que é o padrão no macOS Catalina e posterior)

Exemplo para ~/.zshrc:

echo 'export EMAIL_USER="seu_email@gmail.com"' >> ~/.zshrc
echo 'export EMAIL_SENHA="sua_senha_de_app"' >> ~/.zshrc
source ~/.zshrc # Para aplicar as mudanças imediatamente

Docker Compose

No Docker Compose, você pode definir variáveis de ambiente de algumas maneiras no seu arquivo docker-compose.yml. A forma mais comum e recomendada para credenciais é usar um arquivo .env.

Usando um arquivo .env (Recomendado para credenciais):

  1. Crie um arquivo chamado .env no mesmo diretório do seu docker-compose.yml.
  2. Adicione suas variáveis de ambiente a este arquivo, uma por linha:

    # .env
    EMAIL_USER=seu_email@gmail.com
    EMAIL_SENHA=sua_senha_de_app
    
  3. No seu arquivo docker-compose.yml, referencie essas variáveis. O Docker Compose irá automaticamente carregar variáveis de um arquivo .env no mesmo diretório.

    # docker-compose.yml
    version: '3.8'
    services:
      minha-app-spring:
        image: sua-imagem-spring-boot:latest # Ou use build: . se for construir a imagem
        ports:
          - "8080:8080"
        environment:
          # Estas variáveis serão lidas do arquivo .env
          - EMAIL_USER=${EMAIL_USER}
          - EMAIL_SENHA=${EMAIL_SENHA}
    
  4. Execute seu serviço Docker Compose: docker-compose up -d.

Alternativa (menos recomendada para credenciais sensíveis em controle de versão):

Você também pode definir as variáveis diretamente no docker-compose.yml na seção environment, mas isso expõe os valores no arquivo.

# docker-compose.yml
services:
  minha-app-spring:
    image: sua-imagem-spring-boot:latest
    ports:
      - "8080:8080"
    environment:
      EMAIL_USER: seu_email@gmail.com
      EMAIL_SENHA: sua_senha_de_app # Evite isso em produção

Sempre prefira o método do arquivo .env e certifique-se de adicioná-lo ao seu .gitignore para evitar que suas credenciais sejam versionadas.