在這兩個部分的系列中,我們將探索 Drupal 8 中的郵件 API。在此過程中,我們將涵蓋兩個主要方面:如何以程式設計方式使用它來發送電子郵件以及如何擴展它以使用外部像山魈一樣的服務。
為了示範這一點,在第一部分中,我們將建立一個自訂電子郵件模板,用於在目前使用者儲存新的文章節點時向他/她發送電子郵件。此外,我們將了解其他人如何更改該模板,以便允許 HTML 呈現電子郵件正文而不是預設的純文字。
在第二部分中,我們將研究擴展郵件系統並整合外部 API 以進行電子郵件傳送。為此,我們將使用 Mandrill 及其 PHP 函式庫,它為與其 API 互動提供了良好的基礎。
我們完成的所有工作都可以在這個 Git 儲存庫中找到,作為我們將在這裡開始編寫的自訂 Drupal 8 模組的一部分。因此,如果您想繼續了解,請隨時查看。讓我們開始吧。
該模組的第一個先決條件是它的 .info
檔案:
d8mail.info.yml:
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()
的模組名稱以及您想要使用且由該掛鉤定義的範本 id。但我們很快就會看到這一點。首先,我們如何實現它?
d8mail.module:
/** * 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
,因為文字可能包含 HTML,如果我們不對 HTML 元素進行編碼,它可能會被截斷。由於我們使用的是 SafeMarkup
類,因此我們需要在頂部使用它:
use Drupal\Component\Utility\SafeMarkup;
此外,訊息正文是一個數組,稍後將內爆為字串。顯然我們還可以設定許多其他參數,例如標頭,但這對於本範例來說就足夠了。
這就是 hook_mail()
實作的全部內容。現在讓我們看看每次建立新節點時都會執行的程式碼,hook_entity_insert():
/** * 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
)$params
数组并用于翻译主题消息的语言 ($langcode
)然后我们将所有这些值传递给邮件管理器的 mail()
方法。后者负责构建电子邮件(调用正确的 hook_mail()
实现是其中的一方面)并最终将实际交付委托给负责的插件。默认情况下,这将是 PHPMail,它使用 PHP 自带的默认 mail()
函数。
如果邮件管理器成功发送电子邮件(不考虑实际发送,而是考虑成功的 PHP 操作),则 mail()
方法将返回一个包含 result
键的数组,其中包含以下内容:邮件插件返回。通过检查该值,我们可以了解电子邮件操作是否成功,并通知用户我们已通知他们他们的操作。否则,我们将打印并记录一条错误消息。
就是这样。清除缓存并创建文章节点应该会在您的收件箱中收到一封电子邮件。如果您没有收到任何信息,并且屏幕上没有错误迹象,请务必检查服务器日志和邮件队列,以验证电子邮件是否已发出。
在继续之前,我想快速说明一下这个钩子的实现。在这个例子中,我直接将所有逻辑放在其中。此外,我在顶部使用了早期返回,这本质上意味着除了特定于文章节点的逻辑之外,不能添加其他逻辑。在实际应用程序中,我建议将邮件逻辑重构为单独的函数或类,并遵循该逻辑。此外,您不应在钩子实现中使用提前返回,而应在满足条件时调用其他函数。
一旦所有这些都到位,我们就可以使用另一个工具来更改现有的设置:hook_mail_alter()。在负责的邮件插件发送电子邮件之前,从邮件管理器内部调用此挂钩。目的是允许其他模块对正在发送的现有电子邮件进行最终更改。
虽然其他模块也可以使用它,但我们将在我们一直使用的同一模块中说明示例实现。为此,我们将通过更改其默认标头之一来更改电子邮件,以便将其从纯文本转换为 HTML。我们可以这样做:
/** * Implements hook_mail_alter(). */ function d8mail_mail_alter(&$message) { switch ($message['key']) { case 'node_insert': $message['headers']['Content-Type'] = 'text/html; charset=UTF-8; format=flowed; delsp=yes'; break; } }
如您所见,这是对 Content-Type
标头的简单更改,可将电子邮件转换为 HTML。这样纯文本 HTML 实体将被邮件客户端解析为 HTML。使用 switch case,我们确保这只发生在我们之前定义的电子邮件模板中。
这里需要注意的一件事是,在相关的 hook_mail()
实现之后调用 alter hook。因此,在此之后,对电子邮件进行的唯一处理是在邮件插件的 format()
方法内完成的(由其接口强制执行)。
这几乎就是使用 Drupal 8 以编程方式发送电子邮件的全部内容。我们已经了解了以编程方式设置电子邮件模板所需的步骤,只要我们需要,这些模板就会由邮件管理器进行水合。我们还提到了 Drupal 8 中用于发送电子邮件的默认邮件传递插件。最后,我们看到了其他模块现在如何通过添加新标头、更改主题、将值连接到邮件正文来更改我们的电子邮件等
在下一篇文章中,我们将考虑用我们自己的自定义实现替换默认的 PHPMail 插件。我们将在 PHP 库的帮助下设置一个使用 Mandrill 的邮件程序。目标是允许我们自己的模块使用此邮件程序,而应用程序的其余部分继续使用默认的 PHPMailer。
以上是擴充 Drupal 8 Mail API 的功能:第 1 部分的詳細內容。更多資訊請關注PHP中文網其他相關文章!