For the complete documentation index, see llms.txt. This page is also available as Markdown.

Отправка электронной почты (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',
    ],
];

Основные варианты:

DSN
Что означает

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)

Последнее обновление

Это было полезно?