لقد قمت مؤخرًا بمراجعة رسائل البريد الإلكتروني: المهمة والتعليمات البرمجية ذات الصلة بهدف اختبار جميع مسارات فشل التعليمات البرمجية وتعديل نص الخطأ.
اكتشفت أيضًا أن آثار تعيين DISCOURSE_SMTP_ENABLE_STARTTLS=false هي (في الغالب) صفرية. لم يؤدِ تعيين هذا إلى تعطيل STARTTLS فعليًا ، وفي الواقع ، يمكن أن يتعايش بشكل جيد مع TLS عند الاتصال (DISCOURSE_SMTP_FORCE_TLS=true).
قبل أن أقوم بدمج هذا ، أعتقد أن تحذيرًا إداريًا في لوحة التحكم عند تعيين DISCOURSE_SMTP_ENABLE_STARTTLS=false مناسب. أتخيل أن هناك على الأقل مستضيفًا ذاتيًا واحدًا قام بتعيين هذا ولكنه لا يحتاجه ويعتمد فعليًا على STARTTLS.
هذا يبدو عملاً جيدًا! شيء واحد لاحظته (أعتقد أنني لاحظته) هو أن مهمة rake لا تستخدم في الواقع نفس الكود الذي يستخدمه الإرسال الفعلي (مثل صفحة اختبار البريد الإلكتروني /admin/email). أنا متأكد من أنني واجهت حالة عمل فيها في تجربة المستخدم ولكن ليس في مهمة rake (أو ربما كان العكس؟)
بينما لا يزال الأمر حاضرًا في ذهنك، إذا كان بإمكانك التأكد من أنه عند الإرسال الفعلي، فإنه يستخدم نفس الكود الذي يستخدمه Discourse، فسيكون ذلك رائعًا.
@supermathie هل يستحق هذا إرسال رسالة خاصة لكل مسؤول على كل موقع لديه هذا المتغير معينًا؟ سيقوم نظام فحص المشكلات الحالي لدينا بذلك، ولست متأكدًا من أن هذا مبرر هنا، نظرًا لأنه في الغالب، يكون لهذا تأثير nil. من الناحية المثالية، أود فقط عرض هذا على لوحة المعلومات دون إرسال إشعارات للمستخدمين المسؤولين، ولست متأكدًا من أن بنية فحص المشكلات الحالية لدينا تدعم حالة الاستخدام هذه.
أعتقد ذلك - أجد أنه من المحتمل للغاية أنه نظرًا لمدى ارتباك العديد من المسؤولين حول إعداد البريد الإلكتروني، فإن شخصًا ما لديه هذا المتغير معينًا بينما يعتمدون فعليًا على starttls.
لا ينبغي لأحد أن يكون لديه هذا المتغير معينًا، على الأرجح.
أفضل أن يكون لدي تحذير خاطئ بدلاً من كسر إعداد البريد الإلكتروني لشخص ما بصمت.
البديل هو إزالة التحقق وتعطيل المتغير بحيث لا يفعل شيئًا على الإطلاق.
سيكون من الجيد ألا يظهر التحذير عندما يكون خادم SMTP الصادر هو localhost (أي يتطابق مع اسم نطاق Discourse) حيث أن بروتوكول TLS بين حاوية Docker والجهاز المضيف غير مطلوب لأنهما نفس الجهاز.
لقد واجهت في الإصدار الحالي الحالة التي أوقفت فيها السطور المعلقة (القيمة الافتراضية هي true) إرسال البريد الإلكتروني مع force_tls. لذلك، قمت بإلغاء التعليق عليها وضبطها على false. يعمل إرسال البريد الإلكتروني الآن - ولكن لدي هذه الرسالة في الواجهة الخلفية…
يعتمد الأمر قليلاً على المنفذ (port) الذي يعمل عليه مزود خدمة البريد الإلكتروني الخاص بك… لا يمكن أن يعمل كلاهما - وله تأثير بالتأكيد.
لقد لاحظت هذا أيضًا. بعد تحديث Discourse في 28 نوفمبر، بدأت أرى فشلًا في تسليم البريد مع رسالة الخطأ Job exception: :enable_starttls and :tls are mutually exclusive. Set :tls if you're on an SMTPS connection. Set :enable_starttls if you're on an SMTP connection and using STARTTLS for secure TLS upgrade.
تتبع المكدس
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/mail-2.9.0/lib/mail/network/delivery_methods/smtp.rb:159:in `build_smtp_session'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/mail-2.9.0/lib/mail/network/delivery_methods/smtp.rb:154:in `start_smtp_session'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/mail-2.9.0/lib/mail/network/delivery_methods/smtp.rb:108:in `deliver!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/mail-2.9.0/lib/mail/message.rb:269:in `deliver!'
/usr/local/lib/ruby/3.3.0/delegate.rb:87:in `method_missing'
/var/www/discourse/lib/email/sender.rb:296:in `send'
/var/www/discourse/app/jobs/regular/user_email.rb:80:in `send_user_email'
/var/www/discourse/app/jobs/regular/user_email.rb:40:in `execute'
/var/www/discourse/app/jobs/base.rb:318:in `block (2 levels) in perform'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-7.0.0/lib/rails_multisite/connection_management/null_instance.rb:49:in `with_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-7.0.0/lib/rails_multisite/connection_management.rb:17:in `with_connection'
/var/www/discourse/app/jobs/base.rb:305:in `block in perform'
/var/www/discourse/app/jobs/base.rb:301:in `each'
/var/www/discourse/app/jobs/base.rb:301:in `perform'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:220:in `execute_job'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:185:in `block (4 levels) in process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:180:in `traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:183:in `block in traverse'
/var/www/discourse/lib/sidekiq/suppress_user_email_errors.rb:6:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:182:in `traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:183:in `block in traverse'
/var/www/discourse/lib/sidekiq/discourse_event.rb:6:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:182:in `traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:183:in `block in traverse'
/var/www/discourse/lib/sidekiq/pausable.rb:131:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:182:in `traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:183:in `block in traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/job/interrupt_handler.rb:9:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:182:in `traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:183:in `block in traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/metrics/tracking.rb:26:in `track'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/metrics/tracking.rb:134:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:182:in `traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:173:in `invoke'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:184:in `block (3 levels) in process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:145:in `block (6 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/job_retry.rb:118:in `local'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:144:in `block (5 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/config.rb:39:in `block in <class:Config>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:139:in `block (4 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:281:in `stats'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:134:in `block (3 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/job_logger.rb:15:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:133:in `block (2 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/job_retry.rb:85:in `global'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:132:in `block in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/job_logger.rb:40:in `prepare'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:131:in `dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:183:in `block (2 levels) in process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:182:in `handle_interrupt'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:182:in `block in process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:181:in `handle_interrupt'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:181:in `process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:86:in `process_one'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:76:in `run'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/component.rb:10:in `watchdog'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/component.rb:19:in `block in safe_thread'
تمامًا مثل يوهان كريستوف، كنت سابقًا أُبقي DISCOURSE_SMTP_ENABLE_START_TLS معلقًا (مُعلَّقًا) و DISCOURSE_SMTP_FORCE_TLS مضبوطًا على true لـ TLS الضمني وكان يعمل بشكل ممتاز. ولكن الآن يجب عليّ ضبط DISCOURSE_SMTP_ENABLE_START_TLS صراحةً على false لكي يعمل تسليم البريد، وهو ما يؤدي بالطبع إلى ظهور الرسالة المذكورة أعلاه في لوحة تحكم المسؤول.
المنفذ 465 مع ENABLE_START_TLS=false و FORCE_TLS=true و OPEN_TIMEOUT=10. هذا الأخير بسبب أخطاء مهلة غريبة بدأت أراها بعد تحديث للنظام قبل حوالي ثلاث سنوات، ولكني سآكل قبعتي إذا كان ذلك مرتبطًا بالمشكلة الموصوفة أعلاه.
ألقيت نظرة على سجل الالتزامات (commit history) في هذه الأثناء ولاحظت تحديث مكتبة البريد (mail gem) إلى الإصدار 2.9.0 قبل ثلاثة أيام فقط من التحديث الذي أدخل المشكلة من جهتي (#36254). هناك إدخال في ملاحظات الإصدار يقول: “SMTP: إعادة هيكلة وقبول starttls :always و :auto بواسطة @eval في #1536”. أنا لا أعرف الكثير عن Ruby، ولكن هذا التغيير في الطلب المشار إليه (referenced PR) يبدو مشبوهًا بعض الشيء بالنسبة لي:
لتمكين تعيين DISCOURSE_SMTP_ENABLE_START_TLS على false، يجب إلغاء التعليق عليه - لأنه افتراضيًا مضبوط على true. هذا بالضبط ما تسبب لي في المشكلة. ومع ذلك، حدث ذلك فقط مع أحدث إصدار (2025.12.0-latest).