Use este checklist de validação de sintaxe de email compatível com RFC para capturar casos extremos como strings entre aspas, plus addressing e subdomínios complicados antes do lançamento.

Use um parser dedicado quando possível. Regexes normalmente perdem casos extremos como local parts entre aspas, tags com + e domínios com múltiplos rótulos, então ou rejeitam usuários reais ou aceitam entradas inválidas.
Sintaxe pergunta: “Isto está escrito em um formato de email válido?” Política pergunta: “Queremos permitir isso no nosso produto?” Separe-as para não bloquear endereços válidos enquanto tenta reduzir cadastros de risco.
Não. “Compatível com RFC” significa principalmente que a string pode ser parseada como endereço de email. Não prova que o domínio existe, que tem registros MX ou que a caixa postal recebe mensagens.
Primeiro remova espaços em branco no início e no fim, depois rejeite caracteres de controle como tabs e quebras de linha. Não “normalize” removendo caracteres internos, porque isso pode alterar o endereço que o usuário digitou.
Permita por padrão. [email protected] é um formato normal e amplamente usado; bloqueá-lo costuma criar atrito desnecessário no cadastro sem melhorar a segurança por si só.
Sim. Subdomínios são comuns, e domínios podem ter múltiplos pontos como sub.example.co.uk. Um validador que assume “apenas um ponto” no domínio vai rejeitar muitos endereços reais.
Exija “exatamente um @”, com pelo menos um caractere em cada lado. Não divida no primeiro @ e ignore o resto, e não aceite entradas que contenham múltiplos @ como estão.
Decida intencionalmente. Eles são válidos segundo a norma, mas são raros e podem quebrar sistemas a jusante que assumem formatos mais simples. Se você os rejeitar, trate como uma escolha de política e mostre uma mensagem clara.
Eles ajudam a evitar entradas abusivas ou perigosas e reduzem casos extremos estranhos. Limites práticos comuns: 254 caracteres no total, 64 para o local part, 253 para o domínio e 63 por rótulo de domínio.
Use códigos de motivo que mapeiem falhas específicas, como CONTROL_CHAR, PARSE_FAIL, LENGTH ou DOMAIN_LABEL. Isso torna tickets de suporte e debugging muito mais fáceis do que um genérico “email inválido”.
Endereços de email parecem simples até você tentar validá-los. Muitos bugs em produção vêm de tratar um email como “algumas letras, um @ e um ponto” e depois confiar em uma regex rápida. Endereços reais permitem mais variação do que a maioria dos formulários espera, e pequenas escolhas de parsing podem transformar um endereço válido em um erro “inválido”.
Uma confusão comum é confundir duas perguntas diferentes:
Se você quer reduzir cadastros arriscados, pode bloquear certos padrões. Se seu objetivo é evitar rejeitar usuários reais, primeiro precisa acertar a sintaxe e depois aplicar a política por cima. Separar essas camadas é a diferença entre um validador confiável e outro que silenciosamente perde cadastros.
Rejeitar emails válidos quebra coisas reais. Alguém insere um endereço perfeitamente válido com plus addressing ou um subdomínio, seu formulário diz “inválido” e a pessoa vai embora. Você perde o cadastro e nem reúne dados suficientes para depurar o que aconteceu.
Aceitar emails ruins quebra outras coisas. Endereços inválidos aumentam bounces, o que pode prejudicar reputação do remetente e entregabilidade. Eles também atraem cadastros de baixa qualidade e fraude quando atacantes enchem formulários com lixo.
A maioria das falhas em produção se resume a alguns padrões: regexes que são muito restritas (ou frouxas demais), divisão incorreta ao redor de @, trimming ou “normalização” excessiva, e misturar checagens de sintaxe com checagens de entregabilidade.
Exemplo: alguém se cadastra com [email protected]. Um validador simplista o rejeita porque espera apenas um ponto no domínio. O endereço pode estar perfeitamente certo, mas o usuário nunca chega à confirmação.
Este post foca na sintaxe: se um endereço está escrito em um formato válido. Não prova que a caixa existe ou que o domínio pode receber mail. Essas checagens pertencem a camadas posteriores.
“Compatível com RFC” é principalmente sobre sintaxe: essa string pode ser parseada como um endereço de email segundo as regras da RFC 5322? Isso é útil, mas é só o primeiro portão. Um endereço sintaticamente válido ainda pode ser não entregável, inseguro ou de baixa qualidade.
Pense na validação em camadas:
Um pipeline prático se parece com: parsear sintaxe, verificar o básico do domínio e então aplicar sua política (bloquear domínios descartáveis conhecidos, armadilhas de spam e outros sinais de risco). Sintaxe sozinha nunca deve fingir que garante entregabilidade.
Para formulários de cadastro, “compatível com RFC” geralmente significa aceitar formatos reais comuns (tags com +, subdomínios, TLDs mais longos) e evitar rejeitar endereços válidos só porque são incomuns.
Algumas equipes intencionalmente endurecem regras. Isso pode ser razoável, mas deve ser uma escolha deliberada, documentada e testada. Por exemplo, você ainda pode rejeitar:
@ ou falta da parte local ou do domínioCenário: [email protected] pode ser sintaticamente válido. Se o domínio não tem registros MX, você pega isso na camada de domínio. Se for um provedor descartável conhecido, isso é política.
A maioria dos bugs de validação de email acontece porque o validador está chutando. Antes de pegar uma regex, mantenha a estrutura clara: uma parte local, exatamente um @ e uma parte de domínio.
@. É aí que moram os casos complicados: tags com +, pontos e às vezes strings entre aspas.@. Segue regras de rótulos de domínio e pode ser internacionalizada.Manter essas peças separadas torna a lógica mais fácil de entender e muito mais simples de testar.
Endereços reais podem incluir caracteres não ASCII na parte local (EAI) e domínios não ASCII (IDN). Decida desde o início o que você suporta.
Se aceitar apenas ASCII, rejeite não-ASCII cedo com uma mensagem clara. Se aceitar IDNs, normalmente você vai validar o domínio em sua forma compatível com ASCII (punycode) internamente.
Limites de comprimento ajudam a evitar casos extremos e protegem seus formulários contra abuso. Limites comuns usados na prática:
Faça uma limpeza básica antes de parsear: remova espaços em branco no início e no fim, e rejeite endereços com espaços internos a menos que você suporte intencionalmente local parts entre aspas. Não transforme a parte local para minúsculas (ela pode ser sensível a maiúsculas), mas lowercasing o domínio geralmente é seguro.
Plus addressing é quando alguém adiciona uma tag após um sinal de mais, como [email protected]. Pessoas usam isso para filtrar email e rastrear cadastros, então rejeitá-lo adiciona atrito sem benefício.
Trate + como um caractere normal na parte local (fora de strings entre aspas). Mesmo que alguns provedores ignorem a tag para entrega, ainda faz parte do endereço como escrito.
Muitas equipes aceitam um “subconjunto seguro” na parte local (letras, dígitos e alguns separadores como ., _, -, +). Isso cobre a maioria dos endereços reais e deixa a implementação mais simples.
As regras da RFC permitem mais pontuação, mas ampliar o conjunto aceito só ajuda se você fizer isso corretamente e mantiver testes sólidos.
Na forma comum não entre aspas, pontos são permitidos na parte local, mas não em qualquer posição:
[email protected] é inválido[email protected] é inválidoNão incorpore comportamento específico de provedores na sintaxe. Alguns provedores tratam firstlast e first.last como a mesma caixa, mas isso não é uma regra de sintaxe.
Alguns casos rápidos que valem testar:
[email protected] (tag com +)[email protected] (ponto)[email protected] (ponto inicial)[email protected] (ponto duplo)[email protected] (tag + com subdomínio)Strings entre aspas existem porque as regras de email precisaram cobrir sistemas antigos e nomes de caixa incomuns. Elas aparecem na parte local quando o endereço precisa de caracteres que seriam ilegais ou ambíguos de outra forma.
Uma parte local entre aspas é envolvida por aspas duplas, como \"john smith\"@example.com. Dentro das aspas, espaços são permitidos. Se você precisa de uma aspa dupla literal ou de uma barra invertida dentro das aspas, ela deve ser escapada com uma barra invertida.
A parte confusa é que as regras mudam dentro das aspas. Dois pontos em sequência são normalmente inválidos em uma parte local não entre aspas, mas são permitidos dentro de uma string entre aspas. Isso significa que \"a..b\"@example.com pode ser válido mesmo que [email protected] seja inválido.
Para cadastros, você tem uma escolha real:
Ambas são defensáveis. O que causa bugs é rejeitá-las acidentalmente com uma regex que você não quis depender.
Casos de teste sintaticamente válidos:
\"john smith\"@example.com\"a..b\"@example.com\"john\\\"smith\"@example.com\"back\\\\slash\"@example.com\"weird()[],:;\u003c\u003e@\"@example.comStrings entre aspas afetam apenas a parte local. Você ainda precisa validar o domínio separadamente.
Muitos validadores erram no domínio. Subdomínios são normais e comuns. [email protected] não deve surpreender seu parser.
Uma abordagem simples é validar o domínio como rótulos separados por pontos e então aplicar algumas regras fáceis.
Para a maioria dos cadastros de consumidor, estas regras funcionam bem:
Exigir “pelo menos um ponto” frequentemente é um bom filtro contra erros de digitação para endereços públicos, mas pode ser uma decisão de política se você suportar domínios internos.
A colocação de pontos é onde bugs se escondem. Estes devem ser falhas duras:
[email protected][email protected], [email protected].[email protected][email protected], [email protected]a@sub_domain.exampleA maioria dos erros “email inválido” vem de validadores que fazem suposições em vez de seguir regras consistentes.
Espaços em branco são um grande problema. Copiar/colar pode adicionar espaços iniciais, finais, tabs, espaços sem quebra ou uma newline oculta. Se você validar antes de trimar, rejeita um endereço válido. Se “normalizar” demais (como remover todos os espaços onde quer que sejam), você pode mudar o significado do endereço.
Outro erro é dividir ao redor de @ de forma ingênua. Você quer uma regra clara: exatamente um separador @, com pelo menos um caractere em cada lado. Não aceite lixo dividindo no primeiro @ e ignorando o resto, e não trave ou gere erros confusos dividindo em todos os @.
Algumas bibliotecas também suportam parcialmente features da RFC como comentários (por exemplo john.smith(comment)@example.com). Suporte parcial pode ser pior do que rejeição consistente porque cria divergências entre frontend e backend.
Sinais de alerta:
@ sem impor “exatamente um”Parecidos Unicode são complicados. Mesmo que você suporte endereços internacionalizados, ajuda registrar casos suspeitos e mostrar uma mensagem clara quando algo parece estranho.
Um validador confiável não é um padrão esperto. É um pequeno conjunto de regras aplicadas na ordem certa.
Remova espaços em branco no início e no fim, então rejeite caracteres de controle (tabs, quebras de linha, null bytes). Decida como tratar espaços Unicode não usuais. Seja explícito se suporta ou não não-ASCII.
Uma abordagem só com regex frequentemente rejeita endereços válidos ou aceita quebrados. Use um parser que entenda parte local vs domínio, e saiba lidar com strings entre aspas se você decidir suportá-las.
Mantenha parsing separado de política. Parsing responde “é sintaticamente válido?” Política responde “permitimos no produto?”
Depois do parse, aplique limites rígidos e checagens básicas de sanidade do domínio (limites de comprimento, sem rótulos vazios, sem hífens nas bordas, subdomínios permitidos quando bem formados). Isso pega entradas que podem tecnicamente parsear mas que vão causar problemas depois.
Decida intencionalmente sobre casos extremos como partes locais entre aspas. Se bloquear, diga e mostre uma mensagem clara. Se permitir, adicione testes para caracteres escapados e espaços.
O mais importante é manter as mesmas regras na web, mobile e backend para que os usuários não vejam erros inconsistentes.
Quando o suporte perguntar por que um email foi rejeitado, “inválido” não ajuda. Registre um pequeno conjunto de códigos de motivo (por exemplo: CONTROL_CHAR, PARSE_FAIL, LENGTH, DOMAIN_LABEL). Isso facilita diagnosticar picos e ajuda a encontrar problemas como um teclado iOS que insere uma newline oculta.
Um validador é tão bom quanto os testes que garantem seu comportamento. Mantenha um conjunto pequeno de “deve passar” baseado em cadastros reais, um conjunto “deve falhar” para rejeições universais e um conjunto de casos extremos para armadilhas do parser.
Exemplos que devem passar:
Exemplos que devem falhar:
plainaddress (sem @)alex@ (sem domínio)@example.com (sem parte local)[email protected] (ponto duplo na parte local)Se decidir suportar strings entre aspas, adicione testes explícitos como \"john..doe\"@example.com e \"john\\\"doe\"@example.com. Se decidir não suportá-las, mantenha os testes igualmente, mas marque-os como rejeições por política para que a escolha fique visível.
Não pare em apenas passar/falhar. Armazene códigos de motivo esperados para que falhas sejam acionáveis.
{ "input": "[email protected]", "expected": "fail", "reason": "LOCALPART_DOT_SEQUENCE" }
Execute a mesma suíte em todos os lugares que você valida: web, mobile, backend e qualquer fluxo de autenticação de terceiros. É aí que as divergências geralmente aparecem.
Se quiser menos bugs de cadastro e menos tickets “por que este email não funciona?”, mantenha suas regras de sintaxe curtas e consistentes. Um limite prático fica assim:
@, com pelo menos um caractere em cada ladoDecida uma vez e documente: se aceita partes locais entre aspas como \"john smith\"@example.com. Elas são válidas segundo a RFC 5322, mas raras em cadastros e frequentemente maltratadas por sistemas a jusante.
Depois da sintaxe, adicione as checagens que a sintaxe não cobre: verifique se o domínio existe, cheque registros MX e filtre provedores descartáveis e armadilhas conhecidas. Se preferir não manter essas camadas internamente, Verimail (verimail.co) é uma API de validação de email que executa checagens de sintaxe junto com verificação de domínio, lookup MX e correspondência de descartáveis e blocklists, para que você mantenha a lógica do cadastro consistente sem colocar tudo em uma única regex.