📩 Mailpit: Ferramenta de Teste de E-mail com API + [O que usamos no TabNews?]
Turma esbarrei recentemente no Mailpit, uma ferramenta Open Source para captura de email ("mail catcher") que simula um servidor falso de SMTP e que pode ser usado em testes de email, incluindo em testes automatizados de integração por disponibilizar uma API em REST e uma Imagem Docker para subir facilmente o serviço. Fora isso, é disponibilizado uma Interface Web para você manualmente ver os emails, principalmente os com formatação HTML.
O que usamos no TabNews?
Para nos certificarmos que o backend
está enviando os emails nas situações corretas, inclusive enviando com as informações corretas, nós usamos um outro sistema de captura de emails chamado MailCatcher.
Ele funciona de forma adequada e nunca apresentou problemas, nem quando usado de forma manual para verificar os emails pela Interface Web, nem nos testes automatizados de integração, tanto rodando tudo Localmente ou no Continuous Integrator (e a gente roda bastante testes). E eu uso este mesmo serviço no curso.dev e lá considero ser algo ainda mais crÃtico, pois preciso ter certeza absoluta que não quebrei por nada o envio dos Códigos de Ativação a cada nova matrÃcula.
Mas apesar de tudo isso, a Interface Web e API do MailCatcher são muito mal implementadas na minha opinião.
Digo isso, pois no contexto de "teste de integração de um email", seria muito conveniente ter um endpoint /last
ou /latest
, por exemplo, para já puxar o último email enviado, com todas as informações (cabeçalho e corpo) tudo num só JSON
... mas não, infelizmente precisamos bater no endpoint de pegar todos os emails, selecionar o último, depois bater num segundo endpoint para puxar o corpo do email e aà sim fazer a verificação final. Isto é feito neste método:
async function getLastEmail() {
const emailListResponse = await fetch(`${emailServiceUrl}/messages`);
const emailList = await emailListResponse.json();
if (emailList.length === 0) {
return null;
}
const lastEmailItem = emailList.pop();
const emailTextResponse = await fetch(`${emailServiceUrl}/messages/${lastEmailItem.id}.plain`);
const emailText = await emailTextResponse.text();
lastEmailItem.text = emailText;
return lastEmailItem;
}
Fora isso, é muito comum você precisar limpar a caixa de entrada dos emails entre um teste e outro, mas não foi documentado como fazer isso pela API. Então tive que "roubar" da Interface Web deles um método que era usado lá. E isso foi reimplementado neste método:
async function deleteAllEmails() {
await fetch(`${emailServiceUrl}/messages`, {
method: 'DELETE',
});
}
O bom é que fornecem uma Imagem Docker, então fica muito fácil subir o serviço em ambiente local para desenvolvimento ou no estágio de Continuous Integration 💪 E isto foi implementado nesta parte do nosso Docker Compose:
mailcatcher:
container_name: mailcatcher
image: sj26/mailcatcher
expose:
- 1025
- 1080
ports:
- 1025:1025
- 1080:1080
Outras alternativas
Eu descobri sobre o Mailpit numa thread no Hacker News (link na Fonte) e alguns outros comentários listaram outras alternativas e eu agreguei na lista abaixo:
- Lunatic SMTP: https://github.com/anlar/lunaticsmtp
- Green Mail: https://greenmail-mail-test.github.io/greenmail/
- Mailhog: https://github.com/mailhog/MailHog
- MailDev: https://github.com/maildev/maildev
- Ethereal: https://ethereal.email/
- FakeSMTP: http://nilhcem.com/FakeSMTP/
- smtp4dev: https://github.com/rnwood/smtp4dev