معالجة أخطاء واجهة برمجة البريد الإلكتروني وحدودها: رموز الحالة وإعادة المحاولة والمراقبة

ماذا تعني كل استجابة من API البريد الإلكتروني في Inbixio، وأي الأخطاء تُعاد محاولتها وأيها يُصلح، وكيف تعمل الحدود الشهرية، وكيف تراقب التسليم في بيئة الإنتاج.

إرسال بريد إلكتروني واحد في عرض تجريبي أمر سهل. أما إرسال مئة ألف رسالة شهريًا في بيئة الإنتاج فيعني الاستعداد للحظات التي تسوء فيها الأمور: مفتاح أُلغي، أو بطاقة انتهت صلاحيتها، أو شهر انتهى حدّه أسرع من المتوقع، أو خادم بريد يمرّ بيوم سيئ.

يشرح هذا الدليل كل استجابة تُعيدها نقطة نهاية الإرسال في Inbixio، وما ينبغي أن تفعله شيفرتك حيال كل منها، وكيف تراقب التسليم بعد الإطلاق.

مرحلتان: القبول ثم التسليم

يمرّ استدعاء POST /api/send-email/ بمرحلتين:

  1. طلب API. تتحقق Inbixio من مفتاحك وصلاحياته واشتراكك واستخدامك الشهري وجسم الطلب. فإن كان كل شيء سليمًا، تُعيد 200 وتضيف الرسالة إلى قائمة الإرسال.
  2. التسليم. بعد لحظات تتصل Inbixio بخادم SMTP الخاص بك وتسلّمه الرسالة. تُسجَّل كل رسالة على أنها مُرسلة أو فاشلة، وتغذّي هذه النتائج الأرقام في لوحة التحكم.

إذن تعني 200 “قُبلت للتسليم”، لا “وصلت إلى صندوق الوارد”. المشكلات في المرحلة 1 تعود في صورة أخطاء HTTP يمكن لشيفرتك معالجتها. أما المشكلات في المرحلة 2، مثل كلمة مرور SMTP خاطئة، فتظهر في معدّل التسليم الفاشل في لوحة التحكم. تُجري Inbixio محاولة تسليم واحدة لكل رسالة، ولا تعيد محاولة التسليم الفاشل.

كل استجابة وما يجب فعله

الحالة الجسم المعنى ما يجب أن تفعله شيفرتك
200 {"message": "Email queued successfully."} مقبولة انتهى الأمر
400 {"error": "to_email, subject, and message are required."} حقل مفقود أو فارغ أصلح الطلب؛ لا تُعِد المحاولة
400 {"error": "to_email must be a single valid email address."} ليس عنوانًا صالحًا واحدًا بالضبط أصلح الطلب؛ لا تُعِد المحاولة
400 {"error": "subject must be a single line of at most 500 characters."} الموضوع طويل جدًا أو يحتوي على فاصل أسطر أصلح الطلب؛ لا تُعِد المحاولة
400 {"error": "message must be text of at most 1,000,000 characters."} نص الرسالة كبير جدًا أصلح الطلب؛ لا تُعِد المحاولة
400 {"error": "No SMTP configuration found. Please add an email server first."} لا يوجد خادم مربوط أضف خادمًا من لوحة التحكم
401 {"detail": "API key missing"} لا توجد ترويسة X-API-Key أصلح الإعدادات؛ لا تُعِد المحاولة
401 {"detail": "Invalid API key"} مفتاح خاطئ أو مُجدَّد أو محذوف حدّث المفتاح؛ نبّه فريقك
401 {"detail": "API key access not allowed"} المفتاح مُعطَّل استخدم مفتاحًا آخر؛ نبّه فريقك
402 {"error": "An active subscription is required to send emails."} الاشتراك غير نشط أصلح الفوترة؛ نبّه فريقك
403 {"error": "This API key does not have send permission."} المفتاح يفتقد صلاحية Send فعّل Send أو استخدم مفتاحًا آخر
429 {"error": "Monthly email limit reached for your plan.", "limit": 25000, "sent": 25000} بلغت حدّ الباقة رقِّ باقتك، أو أجّل البريد حتى الشهر التالي؛ لا تُعِد المحاولة
429 {"detail": "Request was throttled. Expected available in 12 seconds."} طلبات كثيرة جدًا بهذا المفتاح خلال وقت قصير (تقييد المعدّل) انتظر المدة في ترويسة Retry-After، ثم أعد المحاولة
503 {"error": "Too many emails are waiting to be sent. Please retry in a few seconds."} انشغال مؤقت انتظر المدة في ترويسة Retry-After، ثم أعد المحاولة
5xx / انتهاء المهلة — مشكلة مؤقتة أعد المحاولة مع تراجع تدريجي

تصل رسائل الخطأ ضمن error في معظم الاستجابات، وضمن detail في أخطاء المصادقة، لذا اقرأ الاثنين:

const body = await res.json().catch(() => ({}));
const reason = body.error ?? body.detail ?? res.statusText;

أعد المحاولة فقط لما قد ينجح لاحقًا

إعادة محاولة 401 مئة مرة لن تجعل المفتاح صالحًا؛ بل ستملأ سجلاتك فحسب. قسّم الأخطاء إلى مجموعتين:

  • أعد المحاولة: أخطاء الشبكة، وانتهاء المهلة، واستجابات 5xx، و429 الخاصة بتقييد المعدّل (التي تحمل رسالة detail). انتظر المدة التي تحددها ترويسة Retry-After، وإلا فاستخدم التراجع الأُسّي مع عنصر عشوائي، وتوقّف بعد بضع محاولات.
  • لا تُعِد المحاولة: 400 و401 و402 و403 و429 الخاصة بالحدّ الشهري (التي تحمل limit وsent). هذه تحتاج إلى تدخّل بشري أو طلب مختلف. سجّلها بوضوح، وأطلق تنبيهًا عند 401 و402 و429 الخاصة بالحدّ الشهري، لأنها توقف بريدك كله.
// 5xx and the short-term rate limit can succeed later; the monthly limit (body has `limit`) can't.
const retryable = (status, body) => status >= 500 || (status === 429 && body.limit === undefined);

export async function sendWithRetry(payload, attempts = 4) {
  for (let i = 0; i < attempts; i++) {
    let res;
    try {
      res = await fetch('https://backend.inbixio.com/api/send-email/', {
        method: 'POST',
        headers: { 'X-API-Key': process.env.INBIXIO_API_KEY, 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
        signal: AbortSignal.timeout(15_000),
      });
    } catch (err) {
      if (i === attempts - 1) throw err; // network error or timeout: retry
    }
    if (res?.ok) return res.json();
    if (res) {
      const body = await res.json().catch(() => ({}));
      if (!retryable(res.status, body)) {
        throw new Error(`Inbixio ${res.status}: ${body.error ?? body.detail ?? res.statusText}`);
      }
    }
    const retryAfter = Number(res?.headers.get('Retry-After')) * 1000;
    const delay = retryAfter || Math.min(30_000, 1000 * 2 ** i) * (0.5 + Math.random()); // 0.5s–30s with jitter
    await new Promise((r) => setTimeout(r, delay));
  }
  throw new Error('Inbixio: gave up after retries');
}

بشأن التكرار: إذا انتهت مهلة الطلب، فربما يكون قد قُبل رغم ذلك، وقد تؤدي إعادة المحاولة حينها إلى إرسال الرسالة نفسها مرتين. في الإيصالات والإشعارات يكون هذا مقبولًا عادةً؛ أما في أي رسالة قد يربك تكرارها المستخدمين، فسجّل ما أرسلته في قاعدة بياناتك وتحقّق منه قبل إعادة المحاولة.

الحدود الشهرية

تتضمن كل باقة عددًا من الرسائل شهريًا: 25,000 في Starter و150,000 في Growth. تحسب Inbixio الرسائل المُرسلة بنجاح في الشهر الميلادي الحالي. وعند بلوغ الحدّ، تُعيد عمليات الإرسال 429 مع قيمة limit الخاصة بك وعدد sent الحالي، إلى أن يبدأ الشهر التالي أو ترقّي باقتك.

لا تنتظر ظهور 429:

  • تعرض صفحة API Keys (مفاتيح API) بطاقة Usage Limit (حدّ الاستخدام) بعدد الرسائل المُرسلة هذا الشهر مقارنةً بحدّ باقتك.
  • اضبط تذكيرًا لنفسك لمراجعتها عند نحو 80% من حدّك، وخطّط للترقية قبل أي إطلاق كبير أو عملية استيراد.
  • لتقدير حجم الإرسال خطوة بخطوة، راجع اختيار باقة واجهة برمجة البريد الإلكتروني.

فشل التسليم (المرحلة 2)

حين تقبل الواجهة الرسالة لكن يرفضها خادم SMTP الخاص بك، تُحسب عملية تسليم فاشلة. تعرض لوحة التحكم معدّل Failed Deliveries (عمليات التسليم الفاشلة) لآخر 7 أيام بدلًا من قائمة بالرسائل منفردة، لذا راقب المعدّل وراجع إعدادات خادمك حين يرتفع. الأسباب المعتادة:

  • فشل المصادقة: تغيّرت كلمة مرور صندوق البريد، أو أصبح المزوّد يشترط كلمة مرور تطبيق.
  • مشكلات الاتصال: المضيف أو المنفذ في إعدادات خادمك خاطئ.
  • حدود المزوّد: وضع مزوّد البريد حدًّا أقصى للإرسال اليومي من صندوق البريد.
  • مستلم مرفوض: رفض خادمك العنوان أثناء الإرسال. أما رسائل الارتداد التي تصل لاحقًا في صورة رسائل بريد، فتذهب إلى صندوق البريد المُرسِل لا إلى Inbixio، لذا تفقّد ذلك الصندوق أيضًا.

يكاد الحل يكون دائمًا في Email Servers (خوادم البريد) أو لدى مزوّد بريدك. ويتناول دليل إعدادات SMTP بالتفصيل الحالات الشائعة.

ما الذي تراقبه في بيئة الإنتاج

تمنحك لوحة تحكم Inbixio الأساسيات:

  • Email Sent (الرسائل المُرسلة) ومعدّل Failed Deliveries لآخر 7 أيام، مع التغيّر في كلٍّ منهما مقارنةً بالأيام السبعة السابقة.
  • Avg Latency (متوسط زمن الاستجابة): المدة التي يستغرقها خادم SMTP لقبول البريد. والقفزة المفاجئة فيه كثيرًا ما تسبق حالات الفشل.
  • مخططات حجم استدعاءات API والبريد على مدار العام، لرصد الاتجاهات وذروات المواسم.
  • Logs (السجلات) لكل استدعاء API: معرّف الحدث، ونقطة النهاية، والطريقة، ورمز الحالة، وزمن الاستجابة، والطابع الزمني.

ومن جهتك، تتبّع عدد الاستجابات غير 200 حسب رمز الحالة، وأطلق تنبيهًا عند ظهور 401 أو 402 أو 429 الخاصة بالحدّ الشهري. فهذه تعني أن البريد كله قد توقف، وسيلاحظ مستخدموك ذلك قبل أن تلاحظه سجلاتك.

قائمة التحقق

  • تعامَل مع 200 على أنها “في قائمة الإرسال”؛ وتحقّق من نتائج التسليم في لوحة التحكم
  • اقرأ error وdetail كليهما من استجابات الخطأ
  • أعد المحاولة فقط لأخطاء الشبكة وانتهاء المهلة و5xx و503 و429 الخاصة بتقييد المعدّل، مع احترام Retry-After
  • أطلق تنبيهًا عند 401 و402 و429 الخاصة بالحدّ الشهري
  • راقب بطاقة Usage Limit قبل الإطلاقات وعمليات الاستيراد
  • راقب معدّل Failed Deliveries وأصلح إعدادات SMTP بسرعة

أرسلها عبر Inbixio

اربط خادم SMTP الخاص بك، وأنشئ مفتاح API بصلاحيات محدّدة، وأرسل من أي لغة برمجة بطلب HTTPS واحد.

إنشاء حساب عرض الأسعار