Por que um provedor de e-mail é o formato errado para QA
Toda forma de dar endereços de e-mail a uma suíte de testes já foi tentada, e cada uma vaza em um lugar diferente:
| Abordagem | O que custa | Onde quebra |
|---|---|---|
Uma caixa de entrada compartilhada (qa@company.com) | Nada para configurar. | Todo teste lê o e-mail de todo outro teste. A primeira consulta de uma nova execução encontra o código da execução anterior. Execuções paralelas são impossíveis. |
Endereçamento com sinal de mais (qa+run42@company.com) | Nada para configurar, se o provedor suportar. | Ainda é uma única caixa de entrada: uma cota, um login IMAP compartilhado pelo time inteiro, e um formulário de cadastro que remove a tag ou recusa o +. |
| Uma caixa de entrada por testador, vinda do provedor | Uma licença cada, e um ticket para criar uma. | Ninguém provisiona uma caixa de entrada por execução de teste. Os testadores reutilizam a deles, e o problema da caixa de entrada compartilhada volta, uma pessoa de cada vez. |
| Um domínio catch-all apontado para cá | Um registro DNS, uma vez. | A caixa de entrada é pública para qualquer um que saiba o endereço, e o e-mail vive 5 dias. As duas coisas não têm problema para um código que importa por onze segundos; nenhuma das duas serve para e-mail real de clientes. |
A quarta linha é o assunto deste guia. É o mesmo mecanismo sobre o qual os domínios públicos descartáveis rodam — um servidor que aceita todo endereço em um domínio em vez de uma lista de caixas de entrada — aplicado a um nome que mais ninguém além de você está usando.
O único registro DNS
No seu provedor de DNS, adicione um único registro MX na raiz de um domínio que você possui. Nenhum outro registro aqui, nenhum TXT para provar nada, nenhuma conta neste site:
Registro MX para o domínio10 smtp.grabmail.io
- Publique o MX. Prioridade 10, apontando para
smtp.grabmail.io. Apague qualquer outro MX no domínio — o e-mail só pode ser entregue em um lugar, e um registro esquecido manda parte dele para outro lugar. - Espere pelo DNS. Geralmente minutos; ocasionalmente o TTL de qualquer registro que estava lá antes.
dig MX qa-example.commostra quando ele entrou em vigor. - Envie uma mensagem para qualquer endereço nele. A primeira entrega é o que conecta o domínio: o servidor consulta o MX naquele momento, se reconhece, e aceita. A partir daí, todo endereço no domínio é uma caixa de entrada.
Um esquema de nomenclatura que diz quem criou a caixa de entrada
Com todo endereço válido, a parte local fica livre para carregar informação — e às duas da manhã, com uma execução falhada e uma caixa de entrada aberta, você vai querer que ela carregue. Três partes, unidas por hífens, nesta ordem:
| Parte | Exemplo | O que isso te dá |
|---|---|---|
| O que criou | signup, reset, e2e, alice | Uma olhada já diz a qual fluxo ou a qual pessoa a caixa de entrada pertence. |
| Qual execução | 1234567890 (o id da execução na CI), um nome de branch, uma data | Toda caixa de entrada de uma mesma execução de pipeline compartilha um token que você pode buscar. |
| Aleatoriedade | 3f9a1c2e | Oito caracteres dela. Essa é a parte que faz com que dois testes, dois shards ou dois retries nunca compartilhem uma caixa de entrada. |
| Nunca: qualquer coisa real | um nome de cliente, um id de usuário real, um número de ticket que nomeia um cliente | A caixa de entrada é pública para qualquer um que saiba o endereço. Nada no endereço deveria valer a pena saber. |
// one helper, every runner: who made it, which run, and eight random characters
export const testAddress = (who: string, run = process.env.GITHUB_RUN_ID ?? 'local') =>
`${who}-${run}-${crypto.randomUUID().slice(0, 8)}@qa-example.com`;
testAddress('signup'); // signup-1234567890-3f9a1c2e@qa-example.comLendo qualquer endereço, as mesmas três chamadas
Nada na API muda para o seu próprio domínio. A mesma chamada de listagem, a mesma chamada de mensagem, o mesmo delete — nenhuma chave no nível público, e o domínio no endereço é a única coisa que muda:
$ curl -sG https://grabmail.io/api/v1/mailbox --data-urlencode "address=signup-1234567890-3f9a1c2e@qa-example.com"O que significa que todo helper deste site funciona sem mudanças depois de uma única constante ser editada: a fixture do Playwright, a task do Cypress, os módulos de Python e Node. Três coisas valem a pena saber, que os domínios públicos não te fazem pensar sobre:
- Um
404significa que o MX ainda não está lá - A listagem responde
404para um domínio que não é hospedado aqui. No seu próprio domínio, isso é um problema de DNS — o registro não propagou, ou aponta para outro lugar — não um problema de API. Rodedig MXprimeiro. - O alias funciona no seu domínio também
- Toda caixa de entrada, em qualquer domínio, tem um segundo endereço em um domínio separado que entrega nela e não consegue lê-la. Dê esse endereço a um site quando você preferir que ele não consiga abrir a caixa de entrada; faça polling no seu próprio endereço.
- Um endereço movimentado é paginado
- Um endereço catch-all que coleta bounces ou um dia de notificações pode conter mais de uma página de 200. Passe
nextde volta comobeforeaté que sejanull.
Mantendo um domínio de teste utilizável
Um domínio seu não está em nenhuma lista de bloqueio de e-mail descartável, o que muitas vezes é o próprio motivo de usar um: a aplicação sob teste recusa grabmail.io e todo outro domínio público, exatamente como deveria. Quatro hábitos mantêm essa condição:
- Use um domínio dedicado —
qa-example.com, não um subdomínio de produção e não o domínio para o qual os clientes escrevem. O serviço aceita só domínios registráveis (example.com, nuncamail.example.com), e um domínio de teste não deveria ter nenhuma outra função. - Não o publique. As listas são construídas a partir do que aparece em sites públicos de e-mail temporário e em dumps de endereços compartilhados. Um domínio que só aparece na sua própria suíte de testes não tem como entrar nelas.
- Tranque-o com SPF e DMARC. Um domínio só de recebimento sem SPF é um domínio a partir do qual qualquer um pode falsificar e-mail; dois registros fecham essa brecha, e não custam nada.
- Não aponte e-mail real para ele. No momento em que um sistema de staging manda notificações de clientes para um endereço catch-all, uma caixa de entrada pública passa a guardar dados de clientes. Domínios de teste carregam e-mail de teste.
Se a aplicação recusa todos os domínios catch-all — algumas verificações de fraude fazem isso, sondando se um endereço aleatório no domínio é aceito — existe um conjunto pago de domínios .com com aparência comum mantidos fora das listas, descrito na página de preços. Por que formulários de cadastro bloqueiam e-mail descartável explica o que cada tipo de verificação enxerga.
Para um time: um domínio, muitos testadores, muitos pipelines
Um domínio catch-all atende a todo mundo, porque a parte local é a única coisa que precisa mudar, e ela é livre. O que um time precisa é de acordo sobre a nomenclatura acima e três pequenas convenções:
- Um prefixo por pipeline e por pessoa
e2e-,nightly-,alice-. Buscar o prefixo no log de um job encontra toda caixa de entrada que ele criou; buscar o de um colega encontra o bug que ele está investigando.- Nada compartilhado, nunca
- Não existe uma “caixa de entrada do time” no domínio nem uma fixture que distribui um endereço fixo. Se duas pessoas precisam da mesma caixa de entrada, uma delas manda o endereço para a outra.
- Os limites de taxa são por cliente
- Uma leitura por segundo por endereço, 1200 requisições por minuto por cliente — um runner de CI é um cliente, um notebook é outro. Um time de dez rodando suítes ao mesmo tempo são dez clientes, não um.
Os limites que se aplicam
O seu próprio domínio recebe o mesmo serviço que os públicos, com os mesmos tetos. Nenhum deles é ajustável, e nenhum é um problema para uma suíte de testes:
| Limite | Valor | O que isso significa para QA |
|---|---|---|
| Retenção | 5 dias por mensagem | Toda execução cria seu próprio e-mail; nada nunca é buscado de uma semana anterior. As regras exatas. |
| Anexos | 5 MB por mensagem | Suficiente para um PDF de fatura ou uma exportação em CSV; uma mensagem maior é recusada no momento do SMTP, então quem envia é avisado. |
| Leituras | 1 por segundo por endereço, 1200 por minuto por cliente | Vinte caixas de entrada consultadas uma vez por segundo a partir de um runner. Além disso, 429 com Retry-After. |
| Privacidade | Nenhuma — qualquer um que saiba um endereço pode lê-lo | Partes locais aleatórias, um domínio não publicado, e nenhum e-mail real de clientes. |
| Envio | Nenhum | O domínio só recebe. A sua aplicação envia através do próprio provedor dela, como em produção. |
Antes de considerar concluído
- Um domínio registrável dedicado, com um registro MX:
10 smtp.grabmail.io, e nenhum outro MX. - Uma mensagem enviada para qualquer endereço nele, e lida de volta pela API.
- SPF e DMARC publicados, para que ninguém possa enviar como se fosse o domínio.
- Um helper de nomenclatura — quem, qual execução, oito caracteres aleatórios — usado por toda suíte.
- O domínio mantido em configuração de ambiente, nunca no código, em capturas de tela ou em tickets.
- Nada que envie e-mail real de clientes apontado para ele.
Daqui em diante, as suítes são as que já foram escritas: Playwright com o domínio na fixture dele, a disciplina independente de runner, e o workflow do GitHub Actions com o domínio em uma variável.
Perguntas
Posso usar um subdomínio, como test.company.com?
Não — o serviço aceita só domínios registráveis (company.com, ou company.co.uk), porque quem quer que controle um domínio controla todo nome abaixo dele, e duas partes não podem ter metades sobrepostas de um mesmo namespace. Registre um domínio dedicado barato para testes; é a prática melhor de qualquer forma.
Quanto tempo até o registro MX funcionar?
Assim que o DNS o serve, o que geralmente é questão de minutos. Se havia um MX anterior, o TTL dele se aplica. O domínio é conectado pela primeira mensagem que chega depois disso — nada mais precisa acontecer, e dig MX te diz quando o registro está no ar.
Isso custa alguma coisa?
Não. Conectar um domínio, todo endereço nele e a API são gratuitos, sem conta. A única coisa paga neste site é um conjunto de domínios mantidos fora das listas de bloqueio de e-mail descartável, para quem não pode usar um domínio próprio.
Alguém mais pode ler e-mail no meu domínio?
Qualquer um que saiba um endereço pode, exatamente como nos domínios públicos. O que o seu próprio domínio muda é a capacidade de adivinhação: os endereços nele estão em um nome que mais ninguém está usando. Partes locais aleatórias e um domínio não publicado tornam a adivinhação impraticável; elas não tornam a caixa de entrada privada, e nada aqui torna.
O que acontece com o e-mail enviado ao domínio antes de eu conectá-lo?
Nada chega aqui até o MX apontar para cá. O e-mail enviado enquanto o registro antigo estava ativo foi para o servidor antigo, ou retornou; o e-mail enviado depois que o DNS mudou chega e conecta o domínio.
Como eu desconecto o domínio?
Remova o registro MX. O e-mail novo para de chegar imediatamente; o que já está nas caixas de entrada expira sozinho dentro de 5 dias. Nada sobre o domínio é mantido depois disso.
A aplicação recusa o meu domínio de teste também. E agora?
Algumas verificações de fraude recusam qualquer domínio que aceite um endereço aleatório — uma sondagem catch-all — em vez de conferir uma lista. Para esses casos, é necessário um domínio que se comporte como um provedor de caixa de entrada comum, que é o que o conjunto pago oferece; por que formulários de cadastro bloqueiam e-mail descartável explica qual verificação você está enfrentando.


