Отправка электронной почты (email)
В JohnCMS для отправки электронной почты используется symfony/mailer. Способ отправки скрыт за общим интерфейсом, поэтому вы можете выбрать наиболее подходящий вашему хостингу транспорт, не меняя код: письма ставятся в очередь одинаково в любом случае.
Транспорты и настройка
Настройки почты указываются в конфигурационном файле config/autoload/mail.global.php. Не редактируйте этот файл — создайте рядом mail.local.php и переопределите в нём нужные значения; подробнее — в разделе Конфигурационные файлы.
Строка подключения (DSN)
Основной способ настройки — параметр dsn. Это родной формат symfony/mailer, поэтому доступны все поддерживаемые им транспорты:
<?php
declare(strict_types=1);
return [
'mail' => [
'dsn' => 'smtps://mail@example.com:password@smtp.example.com:465',
],
];Основные варианты:
smtp://user:pass@smtp.example.com:587
SMTP, шифрование STARTTLS согласуется, если сервер его предлагает
smtps://user:pass@smtp.example.com:465
SMTP, шифрование с первого байта (порт 465)
sendmail://default
отправка через программу sendmail на сервере
native://default
настройки из php.ini
null://null
письма никуда не уходят, удобно для разработки
Полезные параметры SMTP: ?verify_peer=0 — не проверять сертификат (самоподписанный сертификат на своём сервере), ?local_domain=example.com — если сервер требует определённое имя в HELO.
Провайдеры со своим API (Mailgun, Postmark, Amazon SES, Brevo и другие) подключаются установкой соответствующего пакета-моста symfony и указываются его строкой DSN. Несколько транспортов можно объединить: failover:// переключается на следующий, когда транспорт недоступен, roundrobin:// распределяет письма между всеми.
Настройка отдельными параметрами
Если dsn не задан, строка подключения собирается из параметров transport и options — так настраивались сайты до появления dsn, и этот способ продолжает работать:
Значения transport: smtp, sendmail, native, null.
Параметры транспорта smtp: host, port, username, password, encryption, verify_peer, local_domain. Если username и password не заданы, подключение выполняется без авторизации.
Параметр encryption — это ssl (шифрование с первого байта, порт 465), tls (STARTTLS) или пустая строка (без шифрования).
У транспорта sendmail есть единственный параметр command — команда запуска. Если он не задан, используется sendmail_path из php.ini.
Настройка через админку
Основные настройки почты можно менять и без редактирования файлов — в админке, раздел Система → Настройки почты (/admin/settings/mail). Страница доступна тем, кому разрешено менять настройки сайта, и записывает те же значения в mail.local.php.
Там же есть отправка тестового сообщения: письмо уходит немедленно, минуя очередь, поэтому ответ почтового сервера — включая текст ошибки, если что-то не так, — виден сразу на той же странице. Настройки перед проверкой нужно сохранить: они читаются при сборке контейнера, то есть вступают в силу со следующего запроса.
Подпись DKIM и поведение очереди в админке не редактируются: их задают один раз в файле конфигурации.
Перенаправление всей почты
Копия сайта для разработки обычно работает с базой рабочего сайта, поэтому первая же проверка регистрации напишет реальному посетителю. Чтобы этого не случилось, укажите адрес, на который уйдут все письма:
Можно указать и несколько адресов списком. Настоящие получатели сохраняются в заголовке X-Original-To, так что по перенаправленному письму видно, кому оно предназначалось. Перенаправляется не только заголовок, но и SMTP-конверт — то, куда письмо доставляется на самом деле. На рабочем сайте параметр должен быть пустым.
Подпись DKIM
Подпись DKIM доказывает принимающему серверу, что письмо действительно отправлено с вашего домена — без неё письма заметно чаще попадают в спам. Настраивается в секции dkim:
Пока любой из трёх параметров пуст, письма отправляются без подписи. Если ключ указан, но прочитать его не удалось, письма всё равно отправляются — без подписи, а причина записывается в лог.
Отправка сообщений
Отправка email достаточно затратная операция. Для решения этой проблемы отправку email можно переложить на сервер. Для этого в JohnCMS реализована очередь сообщений. Чтобы отправить письмо, необходимо просто добавить его в очередь.
Письмо ставится в очередь через MailQueueInterface — внедрите его в свой use case или сервис:
Что делает этот код? Он добавляет запись в таблицу email_messages. А дальше система проверяет наличие не отправленных писем в очереди и отправляет их.
Поля QueuedEmailDTO
template - шаблон, по которому формируется тело письма. Путь Twig, например
@theme/emails/registration.twig. Как устроены шаблоны писем — в разделе Шаблоны электронных сообщений. (обязательное)locale - код языка, на котором будет отправлено письмо. Это язык получателя, а не того, кто вызвал отправку. (обязательное)
recipient - E-mail адрес получателя. (обязательное)
recipientName - Имя получателя, которое будет отображаться в почтовом клиенте.
subject - Тема сообщения. Не обязательна, но рекомендуется.
priority - Приоритет отправки. Чем меньше, тем выше; по умолчанию 100.
variables - Массив значений, доступных в шаблоне письма.
replyTo, replyToName - Адрес и имя для ответа, если отвечать нужно не на адрес сайта. Например, в уведомлении из формы обратной связи это адрес написавшего посетителя.
cc, bcc - Массивы адресов для копии и скрытой копии.
Адреса проверяются сразу при постановке в очередь: если адрес такой, что почтовый сервер его не примет, push() выбрасывает InvalidEmailAddressException и письмо в очередь не попадает. Это происходит там, где ошибка допущена, а не через минуту в кроне. Если адрес приходит не из проверенной формы, а, например, из настроек сайта, — перехватите исключение и запишите его в лог, как это сделано в модуле обратной связи.
Письмо отправляется сразу в двух версиях — HTML и текстовой, — это заметно влияет на то, попадёт ли оно в спам. Текстовая версия берётся из шаблона с расширением .txt.twig, а если его нет, получается из HTML автоматически. Подробности — в разделе Шаблоны электронных сообщений.
Очередь разбирает планировщик задач: команда mail:send-pending запускается им раз в минуту и отправляет письма пачками. Отправки «на хитах» больше нет — если cron-задача планировщика не настроена, письма так и останутся в очереди.
Повторные попытки и неудачи
Письмо, которое не удалось отправить, остаётся в очереди и отправляется повторно. Различаются два вида неудач:
временная — почтовый сервер недоступен или отклонил соединение. Письмо остаётся в очереди, и следующая попытка выполняется с задержкой. Когда попытки заканчиваются, письмо помечается как неотправленное, а причина сохраняется в колонке
last_error.окончательная — письмо невозможно собрать в принципе: не указан получатель, адрес не соответствует стандарту, шаблон не рендерится. Такое письмо не отправляется повторно, потому что результат будет тот же; оно сразу помечается как неотправленное с указанием причины.
Ни в одном из случаев письмо не помечается отправленным — таблица очереди остаётся честной записью того, что дошло до получателя, а что нет.
Поведение очереди настраивается в секции queue файла mail.local.php:
Одновременный запуск нескольких обработчиков безопасен: пачка писем сначала закрепляется за конкретным процессом и только потом отправляется, поэтому одно и то же письмо не уйдёт дважды.
Команда mail:cleanup (планировщик запускает её раз в сутки) удаляет доставленные письма старше keep_sent_days. Письма, которые доставить не удалось, автоматически не удаляются никогда — это записи о том, что требует внимания.
Обновление с версий без повторных попыток
Повторные попытки опираются на колонки таблицы email_messages, которых нет на сайтах, установленных раньше. Их добавляет обычное обновление базы данных:
То же самое доступно в админке в разделе задач обслуживания — «Update the database». Новые установки получают нужные колонки сразу. Подробности — в разделе Миграции базы данных.
Настройка отправки Email
Добавьте задачу в cron:
Периодичность выполнения установить раз в 1 минуту. Обратите внимание, что может потребоваться указать полный путь к файлу от корня. Посмотреть его можно в phpinfo(), параметр DOCUMENT_ROOT или вывести так: echo $_SERVER['DOCUMENT_ROOT']; Более подробно про то как добавить задачу, вы можете уточнить у вашего хостинг провайдера.
Если вы обновляетесь со старых версий, обратите внимание на изменения:
было:
php system/cron.phpстало:
php system/bin/console schedule:run --no-interaction
Константа USE_CRON в config/constants.php удалена — отправка выполняется только планировщиком, переключать больше нечего.
Подробнее про работу планировщика: Планировщик задач (schedule)
Последнее обновление
Это было полезно?