Langsung ke konten
Integration

Cara memvalidasi email di Node.js tanpa menginstal paket

| 7 min read

Tiga panggilan API memeriksa sintaksis, data MX, dan domain sekali pakai. Tidak ada instalasi npm, tidak ada file regex, tidak ada batas waktu SMTP. Berfungsi dari pengambilan di versi Node.js apa pun.

Email validation interface on a laptop screen
Photo by Stephen Phillips on Unsplash

Regex menangkap format. Ia merindukan segalanya. user@fakdomain123.com berlalu. user@mailinator.com berlalu. admin@company.com (alamat berbasis peran yang harus Anda tandai) lolos. Setiap regex yang Anda salin dari Stack Overflow memiliki titik buta yang sama: regex memvalidasi karakter, bukan infrastruktur.

paket npm juga tidak menyelesaikan masalah ini. email-validator menambahkan ketergantungan dan masih hanya memeriksa format. deep-email-validator melakukan pemeriksaan SMTP, yang menyebabkan waktu mati di belakang firewall dan membuat IP server Anda masuk dalam daftar blokir oleh penyedia email.

Anda memerlukan tiga pemeriksaan: sintaksis, data MX, dan deteksi penyedia sekali pakai. Botoi API melakukan ketiganya dalam satu POST. Tidak ada instalasi. Tidak ada file regex. Tidak ada koneksi SMTP.

Panggilan API

Satu perintah curl untuk melihat bentuk respon:

curl -X POST https://api.botoi.com/v1/email/validate \\
  -H "Content-Type: application/json" \\
  -d '{"email": "test@tempmail.xyz"}'

Responsnya memberi tahu Anda segalanya tentang alamat tersebut:

{
  "success": true,
  "data": {
    "email": "test@tempmail.xyz",
    "is_valid": false,
    "reason": "no_mx_records",
    "is_free": false,
    "is_role": false,
    "is_disposable": true,
    "domain": "tempmail.xyz",
    "format_valid": true
  }
}

format_valid mengkonfirmasi sintaksisnya. is_valid combines format, MX, and deliverability into a single boolean. is_disposable penyedia layanan sekali pakai bendera. is_role menangkap alamat seperti admin@ Dan info@. reason memberi tahu Anda mengapa validasi gagal kapan is_valid adalah salah.

Integrasi Node.js: Rute pendaftaran ekspres

Berikut penangan rute Express lengkap yang memvalidasi email di POST /signup menggunakan pengambilan asli. Pola fail-open memastikan penghentian botoi tidak pernah memblokir pendaftaran sebenarnya:

import express from 'express';

const app = express();
app.use(express.json());

app.post('/signup', async (req, res) => {
  const { email, password } = req.body;

  if (!email || !password) {
    return res.status(400).json({ error: 'Email and password are required' });
  }

  // Validate email before creating the account
  try {
    const validation = await fetch('https://api.botoi.com/v1/email/validate', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': \`Bearer \${process.env.BOTOI_API_KEY}\`,
      },
      body: JSON.stringify({ email }),
      signal: AbortSignal.timeout(3000),
    });

    const result = await validation.json();

    if (result.success && !result.data.is_valid) {
      return res.status(422).json({
        error: 'Invalid email address',
        reason: result.data.reason,
      });
    }
  } catch {
    // Fail open: if the API is unreachable, let the signup proceed
    console.warn('Email validation API unreachable, skipping check');
  }

  // Email passed validation; continue with account creation
  // await createUser(email, password);

  return res.status(201).json({ message: 'Account created' });
});

app.listen(3000);

Rute menolak email yang tidak valid dengan 422 dan spesifiknya reason dari API. Jika API tidak dapat dijangkau, pendaftaran akan dilanjutkan. Anda menukarkan cek yang terlewat untuk aliran pengguna yang tidak terputus.

Validasi tiga lapis

Itu /v1/email/validate titik akhir mencakup dasar-dasarnya. Untuk pemeriksaan menyeluruh, gabungkan tiga titik akhir:

  • /v1/email/validate untuk sintaks dan format
  • /v1/email-mx/verify untuk verifikasi data MX
  • /v1/disposable-email/check untuk deteksi sekali pakai

Fungsi pembantu ini memanggil ketiganya dan mengembalikan hasil terstruktur:

interface ValidationResult {
  valid: boolean;
  formatValid: boolean;
  mxValid: boolean;
  isDisposable: boolean;
  reason: string | null;
}

const API_BASE = 'https://api.botoi.com/v1';
const headers = {
  'Content-Type': 'application/json',
  'Authorization': \`Bearer \${process.env.BOTOI_API_KEY}\`,
};

async function validateEmail(email: string): Promise<ValidationResult> {
  const result: ValidationResult = {
    valid: true,
    formatValid: false,
    mxValid: false,
    isDisposable: false,
    reason: null,
  };

  // Layer 1: Syntax and format check
  const formatRes = await fetch(\`\${API_BASE}/email/validate\`, {
    method: 'POST',
    headers,
    body: JSON.stringify({ email }),
    signal: AbortSignal.timeout(3000),
  });
  const formatData = await formatRes.json();

  if (!formatData.success || !formatData.data.format_valid) {
    return { ...result, valid: false, reason: 'invalid_format' };
  }
  result.formatValid = true;

  // Layer 2: MX record verification
  const mxRes = await fetch(\`\${API_BASE}/email-mx/verify\`, {
    method: 'POST',
    headers,
    body: JSON.stringify({ email }),
    signal: AbortSignal.timeout(3000),
  });
  const mxData = await mxRes.json();

  if (!mxData.success || !mxData.data.has_mx) {
    return { ...result, valid: false, reason: 'no_mx_records' };
  }
  result.mxValid = true;

  // Layer 3: Disposable provider detection
  const dispRes = await fetch(\`\${API_BASE}/disposable-email/check\`, {
    method: 'POST',
    headers,
    body: JSON.stringify({ email }),
    signal: AbortSignal.timeout(3000),
  });
  const dispData = await dispRes.json();

  if (dispData.success && dispData.data.is_disposable) {
    return { ...result, valid: false, isDisposable: true, reason: 'disposable_provider' };
  }

  return result;
}

Gunakan seperti ini:

const result = await validateEmail('user@tempmail.xyz');

if (!result.valid) {
  console.log(\`Rejected: \${result.reason}\`);
  // Rejected: disposable_provider
}

Setiap lapisan menangkap kelas email buruk yang berbeda. Pemeriksaan format menghentikan input sampah. Pemeriksaan MX menghentikan domain yang ditemukan. Cek sekali pakai menghentikan pendaftaran sekali pakai. Bersama-sama, mereka menutupi celah yang dibiarkan terbuka oleh regex.

Menambahkan ke rute API Next.js

Logika yang sama berfungsi di pengendali rute Router Aplikasi Next.js di app/api/validate-email/route.ts. Versi ini menjalankan pemeriksaan format dan pemeriksaan sekali pakai secara paralel untuk memotong latensi:

import { NextResponse } from 'next/server';

const API_BASE = 'https://api.botoi.com/v1';
const headers = {
  'Content-Type': 'application/json',
  'Authorization': \`Bearer \${process.env.BOTOI_API_KEY}\`,
};

export async function POST(req: Request) {
  const body = await req.json();
  const email = body.email?.trim().toLowerCase();

  if (!email) {
    return NextResponse.json(
      { error: 'Email is required' },
      { status: 400 }
    );
  }

  try {
    // Run format check and disposable check in parallel
    const [formatRes, dispRes] = await Promise.all([
      fetch(\`\${API_BASE}/email/validate\`, {
        method: 'POST',
        headers,
        body: JSON.stringify({ email }),
        signal: AbortSignal.timeout(3000),
      }),
      fetch(\`\${API_BASE}/disposable-email/check\`, {
        method: 'POST',
        headers,
        body: JSON.stringify({ email }),
        signal: AbortSignal.timeout(3000),
      }),
    ]);

    const [formatData, dispData] = await Promise.all([
      formatRes.json(),
      dispRes.json(),
    ]);

    if (formatData.success && !formatData.data.format_valid) {
      return NextResponse.json(
        { valid: false, reason: 'Invalid email format' },
        { status: 422 }
      );
    }

    if (dispData.success && dispData.data.is_disposable) {
      return NextResponse.json(
        { valid: false, reason: 'Disposable emails are not allowed' },
        { status: 422 }
      );
    }

    // Then check MX records
    const mxRes = await fetch(\`\${API_BASE}/email-mx/verify\`, {
      method: 'POST',
      headers,
      body: JSON.stringify({ email }),
      signal: AbortSignal.timeout(3000),
    });
    const mxData = await mxRes.json();

    if (mxData.success && !mxData.data.has_mx) {
      return NextResponse.json(
        { valid: false, reason: 'Email domain has no mail server' },
        { status: 422 }
      );
    }

    return NextResponse.json({ valid: true });
  } catch {
    // Fail open on API errors
    return NextResponse.json({ valid: true });
  }
}

Hubungi rute ini dari formulir pendaftaran Anda onBlur handler untuk memvalidasi email sebelum pengguna mengirimkan. Paralel Promise.all menjaga waktu respons di bawah 200 ms untuk sebagian besar permintaan.

Menangani kasus tepi

Tiga pola membuat validator naif tersandung:

Domain penampung semua

Beberapa domain menerima email di alamat mana pun. anything@catch-all-domain.com tidak akan memantul, tapi kotak suratnya mungkin tidak ada. Pemeriksaan MX mengonfirmasi bahwa domain tersebut memiliki server email. Mengonfirmasi kotak surat tertentu memerlukan pengiriman email, yang sengaja dihindari oleh pendekatan ini. Untuk sebagian besar alur pendaftaran, verifikasi tingkat domain sudah cukup.

Alamat berbasis peran

Alamat seperti admin@, info@, Dan support@ adalah kotak masuk bersama. Aturan tersebut valid, namun merupakan kandidat yang buruk untuk kepemilikan akun karena tidak ada satu orang pun yang mengontrolnya. API menandainya dengan is_role: true. Anda dapat memperingatkan pengguna atau memblokir pendaftaran berdasarkan kebutuhan produk Anda.

Ditambah pengalamatan

user+tag@gmail.com mengirimkan ke user@gmail.com. Ini adalah fitur yang sah, bukan penyalahgunaan. Namun ini memungkinkan satu orang membuat banyak akun dengan kotak surat yang sama. Jika Anda ingin mencegah hal ini, lepaskan + akhiran sebelum validasi dan simpan alamat yang dinormalisasi.

Berikut fungsi yang menangani ketiganya:

async function validateEmailStrict(email: string): Promise<{
  valid: boolean;
  warnings: string[];
  reason: string | null;
}> {
  const warnings: string[] = [];

  // Check for plus addressing (user+tag@gmail.com)
  const localPart = email.split('@')[0];
  if (localPart.includes('+')) {
    warnings.push('plus_addressing');
  }

  const res = await fetch('https://api.botoi.com/v1/email/validate', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': \`Bearer \${process.env.BOTOI_API_KEY}\`,
    },
    body: JSON.stringify({ email }),
    signal: AbortSignal.timeout(3000),
  });

  const data = await res.json();

  if (!data.success) {
    return { valid: false, warnings, reason: 'api_error' };
  }

  // Flag role-based addresses (admin@, info@, support@)
  if (data.data.is_role) {
    warnings.push('role_based_address');
  }

  // Reject disposable providers
  if (data.data.is_disposable) {
    return { valid: false, warnings, reason: 'disposable_provider' };
  }

  // Reject domains with no MX records
  if (!data.data.is_valid && data.data.reason === 'no_mx_records') {
    return { valid: false, warnings, reason: 'no_mx_records' };
  }

  return { valid: data.data.is_valid, warnings, reason: null };
}
const result = await validateEmailStrict('admin+test@example.com');
// {
//   valid: true,
//   warnings: ['plus_addressing', 'role_based_address'],
//   reason: null
// }

paket npm vs. pendekatan API

Fitur validator email validator email dalam botoi API
Ketergantungan 1 5+ 0 (pengambilan asli)
Pemeriksaan format Ya Ya Ya
Pemeriksaan MX TIDAK Ya (SMTP) Ya (DNS)
Deteksi sekali pakai TIDAK Ya (daftar lokal) Ya (700+ domain)
Penyelidikan SMTP TIDAK Ya (tidak dapat diandalkan) Tidak (berbasis DNS)
Firewall aman Ya TIDAK Ya
Pemeliharaan Anda memperbarui Anda memperbarui Pembaruan API

Pendekatan paket npm menempatkan logika validasi dan datanya (daftar domain, pola regex) di basis kode Anda. Anda memiliki pembaruannya. Saat penyedia sekali pakai baru diluncurkan, seseorang perlu membuka PR untuk menambahkannya. Pendekatan API membongkar pemeliharaan tersebut. Daftar domain memperbarui sisi server. Kode Anda tetap sama.

Imbalannya: API menambahkan ketergantungan jaringan. Pola fail-open yang ditunjukkan pada contoh Express dan Next.js menangani ini. Jika API tidak aktif, validasi lolos dan Anda mengandalkan perlindungan pendaftaran lainnya (konfirmasi email, pembatasan tarif) sampai API pulih.

FAQ

Bagaimana cara memvalidasi alamat email di Node.js tanpa menginstal paket?
Gunakan API pengambilan asli untuk memanggil titik akhir validasi seperti API email botoi. Kirim permintaan POST dengan alamat email, dan API mengembalikan validitas format, status data MX, dan deteksi penyedia sekali pakai. Tidak perlu instalasi npm, tidak perlu pemeliharaan regex, dan tidak diperlukan koneksi SMTP.
Apa API validasi email terbaik untuk Node.js?
API terbaik menggabungkan tiga pemeriksaan dalam satu panggilan: validasi sintaksis, verifikasi data MX, dan deteksi domain sekali pakai. API botoi mencakup ketiganya dan mengembalikan hasil dalam waktu kurang dari 100 md. Ia berfungsi dari versi Node.js apa pun yang mendukung pengambilan (18+), dan tingkat gratis menangani 100 permintaan per hari.
Bagaimana cara memeriksa apakah alamat email ada tanpa mengirim pesan?
Anda dapat memverifikasi bahwa domain memiliki data MX yang valid menggunakan pemeriksaan berbasis DNS, yang mengonfirmasi bahwa server email ada dan menerima koneksi. Titik akhir botoi /v1/email-mx/verify melakukan ini melalui DNS tanpa membuka koneksi SMTP, sehingga IP Anda tidak pernah masuk daftar blokir. Pendekatan ini mengonfirmasi bahwa domain tersebut asli tetapi tidak dapat mengonfirmasi apakah kotak surat tertentu ada.
Bagaimana cara mendeteksi alamat email sekali pakai di Node.js?
Hubungi titik akhir botoi /v1/disposable-email/check dengan alamat email. Ia memeriksa terhadap 700+ penyedia sekali pakai yang dikenal dan mengembalikan boolean is_disposable. Anda dapat menggabungkan ini dengan validasi format dan pemeriksaan MX untuk pipeline validasi menyeluruh, semuanya menggunakan panggilan pengambilan asli.
Apakah regex cukup untuk validasi email di Node.js?
Tidak. Regex hanya memeriksa format. Email seperti user@fakdomain123.com melewati regex tetapi tidak memiliki server email. user@mailinator.com melewati regex tetapi merupakan alamat sekali pakai. Validasi yang efektif memerlukan pemeriksaan data MX dan penyaringan penyedia sekali pakai, yang tidak dapat dilakukan oleh regex.

Mulai membangun dengan botoi

150+ endpoint API untuk pencarian, pemrosesan teks, pembuatan gambar, dan utilitas developer. Paket gratis, tanpa kartu kredit.