Email ako komponenta alebo klasika
- SontoEremo
- Člen | 341
Rád by som sa Vás spýtal ako riešite zasielanie mailu?
či to máte ako komponentu alebo si odosielanie mailu vkladáte tam kde to
potrebujete?
- jarda256
- Člen | 130
Ahoj, předem říkám, že netvrdím, že moje řešení je správné, ale
mám to takto. Používám tedy mailgun, ale i bez něj se to dá použít.
V abstraktní třídě (v mém případě AbstractBaseFacade
)
mám protected $mailSender
a funkci setMailSender. V konfigu pak
nastavený decorator pro AbstractBaseFacade
. Potom všichni potomci
třídy AbstractBaseFacade
mohou využít funkci sendMail
$mail = new Message();
$mail->addTo($person->email);
$params = [
'a' => $a,
'b' => $b,
'c' => $c,
];
$mail->setSubject('Potvrzení registrace');
$this->mailSender->sendEmail($mail, 'confirmRegistration.latte', $params);
decorator:
App\Model\Facades\AbstractBaseFacade:
setup:
- setEntityManager
- setMailSender
<?php
namespace App\Model\Facades;
use App\MailSender;
use Kdyby\Doctrine\EntityManager;
use Nette\Object;
/**
* Základní fasáda pro všechny ostatní fasády aplikace.
* Předává přístup pro práci s entitami.
* @package App\Model\Facades
*/
abstract class AbstractBaseFacade extends Object
{
/** @var EntityManager */
protected $em;
/** @var MailSender */
protected $mailSender;
public function setEntityManager(EntityManager $em)
{
$this->em = $em;
}
public function setMailSender(MailSender $mailSender)
{
$this->mailSender = $mailSender;
}
}
<?php
namespace App;
use Nette\Application\LinkGenerator;
use Nette\Bridges\ApplicationLatte\ILatteFactory;
use Nette\Bridges\ApplicationLatte\UIMacros;
use Nette\Mail\Message;
use Nette\Mail\IMailer;
use Nette\Mail\SendmailMailer;
use Nette\Mail\SmtpException;
use Nette\Mail\SmtpMailer;
use Kdyby\Doctrine\EntityManager;
use Tracy\Debugger;
class MailSender
{
/** @var SmtpMailer */
protected $smtpMailer;
/** @var SendmailMailer */
protected $sendMailer;
/** @var EntityManager */
protected $em;
/** @var LinkGenerator */
private $linkGenerator;
/** @var ILatteFactory */
private $latteFactory;
function __construct(EntityManager $em, LinkGenerator $lg, ILatteFactory $latteFactory)
{
$this->em = $em;
$this->linkGenerator = $lg;
$this->latteFactory = $latteFactory;
$this->smtpMailer = new SmtpMailer([
'host' => 'smtp.mailgun.org',
'username' => '',
'password' => '',
'secure' => 'ssl',
]);
$this->sendMailer = new SendmailMailer();
}
function sendEmail(Message $message, $template, $variables)
{
$latte = $this->latteFactory->create();
UIMacros::install($latte->getCompiler());
$latte->addProvider("uiControl", $this->linkGenerator);
$html = $latte->renderToString(__DIR__ . '/' . $template, [
'variables' => $variables
]);
$message
->setFrom('info@domena.cz', 'Domena')
->setHtmlBody($html);
try{
$this->smtpMailer->send($message);
} catch (SmtpException $e){
$this->sendMailer->send($message);
}
}
}
- SontoEremo
- Člen | 341
@jarda256
Ďakujem za odpoveď a aj priložené kódy… presne toto sa snažím docieliť
len som nevedel ako dať vedie aké latte zaslať.
$this->mailSender->sendEmail($mail, 'confirmRegistration.latte', $params);
ani ma nenapadlo toto použiť…
Ešte sa ta spýtam ak by som chcel z congig.neon odoslať údaje do MailSender
ako to mám preniesť? lebo toto riešim v config.neon či to je jedno a je to
bezpečné uvádzať aj v MailSender?
- akadlec
- Člen | 1326
Mail sender by IMHO měla být služba a tam kde je potřeba poslat mail by se měla vyžadovat. Dělat to jako komponentu je nepochopení celého nettefw. Cpát ji přes dekorátor do nějaké fasády? No nevim nevim, snad jen pro nějaký „quick“ projekt co se zbouchá za víkend a pak už se na něj nehrábe.
- SontoEremo
- Člen | 341
@CZechBoY @akadlec
Takže je lepšie dávať všade
$template = $this->templateFactory->createTemplate();
$template->setFile('App\Presenters\Templates\Messages\activation.latte');
$template->verifyLink = $this->linkGenerator->link('Global:activationAccount', array(
'token' => $token,
));
$mail = new Message;
$mail->setFrom('Mystical Vision <email@email.xx>')
->addTo($values->email)
->setSubject('Aktivácia účtu na stránke PageName')
->setHtmlBody((string) $template, __DIR__ . '/../../assets/global/img/');
$this->mailer->send($mail);
Tam kde registrujte zas registračný mail atď…?
- CZechBoY
- Člen | 3608
Určitě si to můžeš zjednodušit nějakou svojí továrnou, ale předej
si ji normálně tam kde to potřebuješ a ne úplně všude.
btw. Na tohle jsou dobrý události. Vyvoláš událost někdo se registroval,
mailovej modul se přihlásí k té události a pošle email nezávisle na tom
kdo tu událost vyvolal (databázová vrstva nemusí vůbec o mailech
vědět).
- SontoEremo
- Člen | 341
Tak som sa pokúsil niečo skúsiť napísať ale samozrejme končí to
chybou ale nie tracy ale klasické php…
IEmailSenderFactory
<?php
namespace App\Emails;
interface IEmailSenderFactory {
/**
* @return EmailSender
*/
function create();
}
EmailSender
<?php
namespace App\Emails;
use Tracy\Debugger;
use Nette\Mail\IMailer;
use Nette\Mail\Message;
use Nette\Mail\SmtpMailer;
use Nette\Mail\SmtpException;
use Latte\Loaders\StringLoader;
use Nette\Application\UI\Control;
use Nette\Application\UI\ITemplateFactory;
class EmailSender extends Control {
/** @var Nette\Mail\IMailer @inject */
private $mailer;
/** @var Nette\Application\UI\ITemplateFactory */
private $templateFactory;
public function __construct(IMailer $mailer, ITemplateFactory $templateFactory) {
$this->mailer = $mailer;
$this->templateFactory = $templateFactory;
}
public function sendEmail(Message $message, $template, $variables) {
try {
$this->mailer = new SmtpMailer([
'smtp' => 'true',
'host' => 'smtp.gmail.com',
'username' => 'xx@xx.xxx',
'password' => '*******',
'port' => 465,
'secure' => 'ssl',
]);
$template = $this->templateFactory->createTemplate();
$template->setFile(__DIR__ . 'messages/' . $template);
$message->setFrom('Page Name <xx@xx.xx>')
->setHtmlBody($template);
$this->mailer->send($message);
} catch (SmtpException $e) {
$this->addError("Odoslanie mailu zlyhalo", "warning");
}
}
}
A SignUpFormFacory
$mail = new Message();
$mail->addTo($values->email);
$mail->setSubject('Aktivácia účtu na stránke Mystical Vision');
$this->emailSender->sendEmail($mail, 'activation.latte');
Po odoslaní nastane chyba
Fatal error: Uncaught TypeError: Argument 1 passed to
Tracy\Helpers::getSuggestion() must be of the type array, null given, called in
C:\xampp\htdocs\mysticalvision\vendor\tracy\tracy\src\Tracy\Helpers.php on line
178 and defined in
C:\xampp\htdocs\mysticalvision\vendor\tracy\tracy\src\Tracy\Helpers.php:211
Stack trace: #0
C:\xampp\htdocs\mysticalvision\vendor\tracy\tracy\src\Tracy\Helpers.php(178):
Tracy\Helpers::getSuggestion(NULL, ‚sendEmail‘) #1
C:\xampp\htdocs\mysticalvision\vendor\tracy\tracy\src\Tracy\Debugger.php(281):
Tracy\Helpers::improveException(Object(Error)) #2 [internal function]:
Tracy\Debugger::exceptionHandler(Object(Error)) #3 {main} thrown in
C:\xampp\htdocs\mysticalvision\vendor\tracy\tracy\src\Tracy\Helpers.php on
line 211
- SontoEremo
- Člen | 341
uestla napsal(a):
Co je v
$this->emailSender
vSignUpFormFacory
?
/** @var App\Emails\IEmailSenderFactory */
public $emailSender;
public function __construct(FormFactory $factory, UserManager $userManager, LinkGenerator $linkGenerator, IEmailSenderFactory $emailSender) {
$this->factory = $factory;
$this->userManager = $userManager;
$this->linkGenerator = $linkGenerator;
$this->emailSender = $emailSender;
}
- igor.pocta
- Člen | 100
SontoEremo napsal(a):
Rád by som sa Vás spýtal ako riešite zasielanie mailu?
či to máte ako komponentu alebo si odosielanie mailu vkladáte tam kde to potrebujete?
My máme e-mailovou frontu v databázi, kde jsou dané priority. O odeslání se stará cron a posílá to po dávkách aby nám neodstřelil SMTP :D
Takže v podstatě jen vyrenderuji blok konkrétní úlohy (např. informace o novém úkolu) a ten uložím do databáze. Konzole spuštěná cronem si blok vezme do své šablony a odešle ji kompletně.
Editoval igor.pocta (13. 1. 2017 22:29)
- SontoEremo
- Člen | 341
@CZechBoY
Takže sa mi to podarilo spojazdniť emaily chodia…
Problém nastáva ak chcem pridať link vyhadzuje to chybu Invalid link
destination ‚activation‘.
EmailSender
<?php
namespace App\Emails;
use Tracy\Debugger;
use Nette\Mail\IMailer;
use Nette\Mail\Message;
use Nette\Mail\SmtpMailer;
use Nette\Mail\SmtpException;
use Latte\Loaders\StringLoader;
use Nette\Application\UI\Control;
use Nette\Application\LinkGenerator;
use Nette\Bridges\ApplicationLatte\UIMacros;
use Nette\Bridges\ApplicationLatte\ILatteFactory;
class EmailSender {
/** @var Nette\Mail\IMailer @inject */
private $mailer;
/** @var ILatteFactory */
private $latteFactory;
/** @var Nette\Application\LinkGenerator */
public $linkGenerator;
public function __construct(IMailer $mailer, ILatteFactory $latteFactory, LinkGenerator $linkGenerator) {
$this->mailer = $mailer;
$this->linkGenerator = $linkGenerator;
$this->latteFactory = $latteFactory;
}
public function sendEmail(Message $message, $template, $variables) {
try {
$latte = $this->latteFactory->create();
UIMacros::install($latte->getCompiler());
$latte->addProvider("uiControl", $this->linkGenerator);
$html = $latte->renderToString(__DIR__ . '/messages/' . $template, ['variable' => $variables]);
$message->setFrom('Page Name <xx@xx.xx>')
->setHtmlBody((string) $html, __DIR__ . '/../../assets/global/img/');
$this->mailer->send($message);
} catch (SmtpException $e) {
$this->addError("Odoslanie mailu zlyhalo", "warning");
}
}
}
SignUpFormFacory
$template = $this->templateFactory->createTemplate();
$template->verifyLink = $this->linkGenerator->link(
'activation',
[
'token' => $token,
]);
$mail = new Message();
$mail->addTo($values->email);
$mail->setSubject('Aktivácia účtu na stránke Page Name');
$this->emailSender->sendEmail($mail, 'activation.latte', $template);
Neviem ako povedať SignUpFormFacory že activation sa nachádza v App\Emails\Messages
- SontoEremo
- Člen | 341
@CZechBoY
Dal som to do GlobalPResenter ktorý sa má
createComponentSignUpForm()
/**
* Sign-up form factory.
* @return Nette\Application\UI\Form
*/
protected function createComponentSignUpForm() {
return $this->signUpFactory->create(function () {
$token = Random::generate(32);
$template = $this->templateFactory->createTemplate();
$template->verifyLink = $this->linkGenerator->link('activation', ['token' => $token]);
$mail = new Message();
$mail->addTo($values->email);
$mail->setSubject('Aktivácia účtu na stránke Mystical Vision');
$this->emailSender->sendEmail($mail, 'activation');
$this->redirect(':Homepage:default');
});
}
Ale stále to vyhadzuje Invalid link destination
‚activation‘.
Musím teda šablónu activation.latte ktorú mám v App\Emails\Messages dať
do App\Presenters\Templates\Global?
tam mám login.latte register.latte atď…
Editoval SontoEremo (14. 1. 2017 12:50)
- David Matějka
- Moderator | 6445
jde o to generovani linku
$this->linkGenerator->link('activation', ['token' => $token]);
nestaci jen activation, musis uvest vcetne presenteru (bez dvojtecky na zacatku)
- SontoEremo
- Člen | 341
David Matějka napsal(a):
jde o to generovani linku
$this->linkGenerator->link('activation', ['token' => $token]);
nestaci jen activation, musis uvest vcetne presenteru (bez dvojtecky na zacatku)
Lenže EmailSender nemá presenter a activation mám v App\Emails\Messages\ mám teda activation preniesť do App\Presenters\Templates\Global\?
- SontoEremo
- Člen | 341
predtým som mal activation v Global a link bol
->link(‚Global:activation‘, [‚token‘ ⇒
$token])
lenže teraz ako sa pokúšam mať mail ako Službu tak mám zložku Emails a
vnej messages kde sa nachádza aj activation… neviem ako to teda
spraviť…
- David Matějka
- Moderator | 6445
odesilani mas jako sluzbu. ale ten odkaz, na ktery ten uzivatel prijde, musi byt presenter.
- SontoEremo
- Člen | 341
David Matějka napsal(a):
odesilani mas jako sluzbu. ale ten odkaz, na ktery ten uzivatel prijde, musi byt presenter.
až teraz keď som to začal písať mi to zaplo ja som mal použiť
$template->setFile('App\Emails\Message\activation.latte');
čo sa odosiela na mail a
$template->verifyLink = $this->linkGenerator->link('Global:activationAccount', ['token' => $token]);
čo užívateľa prenesie na domena.xx/global/activationAccount
lenže mi to vyhadzuje chybu Undefined variable: verifyLink
<a href="{$verifyLink|noescape}">
Aktivovať účet
</a>
Ako dostať $verifyLink do App\Emails\Message\activation.latte
- David Matějka
- Moderator | 6445
ted na to koukam poradne a mas to (zas) nejaky pomateny. v signupformfactory
vytvaris template, kterou posilas do sendMail jako treti parametr
variables
a to pak posilas do dalsi sablony… zkus se nad tim
zamyslet, jestli je to opravdu tahle spravne ;)
- SontoEremo
- Člen | 341
@DavidMatějka
zo SignUpFormFactory som to preniesol do GlobalPresenter
/**
* Sign-up form factory.
* @return Nette\Application\UI\Form
*/
protected function createComponentSignUpForm() {
return $this->signUpFactory->create(function () {
$token = Random::generate(32);
$template = $this->templateFactory->createTemplate();
$template->setFile('App\Emails\Message\activation.latte');
$template->verifyLink = $this->linkGenerator->link('Global:activationAccount', ['token' => $token]);
$mail = new Message();
$mail->addTo('email@email.xx');
$mail->setSubject('Aktivácia účtu na stránke PageName');
$this->emailSender->sendEmail($mail, 'activation', $template);
$this->redirect('this');
});
}
SignUpFormFactory sa už stará iba o insert
Editoval SontoEremo (14. 1. 2017 14:18)
- SontoEremo
- Člen | 341
Tak sa mi to podarilo takto hádam je to dobré…
SendMailFacory
<?php
namespace App\Emails;
use Tracy\Debugger;
use Nette\Object;
use Nette\Mail\IMailer;
use Nette\Mail\Message;
use Nette\Mail\SmtpException;
class SendMailFacory {
/** @var Nette\Mail\IMailer @inject */
private $mailer;
public function __construct(IMailer $mailer) {
$this->mailer = $mailer;
}
public function sendEmail(Message $message) {
try {
$message->setFrom('PageName <email@email.xx>');
$this->mailer->send($message);
} catch (SmtpException $e) {
$this->addError("Odoslanie mailu zlyhalo", "warning");
}
}
}
GlobalPresenter
/**
* Sign-up form factory.
* @return Nette\Application\UI\Form
*/
protected function createComponentSignUpForm() {
return $this->signUpFactory->create(function () {
$token = Random::generate(32);
$template = $this->templateFactory->createTemplate();
$template->setFile('App/Emails/Messages/activation.latte');
$template->verifyLink = $this->linkGenerator->link('Global:activationAccount', ['token' => $token]);
$mail = new Message();
$mail->addTo('email@email.xx');
$mail->setSubject('Aktivácia účtu na stránke Page Name');
$mail->setHtmlBody((string) $template, __DIR__ . '/../../assets/global/img/');
$this->sendMailFactory->sendEmail($mail, $template);
$this->redirect('this');
});
}