Nette Mail
Chcesz wysyłać e-maile, na przykład newslettery lub potwierdzenia zamówień? Nette Framework dostarcza niezbędnych narzędzi z bardzo przyjaznym API. Pokażemy:
- jak utworzyć e-mail wraz z załącznikami
- jak go wysłać
- jak połączyć e-maile i szablony
Instalacja
Bibliotekę pobierzesz i zainstalujesz za pomocą narzędzia Composer:
composer require nette/mail
Tworzenie e-maila
E-mail jest obiektem klasy Nette\Mail\Message. Utworzymy go na przykład tak:
$mail = new Nette\Mail\Message;
$mail->setFrom('Franta <franta@example.com>')
->addTo('petr@example.com')
->addTo('jirka@example.com')
->setSubject('Potwierdzenie zamówienia')
->setBody("Dzień dobry,\nTwoje zamówienie zostało przyjęte.");
Wszystkie podawane parametry muszą być w UTF-8.
Oprócz podania odbiorcy metodą addTo(), można również podać odbiorcę kopii addCc() lub
odbiorcę ukrytej kopii addBcc(). We wszystkich tych metodach, włącznie z setFrom(), adresata możemy
zapisać na trzy sposoby:
$mail->setFrom('franta@example.com');
$mail->setFrom('franta@example.com', 'Franta');
$mail->setFrom('Franta <franta@example.com>');
Treść e-maila zapisaną w HTML przekazuje się metodą setHtmlBody():
$mail->setHtmlBody('<p>Dzień dobry,</p><p>Twoje zamówienie zostało przyjęte.</p>');
Nie musisz tworzyć alternatywy tekstowej, Nette wygeneruje ją automatycznie za Ciebie. A jeśli e-mail nie ma ustawionego
tematu, spróbuje go pobrać z elementu <title>.
W treści HTML można również niezwykle łatwo wstawiać obrazy. Wystarczy jako drugi parametr przekazać ścieżkę, gdzie obrazy fizycznie się znajdują, a Nette automatycznie dołączy je do e-maila:
// automatycznie doda /path/to/images/background.gif do e-maila
$mail->setHtmlBody(
'<b>Hello</b> <img src="background.gif">',
'/path/to/images',
);
Algorytm wstawiający obrazy wyszukuje następujące wzorce: <img src=...>,
<body background=...>, url(...) wewnątrz atrybutu HTML style oraz specjalną
składnię [[...]].
Czy wysyłanie e-maili może być jeszcze prostsze?
E-mail jest jak pocztówka. Nigdy nie wysyłaj e-mailem haseł ani innych danych dostępowych.
Załączniki
Do e-maila można oczywiście wstawiać załączniki. Służy do tego metoda
addAttachment(string $file, ?string $content = null, ?string $contentType = null).
// wstawia plik /path/to/example.zip do e-maila pod nazwą example.zip
$mail->addAttachment('/path/to/example.zip');
// wstawia plik /path/to/example.zip do e-maila o nazwie info.zip
$mail->addAttachment('info.zip', file_get_contents('/path/to/example.zip'));
// wstawia plik example.txt do e-maila z zawartością "Hello John!"
$mail->addAttachment('example.txt', 'Hello John!');
Szablony
Jeśli wysyłasz e-maile HTML, naturalnym rozwiązaniem jest zapisywanie ich w systemie szablonów Latte. Jak to zrobić?
$latte = new Latte\Engine;
$params = [
'orderId' => 123,
];
$mail = new Nette\Mail\Message;
$mail->setFrom('Franta <franta@example.com>')
->addTo('petr@example.com')
->setHtmlBody(
$latte->renderToString('/path/to/email.latte', $params),
'/path/to/images',
);
Plik email.latte:
<html>
<head>
<meta charset="utf-8">
<title>Potwierdzenie zamówienia</title>
<style>
body {
background: url("background.png")
}
</style>
</head>
<body>
<p>Dzień dobry,</p>
<p>Twoje zamówienie numer {$orderId} zostało przyjęte.</p>
</body>
</html>
Nette automatycznie wstawi wszystkie obrazy, ustawi temat według elementu <title> i wygeneruje
alternatywę tekstową dla HTML.
Użycie w Nette Application
Jeśli używasz e-maili razem z Nette Application, tj. z presenterami, możesz chcieć tworzyć linki w szablonach za pomocą
atrybutu n:href lub znacznika {link}. Latte domyślnie ich nie zna, ale bardzo łatwo je dodać.
Tworzyć linki potrafi obiekt Nette\Application\LinkGenerator, do którego można uzyskać dostęp, prosząc o jego
przekazanie za pomocą wstrzykiwania
zależności:
use Nette;
class MailSender
{
public function __construct(
private Nette\Application\LinkGenerator $linkGenerator,
private Nette\Bridges\ApplicationLatte\TemplateFactory $templateFactory,
) {
}
private function createTemplate(): Nette\Application\UI\Template
{
$template = $this->templateFactory->createTemplate();
$template->getLatte()->addProvider('uiControl', $this->linkGenerator);
return $template;
}
public function createEmail(): Nette\Mail\Message
{
$template = $this->createTemplate();
$html = $template->renderToString('/path/to/email.latte', $params);
$mail = new Nette\Mail\Message;
$mail->setHtmlBody($html);
// ...
return $mail;
}
}
W szablonie tworzymy linki tak, jak jesteśmy przyzwyczajeni. Wszystkie linki utworzone przez LinkGenerator będą absolutne.
<a n:href="Presenter:action">Link</a>
Wysyłanie e-maila
Mailer to klasa zapewniająca wysyłanie e-maili. Implementuje interfejs Nette\Mail\Mailer i dostępnych jest kilka gotowych mailerów, które przedstawimy.
Framework automatycznie dodaje do kontenera DI usługę typu Nette\Mail\Mailer skonfigurowaną na podstawie Konfiguracji, do której można uzyskać dostęp, prosząc o jej przekazanie za pomocą wstrzykiwania zależności.
SendmailMailer
Domyślnym mailerem jest SendmailMailer, który używa funkcji PHP mail. Przykład użycia:
$mailer = new Nette\Mail\SendmailMailer;
$mailer->send($mail);
Jeśli chcesz ustawić returnPath, a serwer ciągle go nadpisuje, użyj
$mailer->commandArgs = '-fMoj@email.cz'.
SmtpMailer
Do wysyłania poczty przez serwer SMTP służy SmtpMailer.
$mailer = new Nette\Mail\SmtpMailer(
host: 'smtp.gmail.com',
username: 'franta@gmail.com',
password: '*****',
encryption: 'ssl',
);
$mailer->send($mail);
Konstruktorowi można przekazać następujące dodatkowe parametry:
port– jeśli nie jest ustawiony, użyje się domyślnego 25 lub 465 dlassltimeout– timeout dla połączenia SMTPpersistent– użyj połączenia trwałegoclientHost– ustawienie nagłówka Host klientastreamOptions– umożliwia ustawienie SSL context options dla połączenia
FallbackMailer
Nie wysyła e-maili bezpośrednio, ale pośredniczy w wysyłaniu przez zestaw mailerów. W przypadku, gdy jeden mailer zawiedzie, ponawia próbę u następnego. Jeśli zawiedzie i ostatni, zaczyna ponownie od pierwszego.
$mailer = new Nette\Mail\FallbackMailer([
$smtpMailer,
$backupSmtpMailer,
$sendmailMailer,
]);
$mailer->send($mail);
Jako dodatkowe parametry w konstruktorze możemy podać liczbę powtórzeń i czas oczekiwania w milisekundach.
DKIM
DKIM (DomainKeys Identified Mail) to technologia zwiększająca wiarygodność e-maili, która również pomaga w wykrywaniu sfałszowanych wiadomości. Wysłana wiadomość jest podpisywana prywatnym kluczem domeny nadawcy, a ten podpis jest przechowywany w nagłówku e-maila. Serwer odbiorcy porównuje ten podpis z publicznym kluczem przechowywanym w rekordach DNS domeny. Zgodność podpisu dowodzi, że e-mail rzeczywiście pochodzi z domeny nadawcy i że podczas przesyłania wiadomości nie doszło do jej modyfikacji.
Podpisywanie e-maili można ustawić w mailerze bezpośrednio w konfiguracji. Jeśli nie używasz wstrzykiwania zależności, używa się go w ten sposób:
$signer = new Nette\Mail\DkimSigner(
domain: 'nette.org',
selector: 'dkim',
privateKey: file_get_contents('../dkim/dkim.key'),
passPhrase: '****',
);
$mailer = new Nette\Mail\SendmailMailer; // lub SmtpMailer
$mailer->setSigner($signer);
$mailer->send($mail);
Konfiguracja
Przegląd opcji konfiguracyjnych dla Nette Mail. Jeśli nie używasz całego frameworka, a tylko tej biblioteki, przeczytaj, jak wczytać konfigurację.
Do wysyłania e-maili standardowo używa się mailera Nette\Mail\SendmailMailer, który nie wymaga dalszej
konfiguracji. Możemy go jednak przełączyć na Nette\Mail\SmtpMailer:
mail:
# użyje SmtpMailer
smtp: true # (bool) domyślnie false
host: ... # (string)
port: ... # (int)
username: ... # (string)
password: ... # (string)
timeout: ... # (int)
encryption: ... # (ssl|tls|null) domyślnie null (ma alias 'secure')
clientHost: ... # (string) domyślnie $_SERVER['HTTP_HOST']
persistent: ... # (bool) domyślnie false
# kontekst do połączenia z serwerem SMTP, domyślnie stream_context_get_default()
context:
ssl: # przegląd opcji na https://www.php.net/manual/en/context.ssl.php
allow_self_signed: ...
...
http: # przegląd opcji na https://www.php.net/manual/en/context.http.php
header: ...
...
Za pomocą opcji context › ssl › verify_peer: false można wyłączyć weryfikację certyfikatów SSL.
Zdecydowanie odradzamy tego robić, ponieważ aplikacja stanie się podatna na ataki. Zamiast tego dodaj certyfikaty do magazynu.
Aby zwiększyć wiarygodność, możemy podpisywać e-maile za pomocą technologii DKIM:
mail:
dkim:
domain: myweb.com
selector: lovenette
privateKey: %appDir%/cert/dkim.priv
passPhrase: ...
Usługi DI
Te usługi są dodawane do kontenera DI:
| Nazwa | Typ | Opis |
|---|---|---|
mail.mailer |
Nette\Mail\Mailer | klasa wysyłająca e-maile |
mail.signer |
Nette\Mail\Signer | Podpisywanie DKIM |