Отправка электронных писем
Собираетесь ли вы отправлять электронные письма, например, информационные бюллетени или подтверждения заказов? Фреймворк Nette предоставляет необходимые инструменты с очень удобным API. Мы покажем:
- как создать электронное письмо, включая вложения
- как отправить
- как объединить электронные письма и шаблоны
Установка
Загрузите и установите пакет с помощью Composer:
composer require nette/mail
Создание электронных писем
Email – это объект Nette\Mail\Message:
$mail = new Nette\Mail\Message;
$mail->setFrom('John <john@example.com>')
->addTo('peter@example.com')
->addTo('jack@example.com')
->setSubject('Подтверждение заказа')
->setBody("Здравствуйте. Ваш заказ принят.");
Все параметры должны быть закодированы в UTF-8.
Помимо указания получателей с помощью метода addTo()
, вы также
можете указать получателя копии с помощью addCc()
, или получателя
скрытой копии с помощью addBcc()
. Все эти методы, включая
setFrom()
, принимают адресата тремя способами:
$mail->setFrom('john.doe@example.com');
$mail->setFrom('john.doe@example.com', 'John Doe');
$mail->setFrom('John Doe <john.doe@example.com>');
Тело письма, написанное в формате HTML, передается с помощью метода
setHtmlBody()
:
$mail->setHtmlBody('<p>Hello,</p><p>Ваш заказ принят.</p>');
Вам не нужно создавать текстовый вариант письма, Nette сгенерирует его
автоматически за вас. А если у письма нет темы, она будет взята из
элемента <title>
.
Изображения также можно очень легко вставить в HTML-тело письма. Просто передайте путь, где физически находятся изображения, в качестве второго параметра, и Nette автоматически включит их в письмо:
// автоматически добавляет /path/to/images/background.gif к письму
$mail->setHtmlBody(
'<b>Привет</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('John <john@example.com>')
->addTo('jack@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
Если вы используете электронную почту вместе с Nette Application, т. е.
презентерами, вы можете захотеть создать ссылки в шаблонах, используя
атрибут n:href
или тег {link}
. Latte в принципе их не знает, но их
очень легко добавить. Созданием ссылок может заниматься объект
Nette\Application\LinkGenerator
, который вы получите, передав его с помощью внедрения зависимостей.
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">Link</a>
Отправка электронных писем
Mailer – это класс, отвечающий за отправку электронных писем. Он реализует интерфейс Nette\Mail\Mailer и предлагает несколько готовых почтовых программ, которые мы представим.
Фреймворк автоматически добавляет сервис Nette\Mail\Mailer
на основе
configuration в контейнер DI, который вы получаете, передавая
его с помощью внедрения
зависимостей.
SendmailMailer
По умолчанию используется SendmailMailer, который использует функцию PHP mail. Пример использования:
$mailer = new Nette\Mail\SendmailMailer;
$mailer->send($mail);
Если вы хотите установить returnPath
, но сервер всё равно
перезаписывает его, используйте $mailer->commandArgs = '-fmy@email.com'
.
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
– назначение клиентаstreamOptions
– позволяет установить опции контекста SSL для соединения
FallbackMailer
Он не отправляет письма по электронной почте, а рассылает их через набор рассылок. Если одна рассылка не удалась, она повторяет попытку на следующей. Если последний из них не работает, то всё начинается заново с первого.
$mailer = new Nette\Mail\FallbackMailer([
$smtpMailer,
$backupSmtpMailer,
$sendmailMailer,
]);
$mailer->send($mail);
Другие параметры в конструкторе включают число повторов и время ожидания в милисекундах.
DKIM
DKIM (DomainKeys Identified Mail) – это технология надежной электронной почты, которая также помогает обнаружить поддельные сообщения. Отправленное сообщение подписывается закрытым ключом домена отправителя, и эта подпись сохраняется в заголовке электронной почты. Сервер получателя сравнивает эту подпись с открытым ключом, хранящимся в DNS-записях домена. Сверяя подпись, можно доказать, что электронное письмо действительно пришло из домена отправителя и что сообщение не было изменено во время его передачи.
Вы можете настроить mailer для подписи электронной почты в конфигурации. Если вы не используете внедрение зависимостей, она задается следующим образом:
$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
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: ...
...
Вы можете отключить проверку подлинности SSL-сертификата с помощью
опции context › ssl › verify_peer: false
. Настоятельно рекомендуется не
делать этого, так как это сделает приложение уязвимым. Вместо этого,
добавьте сертификаты в хранилище
доверия.
Чтобы повысить доверие, мы можем подписывать электронные письма с помощью технологии 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-подписание |