Uso y extensión de la API de correo de Drupal 8 Parte 2

En el artículo anterior vimos cómo podemos enviar correos electrónicos programáticamente en Drupal 8. También vimos cómo otros módulos pueden alterar estos correos salientes. Hoy vamos a ver cómo podemos usar la API de correo para extender este comportamiento predeterminado. El propósito es utilizar un servicio externo como medio para la entrega de correo electrónico.. 

Para esto, usaremos Mandrill, aunque el enfoque del artículo no será su API o cómo trabajar con él, sino el lado Drupal de las cosas. Y recuerda, el módulo de trabajo se puede encontrar en este repositorio Git..

Como hemos visto en el artículo anterior, el envío de un correo electrónico en Drupal 8 se realiza solicitando al administrador de correo, pasando algunos parámetros a su correo() método, y la creación de un modelo dentro de una hook_mail () implementación. Lo que el administrador de correo hace internamente es cargar el complemento de correo apropiado, construir el correo electrónico y luego delegarlo a la correo() método de cualquier plugin fue cargado.

Pero a quien realmente lo delegue?

Selección de plugin

Una cosa importante que hay que entender antes de escribir nuestro propio complemento es el proceso de selección del administrador de correo para cargar complementos. En otras palabras, ¿cómo sabemos qué complemento cargará y cómo podemos hacer que cargue nuestro propio complemento??

los system.mail.interface La matriz de configuración contiene todas las respuestas. Contiene los identificadores de los complementos disponibles, en función del contexto en el que se utilizan. Por defecto, todo lo que tenemos dentro de esta configuración es default => phpmail. Esto significa que el plugin con el id. phpmail (la clase PHPMail) se utiliza como alternativa para todos los contextos que no se especifican de otra manera, es decir, el valor predeterminado.

Si queremos escribir nuestro propio complemento, necesitamos agregar otro elemento a esa matriz con el ID del complemento como su valor. La clave para este valor puede ser una de dos cosas: el nombre de la máquina de nuestro módulo (para cargar el complemento cada vez que nuestro módulo envíe correos electrónicos) o una combinación de nombre de módulo y correo electrónico modelo clave (para cargar el complemento cada vez que nuestro módulo envíe un correo electrónico utilizando esa clave específica). 

Un ejemplo de este último constructo es d8mail_node_insert, dónde d8mail es el nombre de nuestro módulo que comenzamos a construir en el artículo anterior, y node_insert es el correo electrónico modelo clave que definimos.

Ahora que sabemos cómo se realiza la selección del complemento de correo, debemos asegurarnos de que esta matriz de configuración contenga la información necesaria para que los correos electrónicos se envíen con nuestra d8mail Módulo utiliza el nuevo plugin que vamos a construir. Podemos hacer esto dentro de una implementación hook_install () que se activa solo una vez cuando se instala el módulo:

d8mail.install:

/ ** * Implementa 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 ();  

No super complicado lo que pasa arriba. Cargamos el objeto de configuración editable que representa el system.mail configuración, y añadir un nuevo elemento a la interfaz formación: d8mail => mandrill_mail. Pronto crearemos un complemento de correo con el ID de mandrill_mail que se utilizará para todos los correos electrónicos enviados por el d8mail módulo. Y eso es.

Pero antes de continuar, debemos asegurarnos de que este cambio se revierta cuando se desinstala el módulo. Para esto, podemos usar la contraparte hook_uninstall () que se llama cuando un módulo se desinstala (no hay más módulos deshabilitados en Drupal 8).

Dentro del mismo archivo:

/ ** * Implementa 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 ();  

Con el hook_uninstall () En la implementación hacemos lo contrario de antes: eliminamos nuestro ID de complemento si está configurado.

El escenario de instalación / desinstalación es solo un camino por recorrer. También puede crear un formulario de administración que permita a los usuarios seleccionar el complemento que desean y en qué contexto. Pero aún debe asegurarse de que cuando deshabilita el módulo que define un complemento en particular, la configuración ya no mantendrá una referencia a ese complemento. De lo contrario, el administrador de correo puede intentar usar una clase inexistente y lanzar todo tipo de errores.

Mandril

Como mencioné anteriormente, trabajaremos con la API de Mandrill para ilustrar nuestra tarea. Así que vamos a cargar la biblioteca PHP de Mandrill y hacer que esté disponible en nuestro entorno. Hay tres pasos que tenemos que hacer para esto.

Primero, necesitamos obtener la biblioteca dentro de Drupal. Al momento de escribir esto, esto básicamente significa agregar el "mandril / mandril": "1.0. *" dependencia a la raíz compositor.json archivo y ejecución instalación del compositor. Sin embargo, tenga en cuenta que esto también borrará la instalación de Drupal desde el interior del núcleo/ carpeta y descargar la última versión estable en su lugar. Entonces, deberás editar la raíz index.php Archivo y cambie la ruta al autoloader de acuerdo con estas instrucciones. Esperamos que esta última acción no sea necesaria pronto, y lo invito a seguir las discusiones sobre el futuro de Composer en Drupal 8 para administrar bibliotecas externas.

Segundo, necesitamos obtener una clave API de Mandrill. Por suerte, esto lo podemos generar fácilmente desde sus páginas de administración. Una vez que tengamos eso, podemos almacenarlo dentro de un nuevo archivo creado en nuestro servidor, en cualquiera de las ubicaciones:

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

También podemos pasar la clave como parámetro constructor a la principal. Mandril clase, pero de esta manera no tendremos que codificarla en nuestro código. 

En tercer lugar, necesitamos crear un servicio para poder usar la inyección de dependencia para pasar el Mandril clase en nuestro plugin:

d8mail.services.yml:

servicios: d8mail.mandrill: clase: Mandril 

Dependiendo de cómo haya cargado el Mandril clase en su aplicación, tendrá que cambiar el valor después de clase. Utilizando el compositor.json enfoque, esto será suficiente.

El complemento de correo

Finalmente es hora de crear nuestro plugin. En Drupal 8, las clases de plugin van dentro del src / Plugin Carpeta de nuestro módulo. Sin embargo, dependiendo de su tipo, se colocan más abajo en otros directorios (en nuestro caso, Correo). Escribamos nuestra clase que dependerá de la biblioteca de la API de Mandrill para enviar correos electrónicos:

src / Plugin / Mail / MandrillMail.php:

mandril = $ mandril;  / ** * @inheritdoc * / public static function create (ContainerInterface $ container, array $ configuration, $ plugin_id, $ plugin_definition) return new static ($ container-> get ('d8mail.mandrill'));  / ** * @inheritdoc * / public function format (array $ message) // Unir la matriz del cuerpo en una cadena. $ message ['body'] = implode ("\ n \ n", $ message ['body']); // Convertir cualquier HTML a texto plano. $ message ['body'] = MailFormatHelper :: htmlToText ($ message ['body']); // Envolver el cuerpo del correo para enviar. $ message ['body'] = MailFormatHelper :: wrapMail ($ message ['body']); devuelve $ mensaje;  / ** * @inheritdoc * / public function mail (array $ message) try $ vars = ['html' => $ message ['body'], 'subject' => $ message ['subject' ], 'from_email' => $ message ['from'], 'to' => array (array ('email' => $ message ['to'])),]; $ result = $ this-> mandrill-> messages-> send ($ vars); if ($ resultado [0] ['estado']! == 'enviado') devolver falso;  devolver $ resultado;  catch (Mandrill_Error $ e) return false;  

Hay un par de cosas a tener en cuenta antes de entrar en lo que hace la clase.

Primero, las anotaciones por encima de la clase. Este es solo el mecanismo de descubrimiento de complementos más común para Drupal 8. El carné de identidad clave coincide con el valor que agregamos a la system.mail.interface la matriz de configuración anterior, mientras que el resto son elementos básicos de definición de complementos.

Segundo, la implementación del ContainerFactoryPluginInterface interfaz por la que definimos la crear() método. Este último es parte del proceso de inyección de dependencia mediante el cual podemos cargar el servicio Mandrill que definimos en el servicios.yml archivo anterior. Esto facilita mucho las pruebas y se considera la mejor práctica.

Como mencioné, los complementos de correo necesitan implementar el MailInterface interfaz que hace cumplir la existencia de la formato() y correo() metodos En nuestro caso, el primero hace exactamente lo mismo que el PHPMail plugin: un poco de procesamiento del cuerpo del mensaje. Así que puedes agregar tu propia lógica aquí si quieres. El último método, por otro lado, es responsable de enviar el correo, en nuestro caso, utilizando la API de Mandrill..

Como lo indica la documentación de Mandrill, construimos un mensaje de correo electrónico dentro de $ vars matriz utilizando valores pasados ​​desde el administrador de correo a través de la $ mensaje parámetro. Estos ya serán filtrados a través de hook_mail (), hook_mail_alter () y el propio plugin formato() método. Todo lo que queda es enviar realmente el correo electrónico. No entraré en detalles sobre el uso de la API de Mandrill, ya que puede consultar la documentación de todas las opciones que puede usar..

Después de enviar el correo electrónico y volver de Mandrill a expedido estado, devolvemos la matriz de respuestas completa, que contiene más información. El administrador de correo agrega esta matriz a su propia matriz de retorno con la clave resultado. Si Mandrill tiene un problema, rechaza el correo electrónico o lanza una excepción, devolvemos falso. Esto hará que el administrador de correo maneje esta situación al registrar el incidente e imprimir un mensaje de estado.

Y eso es prácticamente todo. Podemos borrar el caché e intentar crear otro nodo de artículo. Esta vez, el correo electrónico de notificación debe ser enviado por Mandrill en lugar de PHP correo(). Con esto en su lugar, sin embargo, el hook_mail_alter () la implementación se ha vuelto superflua, ya que no hay encabezados que enviemos a Mandrill (y el texto ya es HTML). Y para el caso, una gran parte del trabajo del administrador de correo no se utiliza, ya que no se lo estamos pasando a Mandrill. Pero esto solo tiene la intención de ilustrar el proceso de cómo se puede hacer para configurar esto. Los detalles de la implementación dependen de usted y de sus necesidades..

Conclusión

Y ahí lo tenemos. Hemos implementado nuestro propio plugin de correo para ser utilizado por el d8module Empezamos en el artículo anterior. Y debido a la naturaleza extensible de Drupal 8, ni siquiera tomó mucho esfuerzo. 

Lo que queda por hacer es perfeccionar la lógica de envío de correo y adaptarla a sus circunstancias. Esto puede significar una mayor integración entre Mandrill y su instancia de Drupal, creando plantillas agradables o lo que sea. Además, una tarea importante que queda es escribir pruebas automatizadas para esta funcionalidad. Y Drupal 8 ofrece todo el conjunto de herramientas para eso también..