Jak odesíláte v Nette e-maily?

nettebeginer
Člen | 1
+
0
-

Ahoj,
mám na vás takovou abstraktní otázku… Jak v Nette odesíláte e-maily? Vím, že Nette má třídu Nette\Mail\SendmailMailer a Nette\Mail\Message, ale není asi úplně praktické a správné ji používat všude v presenterech a modelech, kde potřebuju odeslat email. Navíc i s ní je to pořád dost práce a redundantního kódu: musím vytvořit mail, nastavit adresy, vyrenderovat latte šablonu, vytvořit mailer…
Takže se samozřejmě asi nabízí vytvořit si pro to samostatnou třídu, která vše nastaví a já předám pouze šablonu a parametry. Přemýšlím ale, kam taková třída patří, model to úplně není, presenter úplně také ne. Dále přemýšlím, jestli by to nebylo dobré ještě obalit nějakým systémem notifikací, který by zároveň také v databázi ověřil nastavení notifikací uživatele a v budoucnu obsloužil třeba i odeslání SMS apod.

Chci to vyřešit nějak robustně hned na začátku, abych to nemusel za pár měsíců celé předělávat. Škoda, že neexistují (nebo alespoň jsem nenašel) nějaké „best practices“ příklady reálných aplikací, kde by se dalo inspirovat, jak podobné situace implementovat… Jak to děláte vy?

ForestCZE
Člen | 209
+
0
-

Ahoj, já osobně to mám v modelu, i když to není úplně model, ale myslím si, že to až tak nevadí. Normální třída s těmi usingy, o kterých se zmiňuješ. Dvě metody – jedna na sestavení, druhá na odeslání. A pak mám metody, kde skládám HTML obsah, podle toho, o jaký e-mail se jedná. Nakonec jednoduše v presenteru (ve formu nebo handlu) zavoláš metody a pošleš, co potřebuješ. Notifikace jsem zatím neřešil.

Editoval ForestCZE (4. 8. 2020 15:45)

F.Vesely
Člen | 368
+
+2
-

Proc to podle tebe neni model?

Kamil Valenta
Člen | 758
+
+2
-

Vytvořit mail, nastavit adresy, vyrenderovat šablonu musíš, ale to není redundance, vždyť každý mail bude jiný.
Vytvářet mailer nemusíš, vyžádej si jej z DI.

dms
Člen | 87
+
0
-

Na notifikace je vyborny pouzivat https://github.com/…t-dispatcher muzes v budoucnu pridat novy subscriber napr na sms a nijak nemusis sahat do kodu

joe
Člen | 313
+
+2
-

Mám továrnu na vytváření mailů. Každý mail má svou vlastní třídu.

MailFactory.php

public function create(string $class)
{
    return new $class(...); // každému mailu se předávají závislosti
}

NewOrderMail.php

public function compose(Order $order, ... /* a vše, co konkrétní mail všechno vyžaduje */)
{
    // převážně jen předávání proměnných do šablony
    $this->template->order = $order;
}

public function send()
{
    // metoda v rodiči
}

NewOrderMail.latte

{varType App\Model\Entity\Order $order}

{extends '@mail.latte'}

{block content}
    <table>
        <tr>
            <td>Objednávka ID:</td><td>{$order->id}</td>
        </tr>
    </table>

    <style media="emogrifier">
        /* ;-) */
    </style>
{/block}

a v presenteru pak samotné vytvoření a odeslání e-mailu vypadá takto

$mail = $this->mailFactory->create(NewOrderMail::class);
$mail->compose($order);
$mail->send();

Editoval joe (17. 8. 2020 1:56)

Petr Steinbauer
Člen | 26
+
+4
-

Jako nejlepší se nám ukázalo následující:

  • entita (tabulka) s frontou emailů
  • cron/rabbit spouštějící command který posílá emaily

Výhody:

  • hlavní výhoda!!! uživatel nečeká na poslání emailu, k jen přidá řádek do databáze (nebo záznam do rabbita) a nečeká na zpracování poštovními servery
  • přehled co se kde posílalo
  • všechno je v jednom místě – co se neposlalo tady, tak se neposlalo
  • v commandu může být úplně jinde, na jiném containeru a logovat zcela nějak jinak (GDPR)
  • v commandu mohu specifikovat vlastní pravidla, různé smtp servery, atd..
  • lze si rozmyslet návrhový vzor více způsoby – buď do entity ukládat celé změní emailu, nebo jen proměnné a command vygeneruje text emailu z těchto proměných na místě
David Matějka
Moderator | 6445
+
+4
-

jestě bych k @PetrSteinbauer doplnil zásadní výhodu a to je transakční bezpečnost (tedy pokud samozřejmě transakce používáme). Tedy že se nám nestane, že by se třeba odeslal mail, ale následně selhalo uložení do databáze, takže někomu by přišel mail s informací o věci, co vlastně neplatí.

joe
Člen | 313
+
0
-

@PetrSteinbauer A jak to je prosim napriklad pri registraci a poslani e-mailu uzivateli? Pridate zaznam do db a pak se zpracuje poslani e-mailu? Takze je treba rozlisit zpravy s ruznyma prioritama?

Petr Steinbauer
Člen | 26
+
0
-

joe napsal(a):

@PetrSteinbauer A jak to je prosim napriklad pri registraci a poslani e-mailu uzivateli? Pridate zaznam do db a pak se zpracuje poslani e-mailu? Takze je treba rozlisit zpravy s ruznyma prioritama?

Ahoj,
u registraci/resetu hesla je to úplně stejně, do entity/tabulky si přidáte prioritu kterou má Cron zpracovávat přednostně.

Pokud očekáváte desítky emailů za sekundu a cron by nestačil, použijte rabbit nebo paralerizaci. Pro eshopy do pár stovek emailů to bohatě stačí.