تخطي إلى المحتوى
Integration

كيفية التحقق من صحة رسائل البريد الإلكتروني في Node.js دون تثبيت الحزمة

| 7 min read

تقوم ثلاثة استدعاءات لواجهة برمجة التطبيقات (API) بفحص بناء الجملة وسجلات MX والمجالات القابلة للتصرف. لا يوجد تثبيت npm، ولا يوجد ملف regex، ولا توجد مهلة SMTP. يعمل من خلال الجلب في أي إصدار Node.js.

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

تنسيق Regex المصيد. إنه يفتقد كل شيء آخر. user@fakdomain123.com يمر. user@mailinator.com يمر. admin@company.com (عنوان قائم على الدور يجب عليك وضع علامة عليه) يمر. كل تعبير عادي تنسخه من Stack Overflow له نفس النقطة العمياء: فهو يتحقق من صحة الأحرف، وليس البنية التحتية.

حزم npm لا تحل هذا أيضًا. email-validator يضيف تبعية ولا يزال يتحقق من التنسيق فقط. deep-email-validator يقوم بإجراء فحص SMTP، والذي تنتهي مهلته خلف جدران الحماية ويضع عنوان IP الخاص بخادمك في القائمة المحظورة بواسطة موفري البريد.

أنت بحاجة إلى ثلاث عمليات تحقق: بناء الجملة، وسجلات MX، والكشف عن الموفر القابل للتصرف. تعمل واجهة برمجة تطبيقات botoi على تنفيذ المهام الثلاثة في مشاركة واحدة. لا يوجد تثبيت. لا يوجد ملف ريكس. لا يوجد اتصال SMTP.

استدعاء API

أمر تجعيد واحد لرؤية شكل الاستجابة:

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

يخبرك الرد بكل شيء عن العنوان:

{
  "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 يؤكد بناء الجملة. is_valid يجمع بين التنسيق وMX وإمكانية التسليم في قيمة منطقية واحدة. is_disposable أعلام مقدمي رمي. is_role عناوين المصيد مثل admin@ و info@. reason يخبرك لماذا فشل التحقق من الصحة ومتى is_valid غير صحيح.

تكامل Node.js: طريق الاشتراك السريع

إليك معالج المسار السريع الكامل الذي يتحقق من صحة البريد الإلكتروني على POST /signup باستخدام الجلب الأصلي. يضمن نمط الفتح الفاشل أن انقطاع botoi لا يمنع عمليات الاشتراك الحقيقية مطلقًا:

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);

يرفض المسار رسائل البريد الإلكتروني غير الصالحة التي تحتوي على 422 والمحددة reason من واجهة برمجة التطبيقات. إذا تعذر الوصول إلى واجهة برمجة التطبيقات (API)، فستتم متابعة عملية الاشتراك. You trade a missed check for uninterrupted user flow.

التحقق من صحة ثلاث طبقات

ال /v1/email/validate تغطي نقطة النهاية الأساسيات. لإجراء فحص شامل، قم بدمج ثلاث نقاط نهاية:

  • /v1/email/validate لبناء الجملة والشكل
  • /v1/email-mx/verify للتحقق من سجل MX
  • /v1/disposable-email/check للكشف القابل للتصرف

تستدعي هذه الوظيفة المساعدة الثلاثة جميعها وترجع نتيجة منظمة:

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;
}

استخدامه مثل هذا:

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

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

تلتقط كل طبقة فئة مختلفة من رسائل البريد الإلكتروني السيئة. عمليات التحقق من التنسيق توقف إدخال البيانات المهملة. تقوم عمليات فحص MX بإيقاف المجالات المخترعة. تعمل الشيكات التي يمكن التخلص منها على إيقاف الاشتراكات غير المرغوب فيها. معًا، يغطون الفجوة التي يتركها التعبير العادي مفتوحة.

الإضافة إلى مسار Next.js API

يعمل نفس المنطق في معالج مسار Next.js App Router على app/api/validate-email/route.ts. يقوم هذا الإصدار بتشغيل فحص التنسيق والفحص القابل للتصرف بالتوازي لتقليل زمن الوصول:

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 });
  }
}

اتصل بهذا المسار من نموذج الاشتراك الخاص بك onBlur معالج للتحقق من صحة البريد الإلكتروني قبل إرسال المستخدم. الموازي Promise.all يحافظ على وقت الاستجابة أقل من 200 مللي ثانية لمعظم الطلبات.

التعامل مع حالات الحافة

ثلاثة أنماط تتعثر في أدوات التحقق الساذجة:

مجالات الالتقاط

تقبل بعض النطاقات البريد الإلكتروني على أي عنوان. anything@catch-all-domain.com لن ترتد، ولكن قد لا يكون صندوق البريد موجودًا. يؤكد فحص MX أن المجال يحتوي على خادم بريد. يتطلب تأكيد صندوق البريد المحدد إرسال بريد إلكتروني، وهو ما يتجنبه هذا الأسلوب عن قصد. بالنسبة لمعظم عمليات الاشتراك، يعد التحقق على مستوى النطاق كافيًا.

العناوين المستندة إلى الأدوار

عناوين مثل admin@, info@، و support@ هي صناديق بريد وارد مشتركة. إنها صالحة، ولكنها مرشحة ضعيفة لملكية الحساب لأنه لا يوجد شخص واحد يتحكم فيها. تضع واجهة برمجة التطبيقات (API) علامة عليها is_role: true. يمكنك تحذير المستخدم أو حظر الاشتراك بناءً على احتياجات منتجك.

بالإضافة إلى معالجة

user+tag@gmail.com يسلم ل user@gmail.com. هذه ميزة مشروعة وليست إساءة. ولكنه يتيح لشخص واحد إنشاء العديد من الحسابات بنفس صندوق البريد. إذا كنت تريد منع ذلك، قم بتجريد + لاحقة قبل التحقق من الصحة وتخزين العنوان الذي تمت تسويته.

إليك وظيفة تتعامل مع الثلاثة:

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
// }

حزم npm مقابل نهج API

ميزة مدقق البريد الإلكتروني مدقق البريد الإلكتروني العميق واجهة برمجة تطبيقات بوتوي
التبعيات 1 5+ 0 (جلب أصلي)
فحص التنسيق نعم نعم نعم
فحص MX لا نعم (SMTP) نعم (نظام أسماء النطاقات)
كشف يمكن التخلص منها لا نعم (القائمة المحلية) نعم (+700 نطاق)
فحص SMTP لا نعم (غير موثوق) لا (يعتمد على DNS)
جدار الحماية آمن نعم لا نعم
صيانة قمت بالتحديث قمت بالتحديث تحديثات واجهة برمجة التطبيقات

يضع نهج حزمة npm منطق التحقق وبياناته (قوائم المجال، وأنماط regex) في قاعدة التعليمات البرمجية الخاصة بك. أنت تملك التحديثات. عند إطلاق موفر جديد يمكن التخلص منه، يحتاج شخص ما إلى فتح PR لإضافته. يقوم نهج API بتفريغ تلك الصيانة. يتم تحديث قائمة المجال من جانب الخادم. الرمز الخاص بك يبقى كما هو.

المقايضة: تضيف واجهة برمجة التطبيقات (API) تبعية للشبكة. نمط الفتح الفاشل الموضح في أمثلة Express وNext.js يعالج هذا. إذا كانت واجهة برمجة التطبيقات (API) معطلة، فسيتم تمرير التحقق من الصحة وتعتمد على وسائل حماية الاشتراك الأخرى (تأكيد البريد الإلكتروني، وتحديد المعدل) حتى يتعافى API.

FAQ

كيف يمكنني التحقق من صحة عنوان البريد الإلكتروني في Node.js دون تثبيت الحزمة؟
استخدم واجهة برمجة تطبيقات الجلب الأصلية لاستدعاء نقطة نهاية التحقق من الصحة مثل واجهة برمجة تطبيقات البريد الإلكتروني في botoi. أرسل طلب POST باستخدام عنوان البريد الإلكتروني، وستقوم واجهة برمجة التطبيقات (API) بإرجاع صلاحية التنسيق وحالة سجل MX واكتشاف الموفر القابل للتصرف. لا يلزم تثبيت npm ولا صيانة regex ولا يلزم وجود اتصالات SMTP.
ما هي أفضل واجهة برمجة تطبيقات للتحقق من البريد الإلكتروني لـ Node.js؟
تجمع أفضل واجهة برمجة تطبيقات (API) بين ثلاثة عمليات تحقق في مكالمة واحدة: التحقق من صحة بناء الجملة، والتحقق من سجل MX، واكتشاف النطاق القابل للتصرف. تغطي واجهة برمجة تطبيقات botoi الثلاثة جميعًا وتنتج نتائج أقل من 100 مللي ثانية. وهو يعمل من أي إصدار Node.js يدعم الجلب (18+)، وتتعامل الطبقة المجانية مع 100 طلب يوميًا.
كيف يمكنني التحقق من وجود عنوان بريد إلكتروني دون إرسال رسالة؟
يمكنك التحقق من أن المجال يحتوي على سجلات MX صالحة باستخدام فحص يستند إلى نظام أسماء النطاقات (DNS)، والذي يؤكد وجود خادم البريد ويقبل الاتصالات. تقوم نقطة النهاية botoi /v1/email-mx/verify بذلك عبر DNS دون فتح اتصال SMTP، لذلك لن يتم إدراج عنوان IP الخاص بك في القائمة المحظورة أبدًا. يؤكد هذا الأسلوب أن المجال حقيقي ولكن لا يمكنه التأكد من وجود صندوق بريد محدد.
كيف يمكنني اكتشاف عناوين البريد الإلكتروني التي يمكن التخلص منها في Node.js؟
اتصل بنقطة نهاية botoi /v1/disposable-email/check باستخدام عنوان البريد الإلكتروني. فهو يتحقق من أكثر من 700 من موفري الخدمة المتاحين المعروفين ويعيد قيمة منطقية is_disposable. يمكنك دمج ذلك مع التحقق من صحة التنسيق وفحص MX للحصول على مسار تحقق شامل، كل ذلك باستخدام استدعاءات الجلب الأصلية.
هل regex كافٍ للتحقق من صحة البريد الإلكتروني في Node.js؟
لا، Regex يتحقق فقط من التنسيق. يمر بريد إلكتروني مثل user@fakdomain123.com بالتعبير العادي ولكن لا يحتوي على خادم بريد. يمر user@mailinator.com بالتعبير العادي ولكنه عنوان يمكن التخلص منه. يتطلب التحقق الفعال التحقق من سجلات MX وفحص موفري الخدمة الذين يمكن التخلص منهم، وهو ما لا يستطيع التعبير العادي القيام به.

ابدأ البناء مع botoi

أكثر من 150 نقطة نهاية API للبحث ومعالجة النصوص وتوليد الصور وأدوات المطورين. باقة مجانية، بدون بطاقة ائتمان.