MailLandDocs
خطافات الويب

منطق إعادة المحاولة

فهم كيفية إعادة Mail.Land لمحاولة تسليم webhook الفاشلة

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

جدول إعادة المحاولة

يغطي هذا القسم كل حدث يسلّمه durable dispatcher: message.* وsuppression.* وaccount.* وinbound.received. ما يخص أحداث البريد الوارد موجود في تسليمات البريد الوارد أدناه.

تُعيد MailLand محاولة التسليم الفاشل حتى 6 مرات إجمالاً، مع تأخير متزايد قبل كل محاولة إعادة:

المحاولةالتأخير قبل هذه المحاولةإجمالي الوقت المنقضي
1: (المحاولة الأولى)0
2فوري~0
3دقيقة واحدة~دقيقة واحدة
45 دقائق~6 دقائق
515 دقيقة~21 دقيقة
6ساعة واحدة~ساعة و21 دقيقة

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

قابل للإعادة مقابل غير قابل للإعادة

الردود القابلة لإعادة المحاولة

تؤدي رموز الحالة هذه إلى إعادة المحاولة تلقائياً:

  • 408 Request Timeout
  • 429 Too Many Requests
  • 500 Internal Server Error
  • 502 Bad Gateway
  • 503 Service Unavailable
  • 504 Gateway Timeout
  • أخطاء الشبكة (انتهاء المهلة، أخطاء المقبس، إخفاقات DNS)

الردود غير القابلة لإعادة المحاولة

تُعامَل رموز الحالة هذه كإخفاقات دائمة، لا تتم إعادة المحاولة:

  • 400 Bad Request
  • 401 Unauthorized
  • 403 Forbidden
  • 404 Not Found
  • جميع أخطاء 4xx الأخرى (باستثناء 408 و429)
  • استجابة إعادة توجيه فشلت في التحقق (راجع عمليات إعادة التوجيه) أو تجاوزت حد عدد القفزات

إذا أعادت نقطة النهاية لديك رأس Retry-After على استجابة قابلة لإعادة المحاولة، تستخدم MailLand تلك القيمة كتأخير قبل المحاولة التالية بدلاً من الجدول أعلاه: لأي حالة قابلة لإعادة المحاولة، وليس فقط 429. لا يوجد حد أقصى ولا تذبذب عشوائي (jitter) يُطبَّق عليها: احترم هذا في جانبك أيضاً إذا أرسلته، لأن قيمة كبيرة جداً تُحترم كما هي تماماً.

عمليات إعادة التوجيه

لا تتعامل MailLand مع نقطة النهاية لديك كما يفعل المتصفح. تُتَّبع عمليات إعادة التوجيه يدوياً، بحد أقصى 3 قفزات، ويُعاد التحقق من كل قفزة قبل إرسال أي شيء إليها:

  • يجب أن يكون الهدف https://: إعادة التوجيه إلى http:// تُرفض ولا تُخفَّض؛
  • يجب أن يُحلَّل الهدف إلى عنوان عام: إعادة التوجيه إلى عنوان خاص أو loopback أو link-local تُرفض، ولا يُرسَل الطلب أبداً؛
  • تجاوز 3 قفزات يفشل التسليم.

يُبلَّغ عن إعادة التوجيه المرفوضة كفشل تسليم بدون رمز حالة. إذا انتقلت نقطة النهاية لديك، وجّه webhook إلى العنوان الجديد بدلاً من الاعتماد على إعادة توجيه.

إعداد التسليم

الإعدادالافتراضيالوصف
مهلة HTTP15 ثانيةالحد الأقصى لوقت الانتظار لكل محاولة تسليم
الحد الأقصى لإعادة المحاولة6 محاولاتإجمالي محاولات التسليم بما في ذلك الأولى
عتبة الإيقاف التلقائي10 إخفاقات متتاليةيُوقف webhook بعد هذا العدد من الإخفاقات المتتالية: يُستخدم pauseThreshold الخاص بالـwebhook عند ضبطه على قيمة أكبر من 0، وإلا فهذه القيمة الافتراضية
إلغاء التكرارطالما بقي سجل التسليم موجوداًتُستبعد تكرارات الحدث نفسه بقيد (WebhookId, EventId) طالما بقي السطر موجوداً: 30 يوماً على الأقل للتسليمات الناجحة

تسليمات البريد الوارد

يُسلَّم inbound.received عبر durable dispatcher نفسه مثل كل حدث آخر، بجدول إعادة المحاولة نفسه ومعالجة Retry-After نفسها وسجل التسليم نفسه والإيقاف المؤقت التلقائي نفسه الموصوفة أعلاه.

  • ألغِ التكرار على event_id (يساوي X-MLND-Event-Id) كما في أي حدث آخر. وهو ثابت لكل رسالة واردة ولكل ويب هوك، لذا تحمل كل محاولة للبريد نفسه المعرّف نفسه.
  • إعادة التشغيل اليدوية حدث جديد: event_id جديد، والمعرّف الأصلي في data.replay_of. ويبقى data.idempotency_key كما هو.
  • يُوقَّع download_url لكل مرفق في كل محاولة ويبقى صالحًا 15 دقيقة من حينها؛ وid المرفق هو نفسه في كل محاولة. راجع ويب هوك البريد الوارد.

عرض سجل التسليم

اطّلع على عمليات التسليم السابقة لـ webhook:

GET https://api.mail.land/v1/webhooks/{id}/deliveries
List delivery history
curl -X GET "https://api.mail.land/v1/webhooks/wh_abc123/deliveries?limit=20" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

معاملات الاستعلام

المعاملالنوعالافتراضيالوصف
cursorstring-مؤشر معتم من nextCursor للصفحة السابقة. احذفه للصفحة الأولى.
limitint20العناصر لكل صفحة
statusstring-تصفية: success أو failed
eventTypestring-التصفية حسب نوع الحدث (مثلاً message.delivered)
fromdatetime-تاريخ البداية
todatetime-تاريخ النهاية
Delivery history response
{
  "items": [
    {
      "publicId": "p8r2kx7m9wq4rtz",
      "eventType": "message.delivered",
      "messageId": "t_a1b2c3d4e5f6",
      "statusCode": 200,
      "responseTimeMs": 145,
      "success": true,
      "errorMessage": null,
      "createdAt": "2026-02-17T12:34:58.000Z",
      "attemptNumber": 1
    },
    {
      "publicId": "p8r2kx7m3nq1abc",
      "eventType": "message.bounced",
      "messageId": "t_d4e5f6a1b2c3",
      "statusCode": 503,
      "responseTimeMs": 15000,
      "success": false,
      "errorMessage": "Service Unavailable",
      "createdAt": "2026-02-17T12:30:00.000Z",
      "attemptNumber": 3
    }
  ],
  "nextCursor": "eyJ2IjoxLCJzIjoiY3JlYXRlZGF0OmRlc2MiLCJrIjoi...",
  "hasMore": true
}

إعادة محاولة تسليم فاشل

أعِد محاولة تسليم فاشل محدد يدوياً:

POST https://api.mail.land/v1/webhooks/{id}/deliveries/{publicId}/retry
Retry a delivery
curl -X POST https://api.mail.land/v1/webhooks/wh_abc123/deliveries/p8r2kx7m3nq1abc/retry \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

يُعيد 202 Accepted عند النجاح. تُضاف إعادة المحاولة إلى قائمة الانتظار وتستخدم بيانات الحدث الأصلية.

الحالةالرمزالوصف
202-أُضيفت إعادة المحاولة إلى قائمة الانتظار بنجاح
202-التسليم موجود بالفعل في قائمة الانتظار لإعادة المحاولة، لا شيء يحدث، وليس خطأ
400ALREADY_SUCCEEDEDلا يمكن إعادة محاولة تسليم نجح بالفعل
400INVALID_REQUESTالتسليم أقدم من تتبّع إعادة المحاولة الدائم، أو قيد التنفيذ حالياً
404WEBHOOK_NOT_FOUNDwebhook غير موجود
404DELIVERY_NOT_FOUNDمعرّف التسليم غير موجود

الإيقاف التلقائي عند الإخفاقات

عندما يجمع webhook عددًا كافيًا من الإخفاقات المتتالية، تُوقفه MailLand تلقائياً. العتبة هي pauseThreshold الخاص بالـwebhook عند ضبطه على قيمة أكبر من 0، وإلا فهي القيمة الافتراضية وهي 10 إخفاقات متتالية:

  1. يُضبط isActive الخاص بـ webhook على false، ويُعبَّآن pausedAt وpausedReason: يخبرك pausedReason بعدد الإخفاقات وماهية آخر إخفاق
  2. يُنشأ إشعار داخل التطبيق
  3. لا تُسلَّم المزيد من الأحداث حتى يُستأنف webhook

العداد هو عداد محاولات، وليس أحداثاً: حدث واحد يستنفد سلّم إعادة المحاولة بأكمله يساهم بعدة إخفاقات.

لا يوجد إشعار تحذيري مبكر قبل بلوغ العتبة: تحقق من consecutiveFailures بشكل استباقي (راجع أفضل الممارسات أدناه) بدلاً من انتظار إخطارك.

استئناف webhook موقوف

POST https://api.mail.land/v1/webhooks/{id}/resume
Resume a paused webhook
curl -X POST https://api.mail.land/v1/webhooks/wh_abc123/resume \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

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

أي تسليم ناجح يُعيد تعيين عداد الإخفاقات المتتالية إلى الصفر تلقائياً. نجاح واحد بعد 9 إخفاقات يمنع إيقاف webhook.

أفضل الممارسات

  • أعِد 200 بسرعة: عالج حمولات webhook بشكل غير متزامن. ضَع الحدث في قائمة الانتظار وأعِد 200 فوراً. المعالجات طويلة المدى تخاطر بانتهاء المهلة.
  • استخدم معرّف الحدث للمعالجة المتكرِّرة الآمنة (idempotent): رأس X-MLND-Event-Id (والحقل المطابق event_id في الحمولة) ثابت عبر إعادة المحاولات وإعادة الإرسال: يصل نفس الحدث الأصلي دائماً بنفس المعرّف، بغض النظر عن عدد مرات إعادة تسليمه. خزّن المعرّفات المعالَجة وتجاوز ما عالجته من قبل، بحيث يكون التسليم المكرر بلا أثر إضافي في جانبك.
  • راقب الإخفاقات المتتالية: تحقق من حقل consecutiveFailures عند إدراج webhooks. حقق الأمر قبل الوصول إلى عتبة الإيقاف التلقائي.
  • تعامل مع 429 بشكل صحيح: إذا كانت نقطة النهاية مثقلة، أعِد 429 مع رأس Retry-After. ستحترم MailLand ذلك.

الخطوات التالية

في هذه الصفحة