ينقل نمطا الاتصال الرسالة نفسها إلى حساب المرحّل نفسه، والفرق في أين يبدأ TLS لا في ما يُرسل. أحدهما يفتح بنص صريح ثم يترقّى داخل الجلسة؛ والآخر مشفّر من البايت الأول. هذا الفرق الوحيد يحدّد ما ستقبله سياسة مرحّل صارمة، وما يمكن لجهاز وسيط أن يلاحظه، وأي رسالة خطأ ستقضي عصرًا في قراءتها. وإليك كيف أختار بينهما عندما يسلّم تطبيق على شبكة خاصة رسالة إلى خدمة تسليم داخلية.

أين يختلف النمطان فعليًا

المهمة واحدة في الحالتين: المصادقة كحساب معتمد، وتسمية مرسل مسموح، وسرد المستلمين، وانتظار أن يتحمّل المرحّل المسؤولية. وما يتغيّر هو ترتيب العمليات. يبدأ المنفذ 587 كجلسة SMTP بنص صريح، ويعلن STARTTLS في رد EHLO، ولا يترقّى إلا إذا طلب العميل ذلك. أما المنفذ 465 فيتوقع مصافحة TLS قبل نطق أي أمر SMTP.

التسليم والترحيل وظيفتان مختلفتان، ولهذا فإن أرقام المنافذ ليست عادات قابلة للتبادل. يصف RFC 6409 تسليم الرسائل كخدمة قائمة بذاتها، ويغطي RFC 8314 صيغة TLS الضمني التي يعرضها معظم المرحّلات الحديثة على 465. وإذا وثّق مرحّلك إحدى الطريقتين، فإن تلك الوثائق تتفوق على أي تفضيل اكتسبته من جهة عمل سابقة.

ما يمنحك إياه STARTTLS على 587

تحدث الترقية داخل محادثة SMTP، فيستطيع المرحّل الإعلان عنها ويستطيع العميل رفض المتابعة من دونها. في Python، يرفع starttls() استثناءً عندما لا يقدّم الخادم الامتداد، ما يحوّل محاولة خفض المستوى إلى فشل مرئي بدلًا من تسجيل دخول صامت بنص صريح. هذا السلوك هو الحجة الأساسية لهذا النمط، ويستحق الاعتماد عليه عن قصد لا عن طريق الصدفة.

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

جهاز اعتراض يزيل قدرة STARTTLS يُنتج تسليمًا فاشلًا، لا تراجعًا. تلك هي النتيجة التي تريدها، وهي أيضًا أسرع طريقة لاكتشاف أن شيئًا ما يعيد كتابة SMTP على المسار.

ما يغيّره TLS الضمني على 465

لا توجد مرحلة نص صريح على الإطلاق. يجري العميل مصافحة TLS بمجرد فتح المقبس، ويتحقق من الشهادة مقابل مخزن الثقة لديه، ثم يتبادل EHLO وAUTH والرسالة بعد ذلك فقط. ولا شيء يمكنه خفض مستوى الجلسة لأنه لا توجد حالة نص صريح للتفاوض منها، وهذا يزيل فئة كاملة من أعطال الاعتراض.

المقايضة هي قابلية التشخيص. فالمرحّل الذي يجيب على 465 بـ SMTP بنص صريح، أو موازن الحِمل الذي ينهي TLS باسم شهادة خاطئ، يفشل عند المصافحة ويعطيك خطأ SSL بدلًا من خطأ بريد. وعندما يحدث ذلك، تكون المشكلة تحت التطبيق، ولن يصلحها أي قدر من بناء الرسالة.

دالة تسليم واحدة، وناقلان

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

export SMTP_HOST=smtp.relay.internal
export SMTP_PORT=587
export SMTP_USER=svc-notify
export [email protected]
export [email protected]
export SMTP_PASSWORD="$(cat /run/secrets/smtp_password)"
import os, smtplib, ssl
from email.message import EmailMessage

ctx = ssl.create_default_context()
msg = EmailMessage()
msg["From"] = os.environ["MAIL_FROM"]
msg["To"] = os.environ["MAIL_TEST_TO"]
msg["Subject"] = "relay submission test"
msg.set_content("One authorized test message from the app.")

host = os.environ["SMTP_HOST"]
port = int(os.environ.get("SMTP_PORT", "587"))

if port == 465:
    client = smtplib.SMTP_SSL(host, port, context=ctx, timeout=15)
else:
    client = smtplib.SMTP(host, port, timeout=15)
    client.ehlo()
    client.starttls(context=ctx)
    client.ehlo()

with client:
    client.login(os.environ["SMTP_USER"], os.environ["SMTP_PASSWORD"])
    refused = client.send_message(msg)

print("refused:", refused)

create_default_context() يتحقق من السلسلة واسم المضيف، لذا يجب تثبيت CA خاصة في مخزن الثقة بدلًا من تجاوزها بسياق غير موثّق. ويعيد send_message() قاموسًا بالمستلمين الذين رفضهم المرحّل؛ القاموس الفارغ يعني أنه قبلهم جميعًا. مهلة الخمس عشرة ثانية نقطة بداية، وليست قيمة مضبوطة لشبكتك.

أبقِ كلمة المرور خارج الصورة وخارج السجلات. السر الذي يُركّب وقت التشغيل ويُقرأ في البيئة مقبول؛ أما طبع البيئة في سطر سجل فليس مقبولًا، وكذلك أثر تصحيح لتبادل AUTH.

اختر حسب سياسة المرحّل والمسار، لا حسب العادة

ثلاثة شروط تحسم الأمر. أولًا، ما يعلنه المرحّل فعليًا: خدمة تستمع فقط على 587 مع STARTTLS لا يمكن الوصول إليها على 465 مهما كنت تفضّل TLS الضمني. ثانيًا، هل المسار بين التطبيق والمرحّل موثوق بما يكفي لقبول تبادل EHLO قابل للقراءة. ثالثًا، هل يعيد شيء في المنتصف كتابة SMTP أو يوكّله، لأن ذلك يحدد ما إذا كان خطر خفض المستوى نظريًا أم واقعًا.

حين يعرض المرحّل الاثنين، آخذ 465 لخدمة تعمل بلا إشراف و587 لخدمة يراقب فيها شخص أول نشر، لمجرد أن رسائل الفشل تشير إلى طبقات مختلفة. هذا التفضيل تفضيلي وليس سياسة.

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

مقالات ذات صلة