Validar email no formulário de cadastro com API no servidor

Equipe editorial do 1-email.com · Revisado em 9 de outubro de 2026 · Política editorial

Conecte um formulário a um backend local Node.js sem colocar a chave de produção no navegador.

Baixe e execute localmente

Node.js 22+. Não exige instalar pacotes. Baixe todos os arquivos abaixo na mesma pasta e execute:

node signup-server.mjs

Abra http://127.0.0.1:3000. O navegador chama o backend local; o backend chama a API. Este exemplo não cria contas nem armazena contatos.

Arquivos de código

verify.mjs Baixar

// Node.js 22+: server code. Only the public sandbox key is supplied by default.
export class VerificationError extends Error {
  constructor(status, message, retryAfter = null) {
    super(message); this.status = status; this.retryAfter = retryAfter;
  }
}
export async function verifyEmail(email, {key = process.env.EEV_API_KEY || 'eev_sandbox_key', fetchFn = fetch} = {}) {
  const url = new URL('https://api.easyemailverification.com/v1/verify');
  url.searchParams.set('email', email);
  let response;
  try {
    response = await fetchFn(url, {
      headers: {'X-API-Key': key, Accept: 'application/json'},
      signal: AbortSignal.timeout(30000)
    });
  } catch {
    throw new VerificationError(503, 'No reliable result; review the request before retrying.');
  }
  if (!response.ok) {
    const messages = {402: 'No credits: check your account before retrying.',
      429: 'Rate limited: wait before another request; respect Retry-After.'};
    throw new VerificationError(response.status, messages[response.status] || 'Verification request failed.', response.headers.get('Retry-After'));
  }
  let data;
  try { data = await response.json(); } catch { throw new VerificationError(502, 'Invalid JSON response.'); }
  if (!data || !['valid','invalid','unknown'].includes(data.result)) {
    throw new VerificationError(502, 'Unexpected API response; do not classify the address.');
  }
  return data;
}
export function classify(data) {
  if (data.result === 'invalid') return 'invalid';
  if (data.result === 'unknown' || data.disposable || data.accept_all || data.safe_to_send !== true) return 'review';
  return 'passed_checks';
}

signup-server.mjs Baixar

// Local teaching example; creates no accounts and stores no submitted addresses.
import {createServer} from 'node:http';
import {readFile} from 'node:fs/promises';
import {verifyEmail, classify} from './verify.mjs';
const form = await readFile(new URL('./signup.html', import.meta.url));
const server = createServer(async (req, res) => {
  const send = (status, body) => {
    res.writeHead(status, {'Content-Type': 'application/json', 'Cache-Control':'no-store'});
    res.end(JSON.stringify(body));
  };
  if (req.method === 'GET' && req.url === '/') {
    res.writeHead(200, {'Content-Type':'text/html; charset=utf-8'}); return res.end(form);
  }
  if (req.method !== 'POST' || req.url !== '/verify') return send(404, {message:'Not found'});
  if ((req.headers['content-type'] || '').split(';')[0] !== 'application/json') return send(415, {message:'Use JSON'});
  let body = ''; let bytes = 0;
  try {
    for await (const chunk of req) {
      bytes += chunk.length;
      if (bytes > 2048) return send(413, {message:'Request too large'});
      body += chunk.toString('utf8');
    }
    let input;
    try { input = JSON.parse(body); } catch { return send(400, {message:'Invalid JSON'}); }
    if (typeof input?.email !== 'string' || input.email.length > 254 || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(input.email)) {
      return send(400, {message:'Enter one complete address'});
    }
    const data = await verifyEmail(input.email);
    // Keep unknown and catch-all separate from a confirmed rejection.
    send(200, {decision: classify(data), result: data.result, reason: data.reason,
      did_you_mean: data.did_you_mean || null});
  } catch (error) {
    if (!res.headersSent) send(error.status || 503, {message:error.message || 'Check unavailable'});
  }
});
server.requestTimeout = 35000;
server.listen(3000, '127.0.0.1', () => console.log('Demo: http://127.0.0.1:3000'));

signup.html Baixar

<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Signup verification sandbox demo</title>
<style>body{font:18px system-ui;max-width:650px;margin:3rem auto;padding:1rem}input,button{font:inherit;padding:.6rem}pre{white-space:pre-wrap}</style>
<h1>Try a signup check</h1><p>This local demo creates no accounts. Start with a documented sandbox address.</p>
<form id="form"><label for="email">Email address</label><input id="email" name="email" type="email" required value="valid@sandbox.easyemailverification.com"><button>Check</button></form>
<pre id="result" role="status" aria-live="polite"></pre>
<script>
const form = document.getElementById('form'), output = document.getElementById('result');
form.addEventListener('submit', async event => {
  event.preventDefault(); const button = form.querySelector('button'); button.disabled = true;
  output.textContent = 'Checking…';
  try {
    const response = await fetch('/verify', {method:'POST', headers:{'Content-Type':'application/json'},
      body:JSON.stringify({email:document.getElementById('email').value})});
    const result = await response.json();
    output.textContent = `HTTP ${response.status}\n${JSON.stringify(result, null, 2)}`;
  } catch { output.textContent = 'Check unavailable. This is not proof of an invalid address.'; }
  finally { button.disabled = false; }
});
</script></html>

Teste sucesso, incerteza e falhas

Troque o endereço padrão pelo argumento da linha de comando (Python/Node) ou pelo campo do formulário. Use valid, invalid, unknown, catchall, disposable, quota e ratelimit em sandbox.easyemailverification.com. O caso especial typo@gmial.com fornece uma sugestão de correção.

Espere revisão para unknown e sinais de risco. Falta de créditos deve interromper a chamada com 402; limite de chamadas retorna 429. Falhas de rede ou JSON nunca devem gerar classificação valid ou invalid de uma caixa postal.

Antes de ir para produção

Defina EEV_API_KEY no ambiente do servidor. Mantenha o endpoint fixo, use timeout, limite o tamanho da chamada e adicione controles de abuso. Para cadastro real, adicione proteção de origem/CSRF, limites próprios e gestão de consentimento. Não repita uma chamada incerta automaticamente nem troque um endereço com erro silenciosamente.

Fonte primária: Easy API reference. Baixar instruções dos exemplos.

Pronto para endereços reais?

Nós operamos o Easy Email Verification. Crie uma conta gratuita para obter a chave de produção após testar a integração.

Obter uma chave de produção gratuita