Toda a equipa que constrói funcionalidades de email enfrenta eventualmente a mesma bifurcação: apontar o desenvolvimento para um fornecedor SMTP real ou simular a camada de correio e esperar que a produção se comporte. A primeira opção vaza credenciais, gasta quota do fornecedor e ocasionalmente envia um email a um cliente real a partir de um portátil. A segunda não testa nada para além do ponto em que o seu código entrega a mensagem a um servidor. Existe um caminho intermédio melhor — vários, na verdade. Eis como as opções padrão de testes locais se comparam e quando é que cada uma vence.
Porque é que o SMTP real em desenvolvimento é uma má ideia
A tentação é compreensível: fornecedor real, comportamento real, configuração zero. Os custos aparecem mais tarde:
- Fuga de credenciais. Chaves de API que vivem em ficheiros .env nas máquinas dos programadores acabam em registos, capturas de ecrã e, eventualmente, numa conversa de chat.
- Envios reais acidentais. Uma execução de testes contra uma base de dados de produção copiada envia emails a utilizadores reais a partir do seu portátil. Isto acontece constantemente e é sempre memorável.
- Suites de testes instáveis. Quando os testes unitários dependem da disponibilidade, dos limites de taxa e das particularidades do sandbox de um fornecedor externo, o CI torna-se previsão do tempo.
- Custo e quota. Mesmo os níveis gratuitos generosos esgotam-se depressa quando uma suite de testes envia centenas de mensagens por execução.
A solução é manter o envio real completamente fora do ciclo interno — a lógica de programadores e testes de QA com email temporário aplica-se também ao desenvolvimento local.
Opção 1: servidores SMTP locais de recolha total (MailHog, Mailpit)
Um servidor de recolha total escuta num porto local, aceita tudo sem autenticação nem TLS, guarda as mensagens em memória e mostra-as numa interface web. A sua aplicação aponta para ele como para qualquer host SMTP:
SMTP_HOST=127.0.0.1 SMTP_PORT=1025
docker run -p 1025:1025 -p 8025:8025 axllent/mailpit
O Mailpit é o padrão mantido atualmente: pré-visualização de HTML, análise de MIME, uma API REST para asserções e um modo de caos que simula falhas e atrasos. O MailHog, seu antecessor, está sem manutenção desde 2020 mas ainda funciona e ainda aparece em inúmeros tutoriais; escolha o Mailpit para qualquer coisa nova.
Vantajoso para: testes unitários e de integração, trabalho de frontend onde os designers precisam de ver os emails, e portáteis em comboios sem rede nenhuma.
Opção 2: contentores SMTP na stack de desenvolvimento
O degrau seguinte embute o balde de correio na sua stack docker-compose de desenvolvimento como um serviço com nome e um volume persistente. Duas coisas melhoram:
- Estado partilhado. O correio de todos os programadores aterra num sítio previsível, e reiniciar a aplicação não apaga a caixa.
- Asserções de teste por API. O Mailpit expõe uma API REST, pelo que os testes de integração podem obter a última mensagem enviada para um endereço e verificar assunto, cabeçalhos e corpo sem analisar registos.
A contrapartida mantém-se: o correio nunca sai da máquina. Autenticação, DNS e entregabilidade real continuam por testar, pelo que uma suite verde ainda pode lançar um registo de remetente partido. Antes de ligar o staging a domínios reais, confirme também o lado recetor — o verificador de MX mostra os mail exchangers de qualquer domínio para o qual esteja prestes a enviar.
Opção 3: caixas descartáveis para realismo de staging
Os baldes locais não conseguem responder à pergunta: a mensagem chegou realmente através da internet verdadeira? Essa pergunta exige entrega real, e é aí que as caixas descartáveis ganham o seu lugar. Aponte o staging para a sua infraestrutura real de envio e use endereços temporários como destinatários: as mensagens atravessam DNS genuíno, TLS e filtragem do fornecedor, e pode verificar a hora de chegada, o conteúdo e a pasta de spam — não apenas o seu próprio registo de saída.
Esta abordagem brilha para:
- Fluxos de registo ponto a ponto. Ligações de verificação e códigos de utilização única, verificados do lado da caixa, com o padrão de automação em automação com a API de email temporário.
- Pipelines de webhooks. Os webhooks de bounce e de mensagens recebidas precisam de eventos de correio reais para serem testados; o nosso guia para receber webhooks de email de uma caixa temporária percorre a ligação.
- Ensaios gerais de pré-produção. A configuração mais completa de staging está coberta em testes em ambiente de staging.
Qual opção e quando
- Testes unitários locais e pré-visualização: Mailpit no localhost. Rápido, offline, zero efeitos secundários.
- Ambiente de desenvolvimento de equipa: Mailpit como serviço compose com volume. Partilhado, inspetível, verificável por API.
- Verificação de staging e lançamento: envio real mais caixas destinatárias descartáveis. A única opção que exercita o caminho real que o correio dos seus utilizadores percorre.
- Monitorização de produção: não é um tema local — as verificações de colocação e os testes seed assumem esse papel aí.
Trate-as como camadas, não concorrentes: a maioria das configurações maduras usa as três, cada uma na altitude em que é boa.
FAQ
O MailHog continua a ser uma boa escolha em 2026? Ainda funciona, mas está sem manutenção há anos e está atrasado no tratamento de MIME moderno. O Mailpit é o seu sucessor em desenvolvimento ativo com um conjunto de funcionalidades compatível — escolha-o para qualquer coisa nova.
Posso testar DKIM e SPF com um servidor SMTP local? Não. A autenticação envolve DNS e consultas de chaves públicas que um servidor de localhost nunca exercita. Use entrega real para endereços descartáveis e verifique depois as assinaturas na mensagem recebida.
Como impedir o meu ambiente de desenvolvimento de enviar emails a pessoas reais? Aponte-o para SMTP local ou use um sinal de staging que reescreve todos os destinatários para caixas descartáveis. Nunca mantenha credenciais de produção num caminho acessível ao desenvolvimento.
Qual é a forma mais barata de verificar que um email chegou no CI? Crie uma caixa temporária por API, desencadeie o envio, consulte a mensagem e faça falhar o build por timeout. São umas linhas de script e apanha as falhas que os baldes locais não conseguem.
