Статьи

Использование и расширение Drupal 8 Mail API: Часть 1

В этой серии из двух частей мы рассмотрим Mail API в Drupal 8. При этом мы рассмотрим два основных аспекта: как использовать его программно для отправки электронных писем и как расширить его для использования внешнего сервиса, такого как Mandrill. ,

Чтобы продемонстрировать это, в первой части мы создадим пользовательский шаблон электронной почты, который будет использоваться для отправки электронных сообщений текущему пользователю, когда он / она сохранит новый узел Article. Кроме того, мы увидим, как другие могут изменить этот шаблон , чтобы обеспечить HTML-рендеринг тела письма вместо обычного текста по умолчанию.

Во второй части мы рассмотрим расширение почтовой системы и интеграцию внешнего API для доставки электронной почты. Для этого мы будем использовать Mandrill и его библиотеку PHP, которая обеспечивает хорошую основу для взаимодействия с ее API.

Всю работу, которую мы проходим, можно найти в этом Git-репозитории как часть пользовательского модуля Drupal 8, который мы начнем писать здесь. Так что не стесняйтесь проверить это, если хотите следовать. Давайте начнем.

Первым условием этого модуля является его файл .info :

d8mail.info.yml :

1
2
3
4
name: Drupal 8 Mailer
description: ‘Demonstrates the use of the Mail API in Drupal 8.’
core: 8.x
type: module

Теперь мы можем включить модуль на нашем сайте, если захотим.

Есть два основных шага, необходимых для программной отправки электронной почты с помощью Drupal 8. Сначала нам нужно реализовать hook_mail () , чтобы определить один или несколько шаблонов электронной почты. Второй шаг — использование почтового менеджера для отправки писем с использованием одного из этих шаблонов .

Хотя hook_mail() называется hook_mail() это не типичная ловушка, а скорее обычная функция, которая обычно вызывается только тем же модулем, который ее реализует. Другими словами, когда вы отправляете электронное письмо программно, вам нужно указать имя модуля, реализующего hook_mail() и идентификатор шаблона, который вы хотите использовать, и это определяется этим хуком. Но мы увидим это через минуту. Во-первых, как мы это реализуем?

d8mail.module :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
/**
 * Implements hook_mail().
 */
function d8mail_mail($key, &$message, $params) {
  $options = array(
    ‘langcode’ => $message[‘langcode’],
  );
 
  switch ($key) {
    case ‘node_insert’:
      $message[‘from’] = \Drupal::config(‘system.site’)->get(‘mail’);
      $message[‘subject’] = t(‘Node created: @title’, array(‘@title’ => $params[‘node_title’]), $options);
      $message[‘body’][] = SafeMarkup::checkPlain($params[‘message’]);
      break;
  }
}

Это очень простая реализация, которая определяет один шаблон, идентифицируемый как node_insert ( $key ). Два других аргумента функции:

  • $message : передано по ссылке, внутри которого мы добавляем столько шаблонов о нашей электронной почте, сколько нам нужно
  • $params : массив дополнительных данных, которые нужно отправить в электронном письме и которые передаются из почтового менеджера, когда мы пытаемся отправить электронное письмо

Как видите, мы создаем массив $message со значениями, которые мы хотим, чтобы это письмо включало во все вызовы. Мы устанавливаем значение по умолчанию from значения, полученного из системы конфигурации и представляющего основной адрес электронной почты сайта. Мы устанавливаем шаблонную subject электронной почты, которая позволяет получателю знать, что был создан новый узел, за которым следует имя узла (которое будет передано через массив $params ). Тема также переводится на язык, который передается от абонента.

Наконец, мы пропускаем body сообщения через строку sanitiser, потому что текст может содержать HTML, и он может быть усечен, если мы не закодируем элементы HTML. И поскольку мы используем класс SafeMarkup , нам нужно использовать его вверху:

1
use Drupal\Component\Utility\SafeMarkup;

Кроме того, тело сообщения представляет собой массив, который позже будет вставлен в строку. И, очевидно, есть много других параметров, которые мы можем установить, например, заголовки, но этого будет достаточно для этого примера.

И это все для реализации hook_mail() . Теперь давайте обратимся к коду, который запускается каждый раз, когда создается новый узел, hook_entity_insert () :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
 * Implements hook_entity_insert().
 */
function d8mail_entity_insert(Drupal\Core\Entity\EntityInterface $entity) {
 
  if ($entity->getEntityTypeId() !== ‘node’ || ($entity->getEntityTypeId() === ‘node’ && $entity->bundle() !== ‘article’)) {
    return;
  }
 
  $mailManager = \Drupal::service(‘plugin.manager.mail’);
 
  $module = ‘d8mail’;
  $key = ‘node_insert’;
  $to = \Drupal::currentUser()->getEmail();
  $params[‘message’] = $entity->get(‘body’)->value;
  $params[‘node_title’] = $entity->label();
  $langcode = \Drupal::currentUser()->getPreferredLangcode();
  $send = true;
 
  $result = $mailManager->mail($module, $key, $to, $langcode, $params, NULL, $send);
  if ($result[‘result’] !== true) {
    $message = t(‘There was a problem sending your email notification to @email for creating node @id.’, array(‘@email’ => $to, ‘@id’ => $entity->id()));
    drupal_set_message($message, ‘error’);
    \Drupal::logger(‘d8mail’)->error($message);
    return;
  }
 
  $message = t(‘An email notification has been sent to @email for creating node @id.’, array(‘@email’ => $to, ‘@id’ => $entity->id()));
  drupal_set_message($message);
  \Drupal::logger(‘d8mail’)->notice($message);
}

Этот хук срабатывает после каждого сохранения узла, и все, что нам нужно сделать, это убедиться, что мы нацеливаемся на правильный узел и включаем нашу логику.

После проверки, что сущность узла относится к типу article , мы загружаем службу почтового менеджера Drupal и начинаем устанавливать некоторые значения для электронной почты. Нам нужна следующая информация:

  • имя модуля, которое реализует hook_mail() и определяет наш шаблон (что я упоминал выше)
  • идентификатор шаблона ( $key )
  • адрес электронной почты получателя (найденный в текущей учетной записи пользователя)
  • язык ( $langcode ), который входит в массив $params и который будет использоваться для перевода сообщения темы
  • заголовок узла, который будет добавлен к теме письма
  • тело письма, которое в нашем случае будет значением поля тела узла
  • логическое значение, указывающее, должно ли электронное письмо действительно отправляться

Затем мы передаем все эти значения методу mail() почтового менеджера . Последний отвечает за hook_mail() электронной почты (одним из аспектов является вызов правильной реализации hook_mail() ) и, наконец, делегирование фактической доставки ответственному плагину. По умолчанию это будет PHPMail , который использует функцию mail() по умолчанию, которая поставляется с PHP.

Если почтовый менеджер успешно отправил электронное письмо (фактическая доставка не принимается во внимание, а скорее успешное действие PHP), метод mail() вернет массив, содержащий ключ result с любым почтовым плагином, который возвращает. Проверяя это значение, мы можем узнать, было ли действие по электронной почте успешным, и сообщить пользователю, что мы уведомили его об их действии. В противном случае мы печатаем и регистрируем сообщение об ошибке.

И это все. Очистка кэша и создание узла статьи должно привести к тому, что электронное письмо попадет в ваш почтовый ящик. Если вы ничего не получаете, и на экране нет признаков ошибок, обязательно проверьте журналы сервера и почтовую очередь, чтобы убедиться, что электронные письма отправляются.

Прежде чем двигаться дальше, я хотел бы сделать небольшое замечание относительно этой реализации ловушек. В этом примере я разместил всю логику внутри него напрямую. Кроме того, я использовал ранний возврат сверху, что по сути означает, что никакая другая логика не может быть добавлена, кроме той, которая характерна для узлов статьи. В реальных приложениях я рекомендую реорганизовать логику рассылки в отдельную функцию или класс и отложить ее до этого. Более того, вы не должны использовать ранние возвраты внутри реализации ловушек, а вместо этого вызывать другие функции, если выполняются условия.

Как только все это будет сделано , у нас будет еще один инструмент, который позволит нам изменить такую ​​существующую установку: hook_mail_alter () . Этот хук вызывается из почтового менеджера до того, как ответственный почтовый плагин отправит письмо. Цель состоит в том, чтобы позволить другим модулям выполнить окончательные изменения существующей электронной почты, отправляемой.

Хотя это может использоваться и другими модулями, мы проиллюстрируем пример реализации из того же модуля, с которым мы работали. Для этого мы изменим письмо, изменив один из его заголовков по умолчанию, чтобы преобразовать его из обычного текста в HTML. И вот как мы можем сделать это:

01
02
03
04
05
06
07
08
09
10
/**
 * Implements hook_mail_alter().
 */
function d8mail_mail_alter(&$message) {
  switch ($message[‘key’]) {
    case ‘node_insert’:
      $message[‘headers’][‘Content-Type’] = ‘text/html;
      break;
  }
}

Как видите, это простое изменение заголовка Content-Type который преобразует электронную почту в HTML. Таким образом, текстовые HTML-сущности будут анализироваться почтовыми клиентами как HTML. И используя случай переключения, мы гарантируем, что это происходит только для шаблона электронной почты, который мы определили ранее.

Здесь следует заметить, что хук alter hook_mail() после соответствующей реализации hook_mail() . Поэтому после этого единственная обработка, которая происходит с электронной почтой, выполняется внутри метода format() почтового плагина (обеспечивается его интерфейсом).

И это почти все, что нужно для программной отправки электронной почты с использованием Drupal 8. Мы видели шаги, необходимые для программной настройки шаблонов электронной почты, которые гидрируются почтовым менеджером, когда мы этого хотим. Мы также упомянули плагин доставки почты по умолчанию, который используется для отправки электронной почты в Drupal 8. И, наконец, мы увидели, как другие модули теперь могут изменять нашу электронную почту, добавляя новые заголовки, изменяя тему, объединяя значения в теле письма. , и т.д.

В следующей статье мы рассмотрим замену плагина PHPMail по умолчанию на нашу собственную реализацию. Мы настроим почтовую программу, которая использует Mandrill с помощью своей библиотеки PHP. Цель состоит в том, чтобы позволить нашему собственному модулю использовать этот почтовик, в то время как остальная часть приложения продолжает использовать PHPMailer по умолчанию.