Wysyłanie e-maili
Czy zamierzasz wysyłać maile takie jak newslettery czy potwierdzenia zamówień? Nette Framework dostarcza niezbędnych narzędzi z bardzo ładnym API. Zobaczmy:
- jak stworzyć wiadomość e-mail zawierającą załączniki
- jak go wysłać
- jak łączyć e-maile i szablony
Instalacja
Pobierz i zainstaluj bibliotekę za pomocą Composera:
composer require nette/mail
Tworzenie wiadomości e-mail
E-mail jest obiektem klasy Nette\Mail\Message. Możemy go utworzyć w taki sposób:
$mail = new Nette\Mail\Message;
$mail->setFrom('Franta <franta@example.com>')
->addTo('petr@example.com')
->addTo('jirka@example.com')
->setSubject('Potvrzení objednávky')
->setBody("Dobrý den,\nvaše objednávka byla přijata.");
Wszystkie parametry muszą być w języku UTF-8.
Oprócz określenia odbiorcy za pomocą metody addTo()
, można również określić odbiorcę kopii
addCc()
, lub odbiorcę ukrytej kopii addBcc()
. We wszystkich tych metodach, łącznie z
setFrom()
, można określić odbiorcę na trzy sposoby:
$mail->setFrom('franta@example.com');
$mail->setFrom('franta@example.com', 'Franta');
$mail->setFrom('Franta <franta@example.com>');
Ciało maila zapisane w HTML jest przekazywane za pomocą metody setHtmlBody()
:
$mail->setHtmlBody('<p>Dobrý den,</p><p>vaše objednávka byla přijata.</p>');
Nie musisz tworzyć tekstu alternatywnego, Nette wygeneruje go automatycznie za Ciebie. A jeśli mail nie ma ustawionego
tematu, to spróbuje go pobrać z elementu <title>
.
Niezwykle łatwe jest również wstawianie obrazów do ciała HTML. Wystarczy przekazać ścieżkę, gdzie fizycznie znajdują się obrazki jako drugi parametr, a Nette automatycznie dołączy je do maila:
// automatycznie dodaje /path/to/images/background.gif do wiadomości e-mail
$mail->setHtmlBody(
'<b>Witam</b> <img src="background.gif">',
'/path/to/images',
);
Algorytm wstawiający obrazy szuka tych wzorców: <img src=...>
, <body background=...>
,
url(...)
wewnątrz atrybutu HTML style
oraz specjalna składnia [[...]]
.
Czy wysyłanie maili może być jeszcze prostsze?
E-mail jest jak pocztówka. Nigdy nie wysyłaj haseł ani innych danych dostępowych pocztą elektroniczną.
Załączniki
Do maila można oczywiście dodać załączniki. Odbywa się to za pomocą metody
addAttachment(string $file, ?string $content = null, ?string $contentType = null)
.
// wstawia do maila plik /path/to/example.zip pod nazwą example.zip
$mail->addAttachment('/path/to/example.zip');
// wstawia do maila plik /path/to/example.zip o nazwie info.zip
$mail->addAttachment('info.zip', file_get_contents('/path/to/example.zip'));
// wstawia do maila plik example.txt o treści "Witaj John!".
$mail->addAttachment('example.txt', 'Hello John!');
Szablony
Jeśli wysyłasz e-maile w formacie HTML, warto napisać je 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>Potvrzení objednávky</title>
<style>
body {
background: url("background.png")
}
</style>
</head>
<body>
<p>Dobrý den,</p>
<p>Vaše objednávka číslo {$orderId} byla přijata.</p>
</body>
</html>
Nette automatycznie osadza wszystkie zdjęcia, ustawia temat według elementu <title>
i generuje tekstową
alternatywę dla HTML.
Zastosowanie w aplikacji Nette
Jeśli używasz e-maili w połączeniu z Nette Application, tj. prezenterami, możesz chcieć tworzyć linki w szablonach za
pomocą atrybutu n:href
lub tagu {link}
. Nie są one domyślnie znane przez Latte, ale są bardzo łatwe
do dodania. Obiekt Nette\Application\LinkGenerator
może tworzyć linki, do których możesz uzyskać dostęp,
przekazując je za pomocą zastrzyku 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;
}
}
Następnie tworzymy linki w szablonie tak jak jesteśmy do tego przyzwyczajeni. Wszystkie linki utworzone za pośrednictwem LinkGeneratora będą miały charakter bezwzględny.
<a n:href="Presenter:action">Odkaz</a>
Wysyłanie wiadomości e-mail
Mailer to klasa służąca do wysyłania wiadomości e-mail. Implementuje on interfejs Nette\Mail\Mailer, a także istnieje kilka gotowych mailerów, które przedstawimy.
Framework automatycznie dodaje usługę taką jak Nette\Mail\Mailer
zbudowaną na podstawie konfiguracji do kontenera DI, i do której możesz uzyskać dostęp, mając ją przekazaną do ciebie
za pomocą zastrzyku 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 = '-fMuj@email.cz'
.
SmtpMailer
Aby wysłać pocztę przez serwer SMTP, należy użyć SmtpMailer
.
$mailer = new Nette\Mail\SmtpMailer(
host: 'smtp.gmail.com',
username: 'franta@gmail.com',
password: '*****',
encryption: 'ssl',
);
$mailer->send($mail);
Do konstruktora można przekazać następujące dodatkowe parametry:
port
– jeśli nie jest ustawiony, to domyślnie 25 lub 465 jest używany dlassl
timeout
– timeout dla połączenia SMTPpersistent
– użyj trwałego połączeniaclientHost
– ustawienie nagłówka Host ClientstreamOptions
– pozwala na ustawienie opcji kontekstu SSL dla połączenia
FallbackMailer
Nie wysyła maili bezpośrednio, ale pośredniczy w wysyłce poprzez zestaw mailerów. Jeśli jeden mailer się nie powiedzie, ponawia próbę następnego. Jeśli ostatni się nie powiedzie, zaczyna się od pierwszego.
$mailer = new Nette\Mail\FallbackMailer([
$smtpMailer,
$backupSmtpMailer,
$sendmailMailer,
]);
$mailer->send($mail);
Jako dodatkowe parametry w konstruktorze możemy podać liczbę retries oraz czas oczekiwania w milisekundach.
DKIM
DKIM (DomainKeys Identified Mail) to technologia zwiększania wiarygodności e-maili, która pomaga również w wykrywaniu fałszywych wiadomości. Wysłana wiadomość jest podpisywana kluczem prywatnym domeny nadawcy, a podpis ten jest przechowywany w nagłówku wiadomości e-mail. Serwer odbiorcy dopasowuje ten podpis do klucza publicznego przechowywanego w rekordach DNS domeny. Dzięki dopasowaniu podpisu udowadnia się, że e-mail rzeczywiście pochodzi z domeny nadawcy i że wiadomość nie została zmodyfikowana podczas transmisji.
Możesz skonfigurować podpisywanie wiadomości e-mail bezpośrednio w konfiguracji mailera. Jeśli nie używasz wtrysku zależności, jest on używany 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; // nebo SmtpMailer
$mailer->setSigner($signer);
$mailer->send($mail);
Konfiguracja
Przegląd opcji konfiguracyjnych dla Nette Mail. Jeśli nie używasz całego frameworka, a jedynie tej biblioteki, przeczytaj jak załadować konfigurację.
Domyślnie do wysyłania e-maili używany jest mailer Nette\Mail\SendmailMailer
, który nie jest dalej
konfigurowany. Możemy jednak przełączyć ją na Nette\Mail\SmtpMailer
:
mail:
# use 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 jest $_SERVER['HTTP_HOST']
persistent: ... # (bool) domyślnie jest false
# kontekst do połączenia z serwerem SMTP, domyślnie jest to stream_context_get_default()
context:
ssl: # przegląd opcji na stronie https://www.php.net/manual/en/context.ssl.php
allow_self_signed: ...
...
http: # podsumowanie wyborów na stronie https://www.php.net/manual/en/context.http.php
header: ...
...
Za pomocą opcji context › ssl › verify_peer: false
możemy wyłączyć uwierzytelnianie certyfikatu SSL.
Silnie radzimy, aby tego nie robić, ponieważ spowoduje to, że aplikacja będzie podatna na uszkodzenia. Zamiast tego dodaj certyfikaty do repozytorium.
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
Usługi te są dodawane do kontenera DI:
Nazwa | Typ | Opis |
---|---|---|
mail.mailer |
Nette\Mail\Mailer | klasa wysyłania wiadomości e-mail |
mail.signer |
Nette\Mail\Signer | Podpisywanie DKIM |