Executando verificação de segurança...
6

📩 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.

Interface do Mailpit

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:

2

Passei boa parte da minha vida usando o MailHog. Decidi parar de utilizá-lo porque ele tem um ar de código abandonado - mesmo funcionando não recebe melhorias, a última release foi em 2020.

Eu o utilizava porque o Laravel, framework com que trabalho, entregava ele por padrão. Recentemente conheci o MailPit e decidi experimentar, daí gostei. No ecossistema do Laravel o que fazemos é justamente enviar e-mails via PHP e analisar, via interface web, como o e-mail seria entregue - como você mencionou.

MailPit é moderno, está sendo mantido e atualizado frequentemente e também tem imagem docker. Laravel acabou adotando-o por padrão.

MailPit está no ecossistema do Laravel Sail como uma opção de serviço via Docker

A imagem dele no DockerHub é: axllent/mailpit

1

Opa uso o mailhog e o mailpit, comecei ater este problema você sabe o que poderi aser:

Mail Error on dialing with encryption type None: dial tcp 127.0.0.1:1025: connect: connection refused

OBS TIVE QUE ADICIONAR O IP DO MEU CONTAINER DIRETAMENTE

1
1

Eu tive que dar um docker inspect pegar o ip direto do container para resolver, localhost não está indo, eu estava usando o mailhog e pensei que o problema estava na lib mas acabou que não era, estou fazendo um projetinho um golang. Obrigado pela ajuda.

1