Python SMTP-relay: STARTTLS op 587 of TLS op 465?
STARTTLS op 587 en ymplisite TLS op 465 drage beide in Python-ferstjoering, mar mar ien past by jo relay. Ferlykje de handshake en de flatermodi.
Beide ferbiningsmodi drage itselde berjocht nei itselde relay-akkount, en it ferskil is wêr't TLS begjint, net wat ferstjoerd wurdt. De iene iepenet yn kleare tekst en wurdt yn 'e bân opwurde; de oare is fan 'e earste byte ôf fersifere. Dat iene ferskil bepaalt wat in strang relaybelied akseptearret, wat in tuskenapparaat observearje kin, en hokker flaterberjocht jo in middei lêze sille. Hjir is hoe't ik tusken harren kies as in applikaasje op in priveenetwurk in berjocht oan in ynterne ferstjoertsjinst oerlanget.
Wêr't de twa modi eins útinoar geane
De taak is yn beide gefallen itselde: autentisearje as in goedkard akkount, in tastien ferstjoerder beneame, ûntfangers listje, en wachtsje oant it relay de ferantwurdlikheid oernimt. Wat feroaret is de folchoarder fan bewurkingen. Port 587 begjint as in SMTP-sesje yn kleare tekst, kundiget STARTTLS oan yn syn EHLO-antwurd, en wurdt allinnich opwurde as de kliïnt dat freget. Port 465 ferwachtet in TLS-handshake foardat ien SMTP-opdracht útsprutsen wurdt.
Ferstjoering en relay binne ferskate taken, dêrom binne de poartnûmers gjin útwikselbere gewoanten. RFC 6409 beskriuwt berjochtferstjoering as in eigen tsjinst, en RFC 8314 beslacht de ymplisite-TLS-fariant dy't de measte moderne relays op 465 oanbiede. As jo relay ien fan 'e twa dokumintearret, giet dy dokumintaasje foar elke foarkar dy't jo by in eardere wurkjouwer opdien hawwe.
Wat STARTTLS op 587 jo jout
De opwurding bart binnen it SMTP-petear, dat it relay kin it oankundigje en de kliïnt kin wegerje om sûnder it troch te gean. Yn Python smyt starttls() in útsûndering as de tsjinner de útwreiding net biedt, wat in besykjen ta delgraadzje feroaret yn in sichtbere flater ynstee fan in stil oanmelden yn kleare tekst. Dat gedrach is it haadargumint foar de modus, en it is de muoite wurdich om der bewust op te fertrouwen ynstee by tafal.
It bleatstellingsfinster is lyts mar echt: de earste EHLO-útwikseling is lêsber, en neat foar de opwurding draacht bewiisstikken. Op in privee paad tusken in applikaasje-subnet en in yntern relay is dat finster meastentiids akseptabel. Op in paad dat jo net kontrolearje, is dat de reden dat guon teams op 'e oare modus oanstienge.
In apparatuer foar ûnderskepping dy't de STARTTLS-mooglikheid fuorthellet, produsearret in mislearre ferstjoering, net in weromfal. Dat is de útkomst dy't jo wolle, en it is ek de fluchste manier om te ûntdekken dat eat SMTP op it paad oerskriuwt.
Wat ymplisite TLS op 465 feroaret
Der is hielendal gjin kleare-tekstfaze. De kliïnt docht in TLS-handshake sa gau as de socket iepene is, falidearret it sertifikaat tsjin syn fertrouwensopslach, en wikselet earst dêrnei EHLO, AUTH en it berjocht út. Neat kin de sesje delgraadzje, want der is gjin kleare-teksttastân om oer te ûnderhanneljen, en dat hellet in hiele klasse fan ûnderskepingsflaters fuort.
De ruil is diagnostisearberens. In relay dat op 465 mei kleare-tekst-SMTP antwurdet, of in loadbalancer dy't TLS mei de ferkearde sertifikaatnamme beëiniget, mislearret by de handshake en jout jo in SSL-flater ynstee fan in mailflater. As dat bart, leit it probleem ûnder de applikaasje, en gjin hoemannichte berjochtbou sil it reparearje.
Ien ferstjoerfunksje, twa transporten
De koade ferskilt amper tusken de modi, dêrom moat de kar út relaybelied makke wurde ynstee út biblioteekgemak. Eksportearje earst de ynstellingen, en rin dan in inkeld skript dat it transport út 'e konfigurearre poarte kiest.
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() ferifiearret de keatling en de hostnamme, dat in privee CA moat yn 'e fertrouwensopslach ynstallearre wurde ynstee fan omgien te wurden mei in net-ferifiearre kontekst. send_message() jout in wurdboek werom fan ûntfangers dy't it relay ôfwiisde; in leech wurdboek betsjut dat it se allegear akseptearre. De timeout fan fyftjin sekonden is in begjinpunt, net in ôfstelde wearde foar jo netwurk.
Hâld it wachtwurd bûten it byld en bûten de logs. In geheim dat by runtime monteard en yn 'e omjouwing lêzen wurdt, is goed; de omjouwing yn in logrigel werjaan is dat net, en in debugspoar fan 'e AUTH-útwikseling ek net.
Kies nei relaybelied en paad, net nei gewoante
Trije betingsten beslisse it. Earst, wat it relay eins oankundiget: in tsjinst dy't allinnich op 587 mei STARTTLS harket, is net op 465 te berikken, hoe graach jo ymplisite TLS ek wolle. Twad, oft it paad tusken de applikaasje en it relay fertrouber genôch is om in lêsbere EHLO-útwikseling te akseptearjen. Tred, oft eat yn 'e midden SMTP oerskriuwt of proksyt, want dat bepaalt oft it delgraadzjerisiko teoretysk of libbend is.
As it relay beide biedt, nim ik 465 foar in tsjinst dy't sûnder tafersjoch rint en 587 foar ien wêr't in persoan nei de earste útrôl sjocht, inkeld om't de flaterberjochten nei ferskate lagen wize. Dy foarkar is mines en it is gjin belied.
Wat jo ek kieze, registrearje de poarte, it fertrouwensmateriaal en it domein fan 'e ferstjoerder njonken de útrôl. Stjoer dan ien autorisearre testberjocht en befêstigje dat it relay it akseptearre hat, en hâld it ferstjoerresultaat en elk letter ferzendrapport as aparte records. In suksesfolle oerlangering oan it relay is it ein fan 'e ferantwurdlikheid fan 'e applikaasje, net it bewiis dat it berjocht in postfak berikt hat.