Verwenden und Erweitern der Drupal 8-Mail-API Teil 2

Im vorigen Artikel haben wir uns angesehen, wie wir programmgesteuert E-Mails in Drupal 8 versenden können. Außerdem haben wir gesehen, wie andere Module diese ausgehenden Mails verändern können. Heute werden wir untersuchen, wie wir die Mail-API verwenden können, um dieses Standardverhalten zu erweitern. Der Zweck besteht darin, einen externen Dienst als Mittel zur E-Mail-Zustellung zu verwenden. 

Zu diesem Zweck verwenden wir Mandrill, obwohl der Fokus des Artikels nicht auf der API oder dem Umgang damit liegt, sondern auf der Drupal-Seite. Denken Sie daran, dass sich das Arbeitsmodul in diesem Git-Repository befindet.

Wie wir im vorherigen Artikel gesehen haben, wird beim Senden einer E-Mail in Drupal 8 der Mail-Manager angefordert, indem einige Parameter an den E-Mail-Manager übergeben werden mail () Methode und Einrichten a Vorlage in einem hook_mail () Implementierung. Was der Mail-Manager intern tut, ist das Laden des entsprechenden Mail-Plugins, das Erstellen der E-Mail und das Delegieren an das mail () Methode des Plugins, das geladen wurde.

Aber an wen delegiert er eigentlich??

Plugin-Auswahl

Bevor Sie unser eigenes Plugin schreiben, ist es wichtig, dass Sie den Mail-Manager für das Laden von Plugins auswählen. Mit anderen Worten: Woher wissen wir, welches Plugin geladen wird und wie können wir es selbst laden?

Das system.mail.interface Das Konfigurationsarray enthält alle Antworten. Es enthält die IDs der verfügbaren Plugins, die sich nach dem Kontext richten, in dem sie verwendet werden. Standardmäßig haben wir nur diese Konfiguration in dieser Konfiguration default => phpmail. Dies bedeutet, dass das Plugin die ID hat phpmail (die PHPMail-Klasse) wird als Fallback für alle Kontexte verwendet, die nicht anders angegeben sind, d. h. der Standardwert.

Wenn Sie unser eigenes Plugin schreiben möchten, müssen Sie diesem Array ein weiteres Element hinzufügen, dessen Wert die Plugin-ID ist. Der Schlüssel für diesen Wert kann eines von zwei Dingen sein: Der Maschinenname unseres Moduls (zum Laden des Plugins, wenn unser Modul E-Mails sendet) oder eine Kombination aus Modulname und E-Mail Vorlage Schlüssel (um das Plugin zu laden, wenn unser Modul eine E-Mail mit diesem spezifischen Schlüssel sendet). 

Ein Beispiel für das letztere Konstrukt ist d8mail_node_insert, woher d8mail ist unser Modulname, den wir im vorigen Artikel gebaut haben, und node_insert ist die E-Mail Vorlage Schlüssel, den wir definiert haben.

Nun, da wir wissen, wie die Auswahl des Mail-Plugins geschieht, müssen wir sicherstellen, dass dieses Konfigurations-Array die erforderlichen Informationen enthält, damit die E-Mails mit unserem gesendet werden d8mail Verwenden Sie das neue Plugin, das wir erstellen werden. Wir können dies in einer hook_install () - Implementierung tun, die nur einmal ausgelöst wird, wenn das Modul installiert wird:

d8mail.install:

/ ** * Implementiert hook_install (). * / function d8mail_install () $ config = \ Drupal :: configFactory () -> getEditable ('system.mail'); $ mail_plugins = $ config-> get ('interface'); if (in_array ('d8mail', array_keys ($ mail_plugins))) return;  $ mail_plugins ['d8mail'] = 'mandrill_mail'; $ config-> set ('interface', $ mail_plugins) -> save ();  

Nicht super kompliziert was oben passiert. Wir laden das bearbeitbare Konfigurationsobjekt, das das darstellt system.mail Konfiguration und fügen Sie ein neues Element hinzu Schnittstelle Array: d8mail => mandrill_mail. Wir werden in Kürze ein Mail-Plugin mit der ID von erstellen mandrill_mail die für alle E-Mails verwendet wird, die vom gesendet werden d8mail Modul. Und das ist es.

Bevor wir jedoch fortfahren, müssen wir sicherstellen, dass diese Änderung rückgängig gemacht wird, wenn das Modul deinstalliert wird. Dazu können wir das counterpart hook_uninstall () verwenden, das aufgerufen wird, wenn ein Modul deinstalliert wird (in Drupal 8 gibt es keine weiteren Deaktivierungen)..

In derselben Datei:

/ ** * Implementiert hook_uninstall (). * / function d8mail_uninstall () $ config = \ Drupal :: configFactory () -> getEditable ('system.mail'); $ mail_plugins = $ config-> get ('interface'); if (! in_array ('d8mail', array_keys ($ mail_plugins))) return;  unset ($ mail_plugins ['d8mail'])); $ config-> set ('interface', $ mail_plugins) -> save ();  

Mit dem hook_uninstall () Implementierung machen wir das Gegenteil von vorher: Wir entfernen unsere Plugin-ID, wenn sie gesetzt ist.

Das Installations- / Deinstallationsszenario ist nur ein Weg. Sie können auch ein Verwaltungsformular erstellen, mit dem Benutzer das gewünschte Plugin und in welchem ​​Kontext auswählen können. Sie müssen jedoch immer noch sicherstellen, dass bei der Deaktivierung des Moduls, das ein bestimmtes Plugin definiert, die Konfiguration keinen Verweis mehr auf dieses Plugin enthält. Andernfalls versucht der Mail-Manager möglicherweise, eine nicht vorhandene Klasse zu verwenden, und alle möglichen Fehler werden ausgegeben.

Mandrill

Wie bereits erwähnt, arbeiten wir mit der Mandrill-API, um unsere Aufgabe zu veranschaulichen. Lassen Sie uns die PHP-Bibliothek von Mandrill laden und in unserer Umgebung verfügbar machen. Dafür müssen wir drei Schritte machen.

Erstens müssen wir die Bibliothek tatsächlich in Drupal installieren. Zum Zeitpunkt des Schreibens bedeutet dies im Wesentlichen das Hinzufügen von "Mandrill / Mandrill": "1.0. *" Abhängigkeit von der Wurzel composer.json Datei und läuft Komponist installieren. Beachten Sie jedoch, dass dadurch auch die Drupal-Installation aus dem Inneren des Systems gelöscht wird Ader/ Ordner und laden Sie stattdessen die neueste stabile Version herunter. Dann müssen Sie den Stamm bearbeiten index.php Datei und ändern Sie den Pfad zum Autoloader gemäß diesen Anweisungen. Ich hoffe, dass diese letzte Aktion nicht bald notwendig sein wird, und ich möchte Sie ermutigen, die Diskussionen rund um die Zukunft von Composer in Drupal 8 zur Verwaltung externer Bibliotheken zu verfolgen.

Zweitens benötigen wir einen API-Schlüssel von Mandrill. Glücklicherweise können wir dies auf ihren Verwaltungsseiten leicht generieren. Sobald wir das haben, können wir es in einer neuen Datei speichern, die auf unserem Server an einem der folgenden Orte erstellt wurde:

~ /. mandrill.key /etc/mandrill.key 

Wir können den Schlüssel auch als Konstruktorparameter an den main übergeben Mandrill Klasse, aber auf diese Weise müssen wir es nicht in unserem Code fest codieren. 

Drittens müssen wir einen Dienst erstellen, damit wir die Abhängigkeitseingabe verwenden können Mandrill in unser Plugin einbinden:

d8mail.services.yml:

Dienste: d8mail.mandrill: Klasse: Mandrill 

Je nachdem, wie Sie den geladen haben Mandrill Klasse in Ihre Anwendung, müssen Sie den Wert nach ändern Klasse. Mit der composer.json Annäherung reicht dies aus.

Das Mail Plugin

Es ist endlich Zeit, unser Plugin zu erstellen. In Drupal 8 gehen Plugin-Klassen in die src / Plugin Ordner unseres Moduls. Je nach Typ werden sie jedoch weiter unten in anderen Verzeichnissen abgelegt (in unserem Fall) Mail). Lassen Sie uns eine Klasse schreiben, die von der Mandrill API-Bibliothek abhängt, um E-Mails zu senden:

src / Plugin / Mail / MandrillMail.php:

Mandrill = $ Mandrill;  / ** * @inheritdoc * / public statische Funktion create (ContainerInterface $ container, Array $ configuration, $ plugin_id, $ plugin_definition) neues statisch zurückgeben ($ container-> get ('d8mail.mandrill'));  / ** * @heritdoc * / public -Funktionsformat (Array $ message) // Verknüpfe das body-Array in einen String. $ message ['body'] = implode ("\ n \ n", $ message ['body']); // Konvertiere ein beliebiges HTML in Klartext. $ message ['body'] = MailFormatHelper :: htmlToText ($ message ['body']); // Umhüllen Sie den E-Mail-Körper zum Senden. $ message ['body'] = MailFormatHelper :: wrapMail ($ message ['body']); $ Nachricht zurückgeben;  / ** * @heritdoc * / public function mail (Array $ message) try $ vars = ['html' => $ message ['body'], 'subject' => $ message ['subject' ], 'from_email' => $ message ['from'], 'bis' => array (array ('email' => $ message ['to'])),]; $ result = $ this-> mandrill-> messages-> send ($ vars); if ($ result [0] ['status']! == 'gesendet') return false;  return $ result;  catch (Mandrill_Error $ e) return false;  

Es gibt ein paar Dinge, die Sie beachten sollten, bevor Sie in die Klasse einsteigen.

Zuerst die Anmerkungen über der Klasse. Dies ist nur der am häufigsten verwendete Mechanismus zur Erkennung von Plugins für Drupal 8. The Ich würde Schlüssel stimmt mit dem Wert überein, den wir dem hinzugefügt haben system.mail.interface Konfigurationsarray zuvor, während der Rest grundlegende Definitionselemente für Plugins ist.

Zweitens die Umsetzung der ContainerFactoryPluginInterface Schnittstelle, über die wir die definieren erstellen() Methode. Letzteres ist Teil des Abhängigkeitseinspritzungsprozesses, mit dem wir den Mandrill-Service laden können, den wir in definiert haben services.yml Datei früher. Dies macht das Testen viel einfacher und wird als bewährte Methode betrachtet.

Wie bereits erwähnt, müssen die Mail-Plugins das implementieren MailInterface Schnittstelle, die die Existenz der erzwingt Format() und mail () Methoden. In unserem Fall macht das erste genau dasselbe wie das PHPMail plugin: etwas verarbeitung des nachrichtentextes. Sie können also hier Ihre eigene Logik hinzufügen, wenn Sie möchten. Die letztere Methode ist hingegen für das Versenden der E-Mail in unserem Fall über die Mandrill-API selbst verantwortlich.

Wie aus der Mandrill-Dokumentation hervorgeht, erstellen wir eine E-Mail-Nachricht im $ Vars Array mit Werten, die vom Mail-Manager über $ message Parameter. Diese werden bereits durchgefiltert hook_mail (), hook_mail_alter () und das eigene Plugin Format() Methode. Jetzt müssen Sie nur noch die E-Mail versenden. Ich werde nicht näher auf die Verwendung der Mandrill-API eingehen, da Sie in der Dokumentation alle Optionen nachlesen können, die Sie verwenden können.

Nach dem Senden der E-Mail und dem Zurückkehren von Mandrill a geschickt Im Status zurückgeben wir das gesamte Antwortarray, das weitere Informationen enthält. Dieses Array wird dann vom Mail-Manager zu seinem eigenen Return-Array mit der Bezeichnung als hinzugefügt Ergebnis. Wenn Mandrill ein Problem hat, die E-Mail ablehnt oder eine Ausnahme auslöst, kehren wir zurück falsch. Dadurch wird der Mail-Manager mit dieser Situation umgehen, indem er den Vorfall protokolliert und eine Statusmeldung druckt.

Und das ist so ziemlich alles. Wir können den Cache leeren und versuchen, einen anderen Artikelknoten zu erstellen. Diesmal sollte die Benachrichtigungs-E-Mail von Mandrill statt von PHP gesendet werden mail (). Mit diesem an Ort und Stelle jedoch die hook_mail_alter () Die Implementierung ist überflüssig geworden, da es keine Header gibt, die wir tatsächlich an Mandrill senden (und der Text bereits HTML ist). Und in dieser Hinsicht wird nicht viel von der Arbeit des Mail-Managers verwendet, da wir das nicht an Mandrill weitergeben. Dies soll jedoch nur veranschaulichen, wie Sie dies einrichten können. Die Details der Implementierung bleiben Ihnen und Ihren Bedürfnissen überlassen.

Fazit

Und da haben wir es. Wir haben ein eigenes Mail-Plugin implementiert, das von der verwendet werden soll d8modul Wir haben im vorigen Artikel angefangen. Aufgrund der Erweiterbarkeit von Drupal 8 war dies nicht einmal sehr aufwendig. 

Sie müssen nur noch die E-Mail-Versandlogik perfektionieren und an Ihre Umstände anpassen. Dies kann eine weitere Integration zwischen Mandrill und Ihrer Drupal-Instanz bedeuten, die Erstellung schöner Vorlagen oder was Sie haben. Eine wichtige verbleibende Aufgabe ist außerdem das Schreiben automatisierter Tests für diese Funktionalität. Und Drupal 8 bietet auch dafür das richtige Toolkit.