عندما يخبرك ووردبريس أن الرسالة أُرسلت. لكنها لم تصل.
جعفر أبازيد
يشتكي أحد المستخدمين من أنه لم يتلقَّ رسالة إعادة تعيين كلمة المرور. تتحقق من الأمر، فتجد أن ووردبريس يؤكد أنه أرسلها: أعادت الدالة wp_mail() القيمة true، ولا تجد شيئاً في السجلات (Logs)، لأنه لا يوجد ما يُسجل أصلاً. لقد غادرت الرسالة التطبيق… ثم اختفت.
في ووردبريس، لا يُعد هذا خللاً، بل هو السلوك الذي صُمم النظام ليعمل به. تمر رسالة البريد عبر دالة PHP mail() ثم عبر sendmail على الخادم، دون سمعة إرسال (Sending Reputation)، ولا توقيع DKIM، ولا توافق مع SPF، فتقوم خدمات مثل Gmail وOutlook بتصنيفها كرسالة مزعجة (Spam) بهدوء.
والأسوأ من ذلك أن الفشل يحدث بصمت. فخدمة sendmail تقبل الرسالة، لذلك تعيد الدالة wp_mail() القيمة true، بينما تموت الرسالة في مكانٍ لن يسمع عنه ووردبريس أبداً.
الحل الشائع… نصف حل
الحل الذي يقترحه الجميع هو استخدام إضافة SMTP. وهذا يعالج نصف المشكلة فقط (المصادقة)، لكنه في المقابل يخزن اسم المستخدم وكلمة المرور داخل قاعدة البيانات، وتحديداً في جدول wp_options.
وعندها، تصبح بيانات الاعتماد جزءاً من كل نسخة تنتقل معها قاعدة البيانات: النسخة الاحتياطية الليلية، ونسخة Staging التي سحبها أحد المطورين قبل أشهر، وكل ملف Dump محفوظ في مكان ما. وكل من يصل إلى أي نسخة من قاعدة البيانات يصبح قادراً على إرسال رسائل من نطاقك، موقعة بمفتاح DKIM الخاص بك، ودون أي أثر يثبت أن الرسائل لم تصدر عنك.
وبالنسبة لمؤسسة إعلامية تُعد سمعة نطاقها أحد أهم أصولها، فهذا هو الخطر الحقيقي الذي يستحق أن يقلقك.
الرسم التوضيحي: يبدأ المساران بالطريقة نفسها، حيث تستدعي wp_mail() المكتبة PHPMailer.
الحل: ثلاث خطوات
أرسل الرسائل عبر Amazon SES API، وليس عبر SMTP. فواجهة API تعتمد على طلب HTTPS موقع، دون أي كلمة مرور طويلة الأمد تمر ضمن عملية الإرسال.
واستخدم IAM Role بدلاً من مفاتيح الوصول المخزنة. فإذا كان ووردبريس يعمل على إحدى خدمات الحوسبة في AWS (مثل EC2 أو ECS)، فستزوده AWS تلقائياً ببيانات اعتماد مؤقتة (Short-lived Credentials)، تُقرأ لحظة الإرسال ولا تُخزن في أي مكان: لا في قاعدة البيانات، ولا في wp-config.php، ولا حتى على القرص. وبذلك، لا يعود هناك سر يمكن تسريبه، لأنه لا يوجد سر مخزن من الأساس.
أما الخطوة الثالثة، فهي استبدال وسيلة الإرسال فقط، دون إعادة كتابة أي جزء من المنظومة.
أضاف ووردبريس 5.7 نقطة التوسعة (Hook) المسماة pre_wp_mail، وقد يبدو استخدامها للاستحواذ الكامل على wp_mail() خياراً مغرياً. لكنه في الحقيقة فخ. فحينها ستصبح مسؤولاً عن كامل العقد (Contract) الذي توفره الدالة: تحليل الترويسات (Headers)، ودعم Cc وBcc، ونوع المحتوى (Content-Type)، والمرفقات (Attachments)، وجميع مرشحات wp_mail_*. ومع أول تغيير يطرأ على النواة Core، سيبدأ تنفيذك بالانحراف عنه بصمت، وهو الدرس المكلف الذي علمتنا إياه الإضافة السابقة.
لذلك، لا تعيد هذه الإضافة كتابة أي شيء. فهي تترك النواة تبني الرسالة كالمعتاد، وتطبق جميع المرشحات، ثم تزوده بفئة مشتقة من PHPMailer (PHPMailer subclass) لا تعيد تعريف سوى دالة واحدة، هي postSend(). والدرس الذي تجسده بنية الإضافة بسيط: إذا منحتك النواة نقطة توسعة حقيقية، فاستفد منها، ولا تنشئ فرعاً Fork خاصاً بك.
الفشل لم يعد صامتاً
القاعدة الأساسية في هذه الإضافة أنها لا تسمح بحدوث الفشل بصمت. فعندما يرفض Amazon SES رسالةً ما، فإنه يوضح السبب بدقة، سواء كان المرسل غير موثق (Unverified Sender)، أو بسبب قيود الـ Sandbox، أو نتيجة تجاوز حدود الإرسال (Throttling). ولا تخفي الإضافة هذه التفاصيل بإرجاع القيمة false فقط، بل تسجل رسالة الخطأ الحقيقية الصادرة من SES، ثم تمررها عبر الحدث wp_mail_failed.
كما أنها ترفض تماماً العودة إلى mail() كخيار احتياطي. فهذا الحل الذي يبدو “آمناً” ليس سوى عودة إلى الفشل الصامت نفسه؛ إذ يبدو أن الرسالة أُرسلت، بينما ينتهي بها المطاف في مجلد البريد المزعج Spam. فالفشل الواضح يُكتشف ويُصلح، أما النجاح الوهمي الذي ينتهي في البريد المزعج، فلا يلاحظه أحد.
التفصيل الذي تتجاهله الشروحات: الارتدادات والشكاوى
يراقب Amazon SES معدلات الارتداد Bounces والشكاوى Complaints باستمرار، ويبدأ بتقييد معدل الإرسال (Throttling) إذا ارتفعت، ثم قد يعلق الحساب بالكامل إذا تجاوزت الحدود المسموح بها. أما ووردبريس، عند تركه يعمل وحده، فلا يحتفظ بأي سجل للرسائل المرتدة، ولذلك قد يستمر في إرسال البريد إلى عنوان لم يعد صالحاً، مرةً بعد أخرى.
ولهذا يسجل Amazon SES كل ارتداد وشكوى في موضوع (SNS Topic)، بينما تسجل الإضافة عنوان البريد الإلكتروني في جدول الحظر Suppression، وتتحقق منه قبل كل عملية إرسال، بحيث لا يُرسل أي بريد مرة أخرى إلى عنوان سبق أن ارتد أو قدم شكوى.
ولأن نقطة استقبال SNS عبارة عن عنوان URL عام، فإن الإضافة تثبت قيمة WP_SES_SNS_TOPIC_ARN، وتتحقق من التوقيع الرقمي لكل إشعار صادر من Amazon قبل أن تكتب أي سجل في قاعدة البيانات، حتى لا يتمكن أي طرف من تزوير إشعار يؤدي إلى حظر استقبال البريد لمستخدميك.
هذه نسخة عربية مختصرة. أما الشرح الكامل، متضمناً البنية المعمارية، والمبررات الهندسية، والرسوم التوضيحية، فيمكن الاطلاع عليه في المقال باللغة الإنجليزية:
→ Your WordPress says the email sent. It didn’t.
كما أن الإضافة مفتوحة المصدر، ومرخصة بموجب GPL، ومتاحة على كل من GitHub وPackagist:
→ github.com/mantekio/wp-ses-mail · composer require mantekio/wp-ses-mail
وهذه هي الطريقة التي نتعامل بها مع ووردبريس على AWS: استفد من نقاط التوسعة التي توفرها النواة، ولا تخزن ما لا ترغب في رؤيته مُسرَّباً، واجعل الفشل يحدث حيث يمكن رؤيته ومعالجته. وإذا كان نظام إرسال البريد في ووردبريس لديك لا يزال لغزاً تفضل ألا يبقى كذلك، فلنتحدث.