Wysyłanie e-maili
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 Konfiguracja, 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 dlassl
timeout
– 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 |