Toda base de código tem uma: uma expressão regular, copiada do Stack Overflow, que "valida" endereços de e-mail. Parece uma verificação, mas responde a uma pergunta que quase ninguém está realmente fazendo. Um regex consegue dizer que uma string tem o formato de um endereço de e-mail. Ele não consegue dizer se o endereço existe, se aceita mensagens ou se não vai gerar um hard bounce na sua próxima campanha — e essas são as únicas coisas que importam.
A resposta curta#
Regex valida sintaxe, não entregabilidade. definitely-fake@gmail.com é
um endereço de e-mail perfeitamente válido por qualquer regex já escrito, e ele vai gerar bounce
no instante em que você enviar para ele. Pior ainda, os regexes que as pessoas costumam usar ou rejeitam
endereços reais (rígidos demais) ou aceitam qualquer bobagem (permissivos demais), e aquele que é
tecnicamente correto tem milhares de caracteres e ainda assim não consegue confirmar uma
caixa de correio. Use uma verificação de sintaxe simples para pegar erros de digitação no input e depois
verifique a entregabilidade com uma checagem de DNS e SMTP — que é um problema de rede, não
de correspondência de padrões.
O regex que você já viu, e o que ele deixa passar#
Aqui está o arquétipo — alguma variante dele vive na maioria dos projetos:
const re = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
re.test("definitely-fake@gmail.com"); // true ← will hard-bounce
re.test("typo@gmial.com"); // true ← typo'd domain, bounces
re.test("info@company-that-folded.com"); // true ← dead domain
Todos os três passam. Todos os três são não entregáveis. O regex fez seu trabalho perfeitamente e não te disse nada de útil, porque sintaxe e entregabilidade são perguntas diferentes. Todo endereço que um regex consegue enxergar é uma string; se há um humano lendo mensagens nele é um fato sobre a internet, não sobre a string.
O labirinto da RFC 5322#
"Tudo bem", diz o raciocínio, "vou usar um regex correto." A gramática formal para
um endereço de e-mail é definida pela RFC 5322, e um regex que realmente a implementa
é notoriamente monstruoso — milhares de
caracteres, e ele permite coisas que você nunca iria querer aceitar, como partes locais
entre aspas com espaços ("a b"@example.com) e comentários dentro do endereço.
Daí surgem dois problemas. Primeiro, o regex rígido aceita mais do que você quer, não menos — ele está validando contra uma especificação de 2008, não contra "endereços para os quais servidores de e-mail reais vão de fato entregar". Segundo, mesmo uma correspondência RFC 5322 impecável ainda não consegue dizer se o domínio tem um servidor de e-mail ou se a caixa de correio existe. Você gastou um esforço enorme para responder à pergunta fácil com mais precisão, enquanto a pergunta difícil — a mensagem vai chegar? — continua completamente intocada.
As três coisas que o regex fundamentalmente não consegue fazer#
Nenhum padrão, por mais engenhoso que seja, consegue atravessar a rede. O regex não consegue:
- Verificar se o domínio pode receber mensagens.
user@company-that-folded.comtem sintaxe válida em um domínio sem registros MX. Só uma consulta DNS revela o domínio morto. - Confirmar se a caixa de correio existe.
noreply-9f2x@gmail.comtem sintaxe válida para uma conta que nunca foi criada. Só uma conversa SMTP com o Gmail pode te dizer que ela não está lá. - Detectar um domínio catch-all. Um servidor catch-all aceita todos os endereços, então nem mesmo uma checagem SMTP ao vivo consegue confirmar uma caixa de correio específica — e um regex não faz a menor ideia de que o domínio se comporta assim.
Essas não são lacunas de um regex específico; elas estão fora do que qualquer regex consegue fazer, porque são perguntas sobre servidores, não sobre strings.
O que fazer de fato: validar em camadas#
A entregabilidade é uma sequência de verificações cada vez mais caras, e a sintaxe é apenas o primeiro estágio barato (o quadro completo está em como funciona a verificação de e-mail):
- Sintaxe — uma verificação simples no input para pegar erros de digitação óbvios. Essa é a única camada à qual o regex pertence.
- Domínio e MX — uma consulta DNS para confirmar se o domínio pode receber mensagens em algum grau. Veja os guias de Node.js e Python para código funcional.
- Sondagem SMTP da caixa de correio — a conversa de entrega que de fato confirma a caixa de correio, além da detecção de catch-all. Isso exige um servidor de e-mail com uma reputação de IP limpa e uma limitação de taxa cuidadosa, e é por isso que a maioria das equipes recorre a uma API de verificação em vez de construí-la.
A verificação de sintaxe que vale a pena manter#
Para a camada 1, não escreva a RFC 5322 na mão. O caminho pragmático é o input de e-mail HTML5 no navegador (que aplica o padrão do WHATWG living standard de graça) e uma verificação curta e permissiva no servidor:
// Pragmatic: rejects fat-finger errors, accepts the addresses real
// mail servers actually deliver to. Not a deliverability check.
const SYNTAX = /^[^\s@"]+(?:\.[^\s@"]+)*@[^\s@.]+(?:\.[^\s@.]+)+$/;
SYNTAX.test("jane@example.com"); // true
SYNTAX.test("not-an-email"); // false
SYNTAX.test("a@@b.com"); // false
Use-a para dar feedback instantâneo no teclado — nada além disso. Trate um resultado positivo como "vale a pena verificar direito", nunca como "válido".
Percorrendo o resto do caminho#
Depois que a sintaxe passa, a verificação de verdade é um trabalho de rede. Você pode construir as camadas de DNS
e SMTP você mesmo — os guias por linguagem acima mostram até onde dá para chegar —
mas confirmar caixas de correio ao vivo em escala esbarra na porta 25 estar bloqueada na maioria dos
provedores, na reputação de IP e no greylisting, que é
onde uma API gerenciada mostra seu valor. O
POST /verify da Qualisend executa toda a sequência e retorna um veredito
de quatro vias (deliverable | risky | undeliverable | unknown) com um código de motivo, para que
seu código aja com base em se a caixa de correio existe, e não em se a string tem
um @.
Perguntas frequentes#
Existe um regex correto para validação de e-mail?#
Não no sentido que as pessoas gostariam. Existe um regex que implementa a RFC 5322, mas ele tem
milhares de caracteres, aceita formas exóticas que você nunca iria querer e ainda assim não
consegue confirmar se o endereço é entregável. Para uso prático, um padrão curto e permissivo
(ou o input HTML5 type="email") para pegar erros de digitação é a quantidade certa de
regex — o resto é um problema de DNS e SMTP.
Por que meu regex rejeita endereços de e-mail válidos?#
Porque padrões rígidos codificam suposições que não são verdadeiras — que os domínios de
topo têm de 2 a 3 letras (não têm: .email, .io, .marketing), que sinais de mais
ou pontos não são permitidos na parte local (são), ou que novos gTLDs
não existem. Um regex rígido demais é uma fonte comum de cadastros perdidos. Seja
permissivo na sintaxe e verifique a entregabilidade separadamente.
A validação de e-mail do HTML5 verifica se o endereço é real?#
Não. A validação type="email" do navegador é uma verificação de sintaxe — uma versão mais amigável e
padronizada da mesma correspondência de padrões. Ela pega sinais de @ faltando
e defeitos óbvios no input, mas nunca entra em contato com o servidor de e-mail, então
não consegue dizer se o domínio ou a caixa de correio existe.
O que eu deveria usar no lugar do regex para validar e-mails?#
Faça em camadas: uma verificação de sintaxe permissiva para feedback instantâneo, uma consulta DNS/MX para descartar domínios mortos e uma sondagem SMTP da caixa de correio para confirmar a entrega. Construa as duas primeiras você mesmo; use uma API de verificação para a camada SMTP, já que fazer isso de forma confiável exige reputação de IP de envio e limitação de taxa que um regex jamais poderia oferecer.
Quer ver a diferença entre "sintaxe válida" e "vai de fato entregar"?
O plano gratuito inclui 100 créditos de verificação que executam a sequência
completa — sintaxe, DNS e a sondagem SMTP da caixa de correio — para que você possa ver um
endereço aprovado pelo regex voltar como undeliverable. A
referência da API tem exemplos de copiar e colar em sete linguagens.