Python SMTP испраќање: STARTTLS на 587 или TLS на 465?
STARTTLS на 587 и имплицитниот TLS на 465 и двата пренесуваат Python испраќање, но само едниот одговара на вашиот реле. Споредете го ракувањето и режимите на грешка.
Двата режима на поврзување ја пренесуваат истата порака до истата сметка на реле, а разликата е каде започнува 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 за онаа каде што човек ја набљудува првата поставеност, само затоа што пораките за грешка укажуваат на различни слоеви. Таа претпочитаност е моја и не е политика.
Што и да изберете, запишете ја портата, материјалот за доверба и доменот на испраќачот заедно со поставеноста. Потоа испратете една овластена пробна порака и потврдете дека релето ја прифатило, чувајќи го резултатот од испраќањето и секој подоцнежен извештај за достава како одделни записи. Успешното предавање на релето е крајот на одговорноста на апликацијата, а не доказ дека пораката стигнала до сандаче.