В этой статье я расскажу о том, как улучшить стандартный модуль для контактных форм Contact. Это позволит без применения кода, немного управлять поведением Contact, добавить возможность сохранения отправленных писем, а также позволит отправлять письма в формате HTML.
Изначально я хотел просто разобраться с модулем Contact, написать как править формат писем которые он отправляет, я конечно же полез в ядро, и там особо не разгуляться. HTML письма отправлять нельзя, без дополнительного альтера, максимум текст подправить, поэтому я решил влезть в тему поглубже и нашел куда более мощное решение. Но если вам хочется все делать руками и через код, то в поможет вам hook_mail_alter()
и функция, которая отвечает за подготовку писем модуля Contact - contact_mail(). В общем все как и в D7. Вы также можете получать значения кастомных полей вот так: $contactMessage = $message['params']['contact_message'];
и $contactMessage->get('field_name')->getString();
А я расскажу о более комплексном подходе, потому что, как мне кажется, он будет более востребован и необходим. Я начал изучать как дела обстоят в 8-ке, и если в Drupal 7 для отправки HTML писем, как правило, используется Mime Mail, то в Drupal 8 ситуация совершенно иная. Тут все рекомендуют использовать Swift Mailer - как оказалось, это небольшая библиотека для PHP чтобы отправлять письма от SensioLabs, тех что создали Symfony и Twig, которые активно используются в Drupal 8. Так что даже логично, юзать либу из одной экосистемы, и к этим ребятам есть доверие. Соответственно модуль лишь обвязка для библиотеки которое позволит использовать все её возможности, но об этом попозже.
Улучшение модуля Contact ¶
Contact Storage - невероятно полезный модуль если вы собираетесь использовать Contact из ядра. Я вообще не понимаю, как так получилось что такого функционала не оказалась в ядре вместе с самим Contact. Он настолько очевидный и необходимый, при этом это по сути функционал Entifyform. Раз уже сделали его аналог в ядре, почему бы сразу не допилили до ума. Данный модуль раскрывает Contact полноценно как формы-сущности, побуду немного гадалкой и сказу что его потом и внедрят в ядро. Причем на его странице прямо и написано, что цель - попасть в ядро. Что же добавляет данный модуль:
- Позволяет отправлять письма в формате HMTL.
- Хранение всех отправленных сообщений на сайте. Это очень круто! Ведь никакой сбой или проблемы с почтой не потеряют письмо, он продублируется и на сайте. Разумеется с возможностью редактировать и удалять их.
- Возможность указать свой путь для редиректа после успешной отправки формы.
- Также позволяет указать свой алиас пути для страницы отправки формы, чтобы не пользать на страницу управления алиасами.
- Позволяет одной галочкой отключать кнопку Preview.
- Позволяет ограничить количество отправлений через форму для пользователей.
- Добавляет возможность клонировать формы.
Установка необходимых модулей ¶
А теперь вернемся непосредственно к письмам. Для дальнейшей работы нам понадобятся следующие модули Mail System, Swift Mailer и Contact Storage. Обращаю внимание сразу на то, что Swift Mailer нужно (!) ставить через composer иначе он просто не будет работать.
composer require drupal/swiftmailer:~1.0
Настройка Swift Mailer ¶
Давайте сразу настроим Swift Mailer /admin/config/swiftmailer/transport
. На данной странице вам нужно выбрать как будет отправляться почта и данные для отправки. Аналогично модулю SMTP.
Вверху переключившись на вкладку Messages, вы также можете настроить в каком формате будут уходить письма.
Настройка модуля Mail System ¶
Модуль 1 в 1 как в Drupal 7 перекочевал и на Drupal 8. Всё что он делает, позволяет выбирать, какие интерфейсы будут использоваться для форматирования и отправки письма, с возможностью указывать тонкие настройки под конкретные модули и задачи. Разумеется нам по дефолту нужно выбрать Swift Mailer, так как он будет отсылать и формировать письма.
Настройка модуля Contact ¶
Для начала нам нужно включить поддержку html писем для Contact в настройках добавленные модулем Contact Storage (/admin/structure/contact/settings
). Тут никаких сложностей не должно возникнуть.
А вот далее нам надо добавить формат вывода mail для сущности Contact Message. Он используется для формирования письма, если присутствует, конечно. Эта особенность захардкожена в самом модуле Contact (contact_mail()
).
Для этого заходим в настройки View Modes (/admin/structure/display-modes/view) и для Contact message добавлем
Теперь нужно перейти в настройки управления отображением для нужной контактной формы и включить формат вывода Mail.
После чего у вас сверху появится вкладка Mail и там вы сможете настроить то, как сообщение будет отправлено на почту, включая порядок и какие поля необходимо отправлять. Для формирования разметки вы также можете использовать здесь DisplaySuite + FieldGroup. Но и не забывайте что HTML писем достаточно большое количество ограничений, поэтому все же лучше взять контроль над результатом письма при помощи темплейт файла.
Следовательно, вы можете здесь настраивать как и что будет формировать тело письма. Вы можете использовать различные layouts и темплейты для того чтобы сформировать содержимое письма. Но что если вы хотите сделать общий каркас оформления отправляемых писем от модуля Contact? Тут нам и поможет Siwft Mailer. Он добавляет свой собственный шаблон swiftmailer.html.twig со следующим содержанием по умолчанию:
<html>
<head>
<style type="text/css">
table tr td {
font-family: Arial;
font-size: 12px;
}
</style>
</head>
<body>
<div>
<table width="800px" cellpadding="0" cellspacing="0">
<tr>
<td>
<div style="padding: 0px 0px 0px 0px;">
{{ body }}
</div>
</td>
</tr>
</table>
</div>
</body>
</html>
Как вы могли понять, всё что вы настроите на вывод в управлении отображением Mail будет вставлено в body переменную данного темплейта.
Так вот, как же менять эту обертку под себя? Данный модуль регистрирует them hook suggestions для данного темплейт файла в следующем формате swiftmailer-MODULE-KEY.html.twig
. Следовательно, вы можете объявить следующие темплейты:
- swiftmailer.html.twig - будет использоваться для всех отправляемых писем с сайта через Swift Mailer класс, если не определен ни один из шаблонов ниже.
- swiftmailer--contact.html.twig - будет использоваться для всех сообщений отправляемых модулем contact.
- swiftmailer--contact--page-mail.html.twig - будет использоваться для сообщений, отправленных из формы получателям данной контактной формы.
У Contact также есть следующие ключи:
- page-copy - копия письма отправляемая отправителю в случае если поставлена соответствующая галочка.
- page-autoreply - письмо которое отправляется в качестве автоматического ответа отправителю после отправки его письма.
- user-mail - письмо отправляемое через персональную контактную форму получателю (пользователю).
- user-copy - копия письма отправителю, отправленное через персональную контактную форму.
Я решил что хочу переопределить вообще все исходящие contact письма и сделать им единый стиль оформления. Для этого в теме вашего сайта находится папа templates, в неё мы и помещаем нужный нам темплейт swiftmailer--contact.html.twig
<html>
<head>
<style type="text/css">
table tr td {
font-family: Arial;
font-size: 14px;
}
</style>
</head>
<body style="background-color: #222222;">
<div style="width: 100%; padding: 20px 0; background-color: #222222;">
<div style="max-width: 600px; margin: auto;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0"
align="center" width="100%" style="max-width: 600px;">
<tbody>
<tr>
<td>
<img src="image:http://i.imgur.com/AZQIFhO.png" width="600" height="235"
alt="alt_text" border="0" align="center"
style="width: 100%; max-width: 600px;">
</td>
</tr>
</tbody>
</table>
<table role="presentation" cellspacing="0" cellpadding="0" border="0"
align="center" width="100%" style="max-width: 600px;">
<tbody>
<tr>
<td style="background: white; padding: 30px">
{{ body }}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>
В целом это всё. Дальше лишь ваша фантазия и необходимость правки макета письма.
Обращу лишь внимание на ещё одну особенность. Изображение я вставил не просто так, посмотрите на путь до него: src="image:http://i.imgur.com/AZQIFhO.png"
- приставка image перед адресом до изображения не просто так, она указывает Swift Mailer, что это изображение должно быть вставлено в письмо и отправлено вместе с ним через CID (Content-ID), при этом такой файл не отображается как прикрепленный. Это некий аналог data:base64.
С таким подходом, например, Gmail не запрашивает разрешение на подгрузку изображений из внешних источников, прежде чем отобразить их, а сразу показывает.
Комментарии
Отличная статья! А возможно ли вывести каждое поле отдельно? что-то вроде {{ body.field_name }} (так увы не работает)
Думаю можно. Ваш пример не работает потому что body поле самое по себе, а ваша структура пытается вызвать поле field_name у поля body? Это странно. Body же не сущность.
Я точно не могу сейчас сказать, надо препроцессить и смотреть, но опираясь на {{ body }} смею предположить что поле вызывается {{ field_name }}
Здравствуйте, я отправляю письма с помощью hook_mail, а не swiftmailer. Подскажите как мне написать темплейт для этих писем? Знаю, что нужно использовать hook_theme, но что в нем писать, и что делать после этого не знаю.
Грацио, Никита! Оч полезно.