Artigo Build·Desenvolvimento·13 min de leitura de leitura

Como Validar E-mail em JavaScript (2026): Regex, HTML5 e Validação Real

Validar e-mail parece trivial — até você receber 30% de cadastros com 'asdf@asdf' e tentar enviar campanha. Este guia cobre as três camadas (sintaxe, DNS, SMTP), mostra regex que funciona, e explica quando cada nível de validação compensa.

Vitor Morais

Por Vitor Morais

Fundador do MochaLabz ·

✉️

Valide e-mails em massa

Cole uma lista, detecte descartáveis e exporte só os endereços válidos.

Usar validador →

Validar e-mail em JavaScript é uma daquelas tarefas que parecem simples e têm três níveis de complexidade dependendo do que você chama de “válido”. Formato correto? Regex resolve. Domínio que aceita e-mail? Precisa checar DNS. Mailbox que realmente existe? Aí a conversa é com SMTP. Cada camada cobre um tipo de erro e custa mais que a anterior.

Este guia cobre os três níveis, mostra regex que funciona em 99% dos casos, compara bibliotecas populares e aponta os erros clássicos que fazem você rejeitar e-mails legítimos ou aceitar lixo.

Os três níveis de validação

Níveis de validação de e-mail
CritérioO que testaQuando usaCusto
Sintaxe (regex)Formato correto do endereçoTodo formulário webZero
Validação HTML5Formato básico + UX do navegadorQualquer input em HTMLZero
DNS (MX record)Domínio aceita e-mailCadastro com alto custo de contaBaixo
SMTP (ping ao servidor)Mailbox específico existeCampanhas grandes, cobrançaMédio
API comercialTudo acima + reputaçãoE-mail é crítico para receitaAlto

Validação com regex: o básico que resolve 99% dos casos

Um regex funcional para formulários web precisa aceitar o que é válido na prática — não o que é válido no RFC 5322. Esse regex cobre o caso real:

function isEmailValid(email) { const regex = /^[\w.+-]+@[\w-]+(\.[\w-]+)+$/; return regex.test(email.trim().toLowerCase()); } isEmailValid("joao@exemplo.com"); // true isEmailValid("joao+tag@gmail.com"); // true isEmailValid("maria@sub.exemplo.com.br"); // true isEmailValid("invalido"); // false isEmailValid("sem@dominio"); // false isEmailValid("@exemplo.com"); // false

O que esse regex aceita

  • Letras, números, ponto, underscore, traço e plus na parte local.
  • Domínio com hífen.
  • Subdomínios (mail.exemplo.com).
  • TLDs compostos (.com.br, .co.uk).

O que esse regex ainda deixa passar

  • Espaço em branco (use .trim() antes).
  • Maiúsculas/minúsculas (normalize com .toLowerCase()).
  • TLD inventado (.xyz, .pizza — são todos TLDs reais).
  • Domínio inexistente (precisa DNS para pegar).

Atenção

Não tente usar regex RFC 5322 “oficial”. Ele tem 500+ caracteres, é ilegível e rejeita muitos e-mails que os servidores modernos aceitam sem problema. A internet evoluiu além do RFC estrito — seu regex também deve.

HTML5 type=email: validação de graça no navegador

Adicionar type="email" ao input habilita três coisas sem uma linha de JavaScript:

  • Validação de formato ao submeter o formulário (mensagem nativa do navegador).
  • Teclado otimizado no mobile (mostra arroba e ponto em destaque).
  • Ícone de e-mail em autofill de senha/contato.
<form> <label for="email">Seu e-mail</label> <input type="email" id="email" name="email" required placeholder="voce@exemplo.com" /> <button type="submit">Enviar</button> </form>

A validação HTML5 usa regex simples internamente — aceita a@b, o que é tecnicamente válido mas raramente útil. Combine com regex próprio para reforçar:

const form = document.querySelector("form"); const input = document.querySelector("#email"); form.addEventListener("submit", (e) => { if (!isEmailValid(input.value)) { e.preventDefault(); input.setCustomValidity("Digite um e-mail válido, como voce@exemplo.com"); input.reportValidity(); } }); input.addEventListener("input", () => { input.setCustomValidity(""); // limpa mensagem customizada ao digitar });

Validação em React com feedback imediato

Em React, o padrão moderno combina onBlur para validar quando o usuário sai do campo, não a cada tecla (evita mostrar “inválido” enquanto ele ainda está digitando).

import { useState } from "react"; function isEmailValid(email: string): boolean { return /^[\w.+-]+@[\w-]+(\.[\w-]+)+$/.test(email.trim().toLowerCase()); } export function EmailInput() { const [email, setEmail] = useState(""); const [error, setError] = useState<string | null>(null); const handleBlur = () => { if (!email) { setError(null); return; } setError(isEmailValid(email) ? null : "E-mail inválido"); }; return ( <div> <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} onBlur={handleBlur} required /> {error && <p className="text-red-600 text-sm mt-1">{error}</p>} </div> ); }

Validação em Node.js (backend)

O backend deve revalidar — nunca confie no cliente. Em uma rota API:

// Next.js API route (app router) import { NextResponse } from "next/server"; const EMAIL_REGEX = /^[\w.+-]+@[\w-]+(\.[\w-]+)+$/; export async function POST(req: Request) { const { email } = await req.json(); if (!email || typeof email !== "string") { return NextResponse.json( { error: "Campo e-mail obrigatório" }, { status: 400 }, ); } const normalized = email.trim().toLowerCase(); if (!EMAIL_REGEX.test(normalized)) { return NextResponse.json( { error: "Formato de e-mail inválido" }, { status: 400 }, ); } // prossiga com inserção no banco, envio de confirmação, etc. return NextResponse.json({ ok: true }); }

Bibliotecas populares comparadas

Bibliotecas de validação de e-mail em JavaScript
CritérioTamanhoValida DNSMelhor para
validator.js17 KBNãoValidação sintática robusta
email-validator3 KBNãoSimples, leve, edge-ready
deep-email-validatorN/ASimNode.js com verificação SMTP
disposable-email-domains200 KBN/ALista de domínios descartáveis

validator.js (exemplo)

import validator from "validator"; validator.isEmail("joao@exemplo.com"); // true validator.isEmail("joao@exemplo.com", { allow_utf8_local_part: false, require_tld: true, domain_specific_validation: true, }); // true (com opções)

Validação DNS: checar se o domínio recebe e-mail

Regex aceita email@empresainexistente999.com. Só o DNS sabe se essa empresa existe e tem mail server. Em Node.js, use o módulo nativo:

import { resolveMx } from "node:dns/promises"; async function hasMxRecord(domain: string): Promise<boolean> { try { const records = await resolveMx(domain); return records.length > 0; } catch { return false; } } async function validateEmailDeep(email: string): Promise<{ valid: boolean; reason?: string; }> { if (!/^[\w.+-]+@[\w-]+(\.[\w-]+)+$/.test(email)) { return { valid: false, reason: "Formato inválido" }; } const domain = email.split("@")[1]; const mx = await hasMxRecord(domain); if (!mx) { return { valid: false, reason: "Domínio não aceita e-mail" }; } return { valid: true }; }

Contexto

DNS check adiciona 50–500ms de latência. Use só em fluxos onde o valor justifica — não em cada tecla de digitação. Para formulários de alto volume, rode DNS no backend depois do submit (assíncrono) e confirme por e-mail, não no cliente.

Bloqueando e-mails descartáveis

Lista atualizada mantida pela comunidade (3000+ domínios):

import disposableDomains from "disposable-email-domains"; function isDisposable(email: string): boolean { const domain = email.split("@")[1]?.toLowerCase(); return disposableDomains.includes(domain); } isDisposable("joao@mailinator.com"); // true isDisposable("joao@gmail.com"); // false isDisposable("joao@10minutemail.com"); // true

Erros clássicos que rejeitam e-mails legítimos

  • Bloquear plus (+): joao+newsletter@gmail.com é RFC válido e usado por milhões. Regex ruim rejeita.
  • Limitar domínio a 2–3 caracteres após ponto: TLDs modernos têm 6+ caracteres (.museum, .travel, .photography).
  • Rejeitar hífen em domínio: meu-site.com.br é válido.
  • Não aceitar subdomínios: joao@mail.empresa.com.brprecisa passar.
  • Case-sensitivity: e-mails são case-insensitive na parte do domínio. Normalize tudo com toLowerCase().
  • Deixar espaços passarem: trim antes de validar, sempre.

Confirmação por e-mail (double opt-in)

A única forma 100% confiável de validar um e-mail é enviar uma mensagem com link único e esperar o usuário clicar. Requer backend e serviço de envio (Resend, SendGrid, Postmark, AWS SES). Fluxo padrão:

  1. Usuário submete e-mail no cadastro.
  2. Regex valida formato.
  3. Backend cria registro marcado como “pendente”.
  4. Sistema envia e-mail com token único.
  5. Usuário clica no link.
  6. Backend marca registro como “confirmado”.
  7. Só agora o e-mail é considerado válido.

Dica

Double opt-in é obrigatório para newsletters na União Europeia (GDPR) e boa prática global. Reduz taxa de bounce em 80% e melhora reputação do seu domínio de envio — o que aumenta entregabilidade futura.

Serviços comerciais de validação

Quando e-mail é crítico para o negócio (outbound sales, cobrança, marketing em escala), considere API paga:

  • ZeroBounce: verificação SMTP + score de risco + detecção de spam traps. ~US$ 0,008 por e-mail.
  • NeverBounce: similar, bulk pricing menor. Boa integração com Mailchimp.
  • Hunter Email Verifier: B2B-focused. Integração com CRMs.
  • Emailable: preços agressivos, rate limit alto.

Limpeza de lista existente

Se você já tem uma base de e-mails com bounces frequentes, o caminho é limpar antes de enviar de novo:

  1. Exporte a lista em CSV.
  2. Valide sintaxe local com regex — descarta erros óbvios.
  3. Passe por serviço de validação comercial (bulk).
  4. Segmente resultado: válidos, risky, inválidos.
  5. Envie só para válidos. Remova inválidos permanentemente.
  6. Considere re-engajar risky com campanha pequena e monitorar bounce.

Performance: validando grandes listas

Validar 100.000 e-mails com regex é questão de milissegundos. Com DNS, questão de minutos. Com SMTP, questão de horas. Estratégias:

  • Cache de DNS: muitos e-mails compartilham domínio (@gmail.com aparece milhares de vezes). Cache o resultado por domínio.
  • Paralelização com limite: DNS suporta concorrência, mas excesso fura rate limit. Use Promise.all com batch de 10–50.
  • Fila de background: para grandes volumes, use BullMQ/Sidekiq. Não trave o request HTTP.

Segurança: evitando abuso

  • Rate limit no cadastro: limite tentativas por IP (ex.: 5 em 10 minutos) para evitar scraper de contas.
  • Proteção contra enumeration: nunca revele “e-mail já cadastrado” vs “e-mail inválido” com mensagens diferentes em login público.
  • Sanitize antes de exibir: se você ecoa o e-mail no HTML, escape para evitar XSS (React faz automaticamente, PHP e outros não).
  • Não log de e-mails completos: em ambiente de produção, mascare ou hash o e-mail nos logs para LGPD/GDPR.

Validação em uma frase

Validação de e-mail em JavaScript é camadas: regex no cliente para UX, regex no servidor como gatekeeper, DNS opcional quando custo de conta importa, e confirmação por e-mail quando você precisa certeza. Use a camada compatível com o valor em jogo — nem de menos, nem pesadão demais.

Perguntas frequentes

Regex é suficiente para validar e-mail?+

Para a maioria dos formulários, sim. Um regex bem escrito filtra 99% das entradas inválidas (vazio, sem @, sem domínio). Mas regex não verifica se o e-mail existe de verdade — só se o formato está correto. Para registro de conta, considere enviar e-mail de confirmação. Para campanhas grandes, valide com API externa (SMTP check, DNS MX). Regex é porta de entrada, não garantia de entregabilidade.

Qual o melhor regex para validar e-mail em JavaScript?+

Depende do rigor desejado. Para formulários web comuns, o regex /^[\w.+-]+@[\w-]+\.[\w.-]+$/ cobre 99% dos casos válidos. Para seguir RFC 5322 completamente, o regex fica quase inutilizável de tão longo. Na prática, use regex simples e valide real existência via API. Evite regex copiado de StackOverflow sem entender — muitos rejeitam e-mails legítimos (plus signs, domínios com hífen).

Devo validar no frontend ou no backend?+

Nos dois. Frontend dá feedback imediato pro usuário (UX); backend é a única validação confiável (segurança). Cliente pode desabilitar JavaScript, manipular DOM ou enviar request direto via curl. Regra de ouro: frontend valida para melhorar UX, backend valida como se frontend não existisse. Nunca confie só em validação cliente.

Qual a diferença entre type=email e regex customizada?+

O atributo HTML5 type=email habilita validação nativa do navegador com regex simples embutida. Vantagem: zero JavaScript necessário, UX padrão (teclado otimizado no mobile, ícone correto). Desvantagem: não controle o regex, mensagens de erro em idioma do navegador, não valida presença de TLD. Para sites modernos, use type=email + regex próprio combinados — redundância barata.

Como validar se o e-mail realmente existe?+

Três camadas. (1) Sintaxe — regex. (2) DNS — verificar se o domínio tem registros MX configurados (existe servidor de e-mail). (3) SMTP — tentar conectar no servidor SMTP e perguntar se o mailbox existe (sem enviar mensagem). Camadas 2 e 3 exigem backend. Bibliotecas como email-validator (Python) e deep-email-validator (Node.js) automatizam. Serviços como ZeroBounce e NeverBounce oferecem API comercial.

Devo bloquear e-mails descartáveis (Mailinator, 10minutemail)?+

Depende. Para SaaS com trial gratuito e custo por conta, sim — descartáveis indicam baixa intenção e fraude. Para newsletter ou download de conteúdo, bloquear é discutível (pode afastar audiência curiosa). Bibliotecas mantêm listas atualizadas de domínios descartáveis (disposable-email-domains em npm tem 4000+ domínios). O trade-off é falso positivo — alguns usuários legítimos usam domínios categorizados como descartáveis.

Por que o e-mail com + (plus) às vezes é rejeitado?+

Plus addressing (joao+newsletter@gmail.com) é recurso oficial do RFC, suportado por Gmail, Outlook, iCloud e outros. Permite ao usuário criar apelidos sem criar conta nova. Muitos sistemas validam erroneamente com regex que rejeita o +, quebrando o recurso e frustrando usuários que usam plus para organizar inboxes. Seu regex deve aceitar + na parte local obrigatoriamente.

E-mails com acentos e UTF-8 são válidos?+

Tecnicamente sim, desde 2012 (RFC 6531). Um endereço como joão@exemplo.com.br é válido no padrão internacional. Na prática, muitos servidores ainda não suportam, e a entregabilidade é irregular. Para formulários no Brasil, aceite ASCII (letras sem acento) e rejeite UTF-8 com mensagem clara (ex.: &ldquo;use caracteres sem acento&rdquo;). É compromisso entre padrão e realidade.

#javascript#validação#email#regex#html5#typescript#react#node.js#dns#formulário

Artigos relacionados