Nette Mail 4.1.3: aby tvé e-maily vůbec dorazily
Odeslat e-mail je jeden řádek kódu. Doručit ho je disciplína, ve které Gmail a Microsoft každým rokem přitvrzují pravidla. Nette Mail 4.1.3 přináší, co dnes provideři vyžadují: přihlášení přes OAuth, odhlášení jedním kliknutím i modernější DKIM. A jednu bezpečnostní záplatu, kvůli které se vyplatí aktualizovat hned.
Přitom jde o zpětně kompatibilní verzi: nic nepřepisuješ, jen aktualizuješ a nové možnosti si bereš podle potřeby. Projdeme je v pořadí, v jakém na tebe budou tlačit samy: od požadavků velkých providerů přes bezpečnost až po pohodlí při vývoji.
Heslo už nestačí: OAuth 2.0
Gmail i Microsoft 365 postupně vypínají přihlašování jménem a
heslem pro SMTP; aplikační hesla jsou na odchodu a budoucnost patří OAuth
tokenům. SmtpMailer proto umí autentizaci XOAUTH2:
$mailer = new Nette\Mail\SmtpMailer(
host: 'smtp.gmail.com',
username: 'franta@gmail.com',
password: '',
encryption: 'tls',
);
$mailer->setAccessToken($accessToken);
Access tokeny expirují, obvykle po hodině. Místo řetězce proto můžeš předat callback, který se zavolá při každém připojení a vždy dodá čerstvý token:
$mailer->setAccessToken(fn() => $oauth->getFreshToken());
Získání a obnovování tokenu zůstává na tvé OAuth knihovně, to je její řemeslo. Nette Mail řeší jen SMTP část, a tu kompletně: včetně správného ukončení výměny, když server token odmítne, takže v chybě uvidíš skutečný důvod, a ne záhadný timeout.
Odhlášení jedním kliknutím
Gmail a Yahoo vyžadují od hromadných odesílatelů, aby šel newsletter
odhlásit jedním kliknutím přímo v klientovi. Technicky to znamená dvojici
hlaviček podle RFC 8058, které musí přesně souhlasit; samotná hlavička
List-Unsubscribe požadavek nesplňuje. Přesně tenhle typ
znalosti má držet knihovna, ne tvůj kód:
$mail->setUnsubscribe('https://example.com/unsubscribe?token=xyz', 'unsubscribe@example.com');
První parametr je URL, které příjemce odhlásí v reakci na holý HTTP POST, druhý je e-mailová adresa jako záloha pro klienty, kteří POST odeslat neumějí. Obě hlavičky se nově také podepisují DKIM, takže adresu, na kterou kliknutí míří, nemůže nikdo cestou vyměnit.
DKIM: Ed25519 a jedna záplata
Podepisování e-mailů pomocí DKIM umí
Nette Mail dávno. Nově zvládne kromě RSA i podpisy Ed25519 podle RFC 8463:
klíč prostě předáš a knihovna sama pozná, o který typ jde: RSA je
v PEM formátu, Ed25519 jsou surové bajty v base64. Žádný nový parametr,
žádná konfigurace, jen potřebuješ rozšíření sodium.
Přibyl i takzvaný oversigning: v parametru oversignHeaders
vyjmenuješ hlavičky, které se mají chránit proti připojení druhé kopie
k už podepsané zprávě. To je oblíbený trik podvržených e-mailů,
protože mnoho klientů zobrazí právě tu přidanou hlavičku
From. S oversigningem takový pokus podpis rozbije.
A ta slíbená záplata: podpis už neobsahuje tag l=
s délkou těla. Zněl neškodně, jenže umožňoval komukoli přilepit za
podepsanou zprávu libovolný obsah, aniž by podpis přestal platit. To je samo
o sobě důvod aktualizovat, i kdyby tě žádná z novinek nezajímala.
CssInliner se naučil kaskádu
Inlinování CSS do atributů style je u e-mailů nutnost,
protože klienti značku <style> často ignorují. Dosud ale
platilo jednoduché pravidlo: poslední deklarace vyhrává. Vezmi si tenhle
stylesheet:
p.intro { color: red; }
p { color: blue; }
Prohlížeč vykreslí odstavec s třídou intro červeně,
protože specifičtější selektor vítězí. Inliner ho ale obarvil modře a
e-mail se tak lišil od webu, pro který byl stylesheet napsaný. Čím
pečlivěji byly styly napsané, tím víc se výsledek rozcházel.
Od verze 4.1.3 řeší CssInliner konflikty skutečnou CSS
kaskádou jako prohlížeč: !important porazí obyčejné
deklarace, existující inline styl porazí selektory, pak rozhoduje specificita
a teprve nakonec pořadí. Do výstupu se navíc zapíše jen vítězná
hodnota, takže atributy style už nenafukují poražené
deklarace. A oprava se dočkala i konverze na HTML atributy pro Outlook:
width: auto dřív vygenerovalo width="0" a sloupec
v Outlooku zkolaboval do nuly; teď se atribut prostě nevytvoří.
FileMailer a další drobnosti
Nový FileMailer nic neodesílá: každou zprávu zapíše jako
soubor .eml do zadaného adresáře. Soubor otevřeš
v libovolném e-mailovém klientovi a přesně vidíš, co by odešlo.
Ideální do testů a při vývoji:
$mailer = new Nette\Mail\FileMailer(__DIR__ . '/mails');
$mailer->send($mail);
Kolem toho se sešla řada menších vylepšení, která poznáš, až o ně půjde:
- Adresy s mezinárodní doménou jako
jan@příklad.czse automaticky převedou na punycode, takže je běžné SMTP servery neodmítnou. - STARTTLS má výchozí port 587 a vyjednává výhradně TLS 1.2 a 1.3; při selhání handshake se dozvíš skutečný důvod.
- Persistentní spojení, které server mezitím zavřel, se před dalším odesláním tiše obnoví, místo aby každý pokus skončil chybou.
- Velké přílohy se už nemohou tiše uříznout, když se zaplní odesílací buffer, a timeouty platí i proti serveru, který nikdy nepřestane odpovídat.
FallbackMailerse nevrací k mailerům, jejichž selhání je trvalé, například kvůli odmítnutým přihlašovacím údajům.
Jak aktualizovat
Verze 4.1.3 je zpětně kompatibilní, takže stačí obvyklé:
composer update nette/mail
Odeslat e-mail je pořád jeden řádek kódu. O to, aby skutečně dorazil, se teď o poznání víc postará knihovna. Kompletní přehled všech možností najdeš v dokumentaci.
Další čtení
- Nette Http 3.4.0 přináší ochranu proti SSRF útokům
- Latte 3.1: Když šablonovací systém skutečně rozumí HTML
- Formulář ve formuláři? HTML to zakazuje, Nette 3.3 ne
- Nette Utils 4.0: UTF-8, Finder a pojmenované argumenty
- Pět novinek v Latte 3.1, které vám zpříjemní život
- Latte: jeden řádek a lokalizuje za vás
Chcete-li odeslat komentář, přihlaste se