Odesílání e-mailů#
E-mail se v tomhle systému nikdy neposílá přímo z presenteru. Manager zavolá jednu
ze tří metod z SendEmailTrait, ta zprávu sestaví a podle nastavení ji buď zařadí do
fronty, nebo odešle hned. Frontu pak rozesílá cron.
Kód: app/Core/Traits/Api/System/Models/Managers/SendEmailTrait.php (Api varianta)
a app/Core/Traits/Shared/System/Models/Managers/SendEmailTrait.php (sdílená).
Tři metody#
| Metoda | Kdy ji použít |
|---|---|
sendEmail($langId, $emailKey, $to, $values, …) |
výchozí volba — šablona z databáze podle klíče, v jazyce příjemce |
sendEmailFromText($subject, $body, $from, $to, $values, …) |
text sestavený v kódu; šablona v databázi neexistuje |
sendEmailToAll($emailKey, $recipients, $values, …) |
hromadné rozeslání téže šablony více příjemcům |
Všechny berou $values (zástupné texty do šablony), $files (přílohy) a $replyTos.
Adresa pro odpověď se hodí tam, kde má příjemce psát někomu jinému než systému
Typicky u odpovědi na inzerát: zprávu odešle systém, ale odpovědět se má inzerentovi.
Kam zpráva jde: nastavení 1/emailSending#
Tohle je jediné místo, které rozhoduje mezi frontou a okamžitým odesláním:
| Hodnota | Chování |
|---|---|
1 |
všechno do fronty (výchozí) |
2 |
do fronty jen nepřednostní; přednostní odchází okamžitě |
| jinak | vše se odesílá okamžitě, fronta se nepoužije |
Proč vůbec fronta
Odeslání trvá vteřiny. Objednávka posílající dva e-maily by se odbavovala znatelně déle — a při výpadku poštovního serveru by spadla celá. Takhle jen počká zpráva.
Přednostní zpráva má smysl jen u režimu 2
Příznak preferred odlišuje potvrzení registrace nebo obnovu hesla od hromadné
rozesílky. Při emailSending: 1 jde do fronty i ta — a předběhne newsletter až tam,
ne dřív.
Fronta#
Entita EmailQueue nese příjemce, odesílatele, předmět, tělo, přílohy, adresy pro
odpověď a k tomu provozní pole:
| Pole | Význam |
|---|---|
sent, sendDatetime |
odesláno a kdy |
attempts |
počet pokusů |
errorLog |
poslední chyba |
preferred |
přednost před hromadnou rozesílkou |
stopped |
ruční zastavení — zpráva se nebude zkoušet dál |
newsletter |
vazba na rozesílku, když jde o newsletter |
Rozesílá cron /cron/system/email-queue/send — à minutu.
Bez běžícího cronu neodejde nic a nikdo se to nedozví
Fronta jen roste. Uživatel neuvidí chybu, protože z pohledu aplikace se odeslání povedlo — zpráva se přece uložila. Po nasazení proto ověřte, že úloha běží, a pak to ověřte znovu.
Newsletter je záměrně pomalý
Tisíce zpráv během vteřiny vypadají poštovním serverům jako spam. Dávkování je ochrana reputace domény, ne nedodělek.
Šablony#
Šablony jsou v databázi, klíčované řetězcem, s textem pro každý jazyk zvlášť
a zástupnými texty, které se nahradí z $values.
Klíč šablony se nepřejmenovává
Kód si šablonu hledá právě podle něj (findBy([new EqualFilter(['key'], [$emailKey])])).
Po přejmenování sendEmail() šablonu nenajde, vrátí neúspěch — a protože se
návratová hodnota často nekontroluje, zpráva prostě přestane chodit.
Chybějící překlad šablony znamená e-mail v jiném jazyce, ne chybu
Text se hledá pro $langId příjemce. Není-li, použije se fallback — příjemce
dostane zprávu v hlavním jazyce.
Postup: přidávám nový e-mail#
- Založ šablonu v administraci (Systém → E-maily) a dej jí klíč, který už neexistuje.
- Vyplň text pro všechny jazyky — ne jen pro hlavní.
- Zavolej
sendEmail()z manageru, ne z presenteru:
$this->sendEmail(
langId: $user->getLanguageId(),
emailKey: 'order.confirmation',
toEmailAddrr: $order->getEmail(),
values: ['orderNumber' => $order->getNumber()],
);
- Volej to z
completedSave/completedDelete, tedy až po commitu. - Vyhodnoť výsledek — neúspěch znamená, že se zpráva ani nezařadila do fronty.
- Ověř na vývojovém stroji, kam zpráva doopravdy odešla (viz níž).
E-mail v afterSave odejde i tehdy, když se transakce vrátí zpět
afterSave běží uvnitř transakce. Zpráva o vzniklé objednávce se odešle,
objednávka se rollbackne — a zákazník má v ruce potvrzení něčeho, co neexistuje.
Nevratné efekty patří za commit, viz
Životní cyklus manageru.
V cronu se pole NEfiltrují podle publika
Rozesílka běží mimo požadavek, takže #[FieldAccess] se neuplatní — a je to
záměr, aktivační e-mail potřebuje activationKey. Znamená to ale, že co se dostane
do těla zprávy, si musí ohlídat autor šablony a $values.
Vývojové prostředí#
Dev a produkce sdílejí databázi
Zkušební rozesílka může dorazit skutečným zákazníkům. Než něco odešlete,
ověřte hodnotu 1/emailSending a obsah fronty — a u hromadné rozesílky raději
zkontrolujte i seznam příjemců.
Kam sáhnout#
| Chci | Kde |
|---|---|
| tři metody odesílání | app/Core/Traits/Api/System/Models/Managers/SendEmailTrait.php |
| rozhodnutí fronta × okamžitě | app/Core/Traits/Shared/System/Models/Managers/SendEmailTrait.php |
| entitu fronty | app/Core/Base/Shared/System/Models/Entities/EmailQueue.php |
| rozesílací cron | app/UI/Cron/System/Presenters/EmailQueuePresenter.php |
| správu šablon | administrace → Systém → E-maily |
Navazující kapitoly: Životní cyklus manageru · Cron presentery · Naplánované úlohy · Překlady