Відправлення електронних листів
Ви збираєтеся надсилати електронні листи, наприклад, інформаційні бюлетені або підтвердження замовлень? Nette Framework надає необхідні інструменти з дуже зручним API. Ми покажемо вам:
- як створити електронний лист, включаючи вкладення
- як його надіслати
- як поєднати електронні листи та шаблони
Встановлення
Завантажте та встановіть бібліотеку за допомогою Composer:
composer require nette/mail
Створення електронного листа
Електронний лист є об'єктом класу Nette\Mail\Message. Створимо його, наприклад, так:
$mail = new Nette\Mail\Message;
$mail->setFrom('Franta <franta@example.com>')
->addTo('petr@example.com')
->addTo('jirka@example.com')
->setSubject('Підтвердження замовлення')
->setBody("Добрий день,\nваше замовлення було прийнято.");
Усі введені параметри мають бути в кодуванні UTF-8.
Окрім зазначення одержувача за допомогою методу addTo()
, можна
також вказати одержувача копії addCc()
або одержувача прихованої
копії addBcc()
. У всіх цих методах, включаючи setFrom()
, ми можемо
записати адресу трьома способами:
$mail->setFrom('franta@example.com');
$mail->setFrom('franta@example.com', 'Franta');
$mail->setFrom('Franta <franta@example.com>');
Тіло електронного листа, написане в HTML, передається за допомогою
методу setHtmlBody()
:
$mail->setHtmlBody('<p>Добрий день,</p><p>ваше замовлення було прийнято.</p>');
Текстову альтернативу створювати не потрібно, Nette згенерує її
автоматично за вас. А якщо електронний лист не має встановленої теми,
спробує взяти її з елемента <title>
.
До HTML-тіла також можна надзвичайно легко вставляти зображення. Достатньо передати шлях, де фізично знаходяться зображення, як другий параметр, і Nette автоматично включить їх до електронного листа:
// автоматично додасть /path/to/images/background.gif до електронного листа
$mail->setHtmlBody(
'<b>Hello</b> <img src="background.gif">',
'/path/to/images',
);
Алгоритм вставки зображень шукає такі шаблони: <img src=...>
,
<body background=...>
, url(...)
всередині HTML-атрибута style
та
спеціальний синтаксис [[...]]
.
Чи може надсилання електронних листів бути ще простішим?
Електронний лист — це щось на зразок листівки. Ніколи не надсилайте електронною поштою паролі чи інші дані доступу.
Вкладення
До електронного листа, звісно, можна вкладати файли. Для цього
служить метод addAttachment(string $file, ?string $content = null, ?string $contentType = null)
.
// вставить до електронного листа файл /path/to/example.zip під назвою example.zip
$mail->addAttachment('/path/to/example.zip');
// вставить до електронного листа файл /path/to/example.zip під назвою info.zip
$mail->addAttachment('info.zip', file_get_contents('/path/to/example.zip'));
// вставить до електронного листа файл example.txt з вмістом "Hello John!"
$mail->addAttachment('example.txt', 'Hello John!');
Шаблони
Якщо ви надсилаєте HTML-листи, дуже зручно писати їх у системі шаблонів Latte. Як це зробити?
$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',
);
Файл email.latte
:
<html>
<head>
<meta charset="utf-8">
<title>Підтвердження замовлення</title>
<style>
body {
background: url("background.png")
}
</style>
</head>
<body>
<p>Добрий день,</p>
<p>Ваше замовлення номер {$orderId} було прийнято.</p>
</body>
</html>
Nette автоматично вставить усі зображення, встановить тему відповідно
до елемента <title>
та згенерує текстову альтернативу до HTML.
Використання в Nette Application
Якщо ви використовуєте електронні листи разом з Nette Application, тобто з
презентерами, ви можете захотіти створювати посилання в шаблонах за
допомогою атрибута n:href
або тегу {link}
. Latte за замовчуванням
їх не знає, але їх дуже легко додати. Створювати посилання вміє об'єкт
Nette\Application\LinkGenerator
, до якого ви можете отримати доступ, передавши
його за допомогою dependency
injection:
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;
}
}
У шаблоні ми потім створюємо посилання так, як звикли. Усі посилання, створені через LinkGenerator, будуть абсолютними.
<a n:href="Presenter:action">Посилання</a>
Відправлення електронного листа
Mailer — це клас, який забезпечує відправлення електронних листів. Він реалізує інтерфейс Nette\Mail\Mailer, і доступно кілька готових мейлерів, які ми розглянемо.
Framework автоматично додає до DI-контейнера сервіс типу Nette\Mail\Mailer
,
зібраний на основі #конфігурації, до якого ви можете
отримати доступ, передавши його за допомогою dependency injection.
SendmailMailer
Мейлер за замовчуванням — це SendmailMailer, який використовує PHP-функцію mail. Приклад використання:
$mailer = new Nette\Mail\SendmailMailer;
$mailer->send($mail);
Якщо ви хочете встановити returnPath
, а сервер постійно його
перезаписує, використовуйте $mailer->commandArgs = '-fMuj@email.cz'
.
SmtpMailer
Для надсилання пошти через SMTP-сервер використовується
SmtpMailer
.
$mailer = new Nette\Mail\SmtpMailer(
host: 'smtp.gmail.com',
username: 'franta@gmail.com',
password: '*****',
encryption: 'ssl',
);
$mailer->send($mail);
Конструктору можна передати такі додаткові параметри:
port
– якщо не встановлено, використовується стандартний 25 або 465 дляssl
timeout
– таймаут для SMTP-з'єднанняpersistent
– використовувати постійне з'єднанняclientHost
– налаштування заголовка Host клієнтаstreamOptions
– дозволяє налаштувати SSL context options для з'єднання
FallbackMailer
Електронні листи безпосередньо не надсилає, але забезпечує надсилання через набір мейлерів. У випадку, якщо один мейлер зазнає невдачі, він повторює спробу з наступним. Якщо зазнає невдачі й останній, починає знову з першого.
$mailer = new Nette\Mail\FallbackMailer([
$smtpMailer,
$backupSmtpMailer,
$sendmailMailer,
]);
$mailer->send($mail);
Як додаткові параметри в конструкторі можна вказати кількість повторень та час очікування в мілісекундах.
DKIM
DKIM (DomainKeys Identified Mail) — це технологія для підвищення довіри до електронних листів, яка також допомагає виявляти підроблені повідомлення. Надіслане повідомлення підписується приватним ключем домену відправника, і цей підпис зберігається в заголовку електронного листа. Сервер одержувача порівнює цей підпис з публічним ключем, збереженим у DNS-записах домену. Якщо підпис відповідає, це доводить, що електронний лист дійсно надійшов з домену відправника і що під час передачі повідомлення не було змінено.
Підписування електронних листів можна налаштувати для мейлера безпосередньо в конфігурації. Якщо ви не використовуєте dependency injection, це робиться таким чином:
$signer = new Nette\Mail\DkimSigner(
domain: 'nette.org',
selector: 'dkim',
privateKey: file_get_contents('../dkim/dkim.key'),
passPhrase: '****',
);
$mailer = new Nette\Mail\SendmailMailer; // або SmtpMailer
$mailer->setSigner($signer);
$mailer->send($mail);
Конфігурація
Огляд параметрів конфігурації для Nette Mail. Якщо ви використовуєте не весь фреймворк, а лише цю бібліотеку, прочитайте, як завантажити конфігурацію.
Для надсилання електронних листів стандартно використовується
мейлер Nette\Mail\SendmailMailer
, який далі не конфігурується. Однак ми
можемо переключити його на Nette\Mail\SmtpMailer
:
mail:
# використовує SmtpMailer
smtp: true # (bool) за замовчуванням false
host: ... # (string)
port: ... # (int)
username: ... # (string)
password: ... # (string)
timeout: ... # (int)
encryption: ... # (ssl|tls|null) за замовчуванням null (має псевдонім 'secure')
clientHost: ... # (string) за замовчуванням $_SERVER['HTTP_HOST']
persistent: ... # (bool) за замовчуванням false
# контекст для підключення до SMTP-сервера, за замовчуванням stream_context_get_default()
context:
ssl: # огляд параметрів на https://www.php.net/manual/en/context.ssl.php
allow_self_signed: ...
...
http: # огляд параметрів на https://www.php.net/manual/en/context.http.php
header: ...
...
За допомогою опції context › ssl › verify_peer: false
можна вимкнути
перевірку SSL-сертифікатів. Наполегливо не рекомендуємо цього
робити, оскільки програма стане вразливою. Замість цього додайте сертифікати до сховища.
Для підвищення довіри ми можемо підписувати електронні листи за допомогою технології DKIM:
mail:
dkim:
domain: myweb.com
selector: lovenette
privateKey: %appDir%/cert/dkim.priv
passPhrase: ...
Сервіси DI
Ці сервіси додаються до DI-контейнера:
Назва | Тип | Опис |
---|---|---|
mail.mailer |
Nette\Mail\Mailer | клас, що надсилає електронні листи |
mail.signer |
Nette\Mail\Signer | DKIM підписування |