إصدار Discourse: 2026.5.0-latest.1
السياق
عندما يرسل مستخدم خارجي بريدًا إلكترونيًا إلى معالج البريد الوارد باستخدام متغير «نقطة» من Gmail (مثل user.name@gmail.com)، بينما حساب المنتدى المسجل لديهم هو النسخة الأساسية غير المنقطة (username@gmail.com)، ينهار معالج البريد الوارد باستثناء غير مُعالَج: ActiveRecord::RecordInvalid (Validation failed: Primary email has already been taken).
وعلاوة على ذلك، فإن محاولة حل هذه المشكلة بإضافة المتغير المنقوط كبريد إلكتروني ثانوي إلى ملف المستخدم — سواء عبر واجهة المستخدم أو طبقة نموذج Rails Console باستخدام UserEmail.create! — تفشل بنفس خطأ حلقة التحقق تمامًا. الحل الوحيد هو حقن استعلام SQL مباشر في قاعدة البيانات، متجاوزًا ActiveRecord.
خطوات إعادة الإنتاج
-
إنشاء حساب مستخدم على Discourse باستخدام البريد الإلكتروني الأساسي
username@gmail.com. -
أن يرسل ذلك المستخدم بريدًا إلكترونيًا واردًا إلى عنوان فئة/رد من
user.name@gmail.com. -
ملاحظة الرفض في سجلات البريد الوارد بسبب
ActiveRecord::RecordInvalid. -
محاولة إضافة
user.name@gmail.comكبريد إلكتروني ثانوي لحسابusername@gmail.comعبر وحدة تحكم Rails:UserEmail.create!(user_id: target_id, email: 'user.name@gmail.com', primary: false) -
ملاحظة انهيار تحقق النموذج.
السلوك المتوقع
يجب أن يتعامل Discourse مع تطبيع Gmail بسلاسة. ينبغي إما:
-
التعرف على متغير Gmail المنقوط الوارد على أنه ينتمي إلى الحساب الأساسي بسلاسة أثناء مرحلة معالجة البريد الوارد.
-
أو على الأقل السماح للمدير بإضافة المتغير المنقوط كبريد إلكتروني ثانوي للحساب الرئيسي دون تفعيل كتلة التطبيق «البريد الإلكتروني الأساسي محجوز»، نظرًا لأنه ينتمي إلى نفس المستخدم ومُعيّن صراحةً بـ
primary: false.
السلوك الفعلي
تعلق طبقة التطبيق في حلقة منطقية:
-
ترى
user.name@gmail.comكسلسلة «جديدة»، لذا تحاول التصرف بشأنها (إنشاء مستخدم مؤقت أو إرفاق بريد إلكتروني ثانوي). -
أثناء مرحلة التحقق، يُجري نموذج
UserEmailمنطق تطبيع Gmail الخاص به، يزيل النقاط، ويرى أنusername@gmail.comهو بالفعل مؤشر البريد الإلكتروني الأساسي لتلكuser_id، فيمنع تنفيذه نفسه بناءً على افتراض خاطئ بأن هناك صراعًا في سجل مكرر.
طريقة التجاوز المستخدمة لإزالة التعليق
الطريقة الوحيدة لحل هذه المشكلة كانت الدخول عبر SSH إلى الحاوية وتنفيذ استعلام SQL مباشر لتجاوز تحققات ActiveRecord تمامًا:
sql = "INSERT INTO user_emails (user_id, email, \"primary\", created_at, updated_at) VALUES (X, 'user.name@gmail.com', false, NOW(), NOW())"
ActiveRecord::Base.connection.execute(sql)
بمجرد إجبار العملية عبر SQL المباشر، يعمل تتبع البريد الوارد بشكل مثالي. يجب تحديث كود التحقق ليأخذ في الاعتبار هذه الحالة الخاصة.
شكرًا!