Más con Symfony

4.5. La estrategia de envío

La estrategia o mecanismo de envío es una de las características más útiles de la integración de Swift Mailer con symfony. La estrategia de envío permite indicar a symfony la forma en la que se envían los mensajes y se puede configurar mediante la opción delivery_strategy del archivo de configuración factories.yml. La estrategia modifica el comportamiento del método sfMailer::send(). Por defecto se dispone de cuatro estrategias diferentes, que cubren todas las necesidades habituales:

  • realtime: los mensajes se envían en tiempo real.
  • single_address: los mensajes se envían a la dirección de correo electrónico indicada.
  • spool: los mensajes se guardan en una cola de envío.
  • none: los mensajes no se envían y simplemente se ignoran.

4.5.1. La estrategia realtime

La estrategia realtime es la que se utiliza por defecto y la más sencilla de configurar porque no se debe hacer nada especial.

Los emails se envían mediante el transporte configurado en la sección transport del archivo de configuración factories.yml (la siguiente sección explica cómo configurar un transporte para email).

4.5.2. La estrategia single_address

Utilizando la estrategia single_address, todos los mensajes se envían a una dirección de correo electrónico configurada en la opción delivery_address.

Esta estrategia es muy útil en el entorno de desarrollo para no enviar los emails a los usuarios reales pero al mismo tiempo permitir que el programador pueda comprobar con su lector de correo el aspecto y contenido de los emails enviados.

Nota Si quieres comprobar las direcciones para, cc y bcc originales, están disponibles en las cabeceras X-Swift-To, X-Swift-Cc y X-Swift-Bcc respectivamente.

Los emails se envían mediante el mismo transporte que utiliza la estrategia realtime.

4.5.3. La estrategia spool

La estrategia spool hace que todos los mensajes se almacenen en una cola.

Esta es la mejor estrategia para el entorno de producción, ya que las peticiones web no tienen que esperar a que se envíen los emails.

La clase spool se configura mediante la opción spool_class. Symfony incluye por defecto tres clases de este tipo:

  • Swift_FileSpool: los mensajes se guardan en el sistema de archivos.
  • Swift_DoctrineSpool: los mensajes se guardan en un modelo de Doctrine.
  • Swift_PropelSpool: los mensajes se guardan en un modelo de Propel.

Cuando se instancia la clase, se pasa como argumento de su constructor la opción spool_arguments. A continuación se indican las opciones disponibles para los tipos de colas incluidos por defecto:

  • Swift_FileSpool:
    • La ruta absoluta del directorio de la cola (los mensajes se guardan en este directorio)
  • Swift_DoctrineSpool:
    • El modelo de Doctrine en el que se guardan los mensajes (por defecto es MailMessage)
    • El nombre de la columna utilizada para guardar el mensaje (por defecto es message)
    • El método que se invoca para obtener los mensajes a enviar (opcional). Como argumento de este método se le pasan las opciones de la cola.
  • Swift_PropelSpool:
    • El modelo de Propel en el que se guardan los mensajes (por defecto es MailMessage)
    • El nombre de la columna utilizada para guardar el mensaje (por defecto es message)
    • El método que se invoca para obtener los mensajes a enviar (opcional). Como argumento de este método se le pasan las opciones de la cola.

Seguidamente se muestra la configuración típica de una cola de Doctrine:

# Configuración del esquema en schema.yml
MailMessage:
 actAs: { Timestampable: ~ }
 columns:
   message: { type: clob, notnull: true }
# configuración en factories.yml
mailer:
  class: sfMailer
  param:
    delivery_strategy: spool
    spool_class:       Swift_DoctrineSpool
    spool_arguments:   [ MailMessage, message, getSpooledMessages ]

Y la misma configuración de antes para una cola de Propel:

# Configuración del esquema en schema.yml
mail_message:
  message:    { type: clob, required: true }
  created_at: ~
# configuración en factories.yml
dev:
  mailer:
    param:
      delivery_strategy: spool
      spool_class:       Swift_PropelSpool
      spool_arguments:   [ MailMessage, message, getSpooledMessages ]

Para enviar todos los mensajes almacenados en la cola, puedes emplear la tarea project:send-emails (esta tarea es completamente independiente del tipo de cola y de sus opciones):

$ php symfony project:send-emails

Nota La tarea project:send-emails requiere como argumentos el nombre de una aplicación y un entorno.

Cuando se utiliza la tarea project:send-emails, los mensajes se envían con el mismo transporte utilizado por la estrategia realtime.

Nota La tarea project:send-emails se puede ejecutar en cualquier máquina, no necesariamente en la misma en la que se creó el mensaje. Esto es así porque todo se guarda en el objeto del mensaje, incluso los archivos adjuntos.

Nota El funcionamiento interno de las colas es muy sencillo. Los emails se envían sin controlar los errores que se pueden producir, es decir, como si hubieran sido enviados con la estrategia realtime. Obviamente puedes extender las clases de las colas para incluir tu propia lógica de gestión de errores.

La tarea project:send-emails admite opcionalmente las siguientes dos opciones: * message-limit: limita el número de mensajes que se envían. * time-limit: limita (en segundos) el tiempo empleado en enviar los mensajes.

Las dos opciones también se pueden combinar:

$ php symfony project:send-emails --message-limit=10 --time-limit=20

El comando anterior deja de enviar mensajes cuando se envían 10 mensajes o cuando transcurren 20 segundos.

Aun cuando hagas uso de la estrategia spool, puede que tengas que enviar un mensaje de forma inmediata sin almacenarlo en la cola de mensajes. Para ello, puedes hacer uso de un método especial del mailer llamado sendNextImmediately():

$this->getMailer()->sendNextImmediately()->send($mensaje);

En el ejemplo anterior, el $mensaje no se guardará en la cola y se enviará inmediatamente. Como su propio nombre indica, el método sendNextImmediately() solamente afecta al siguiente mensaje que se envía.

Nota El método sendNextImmediately() no produce ningún efecto especial cuando la estrategia de envío no es spool.

4.5.4. La estrategia none

Esta estrategia es muy útil en el entorno de desarrollo para no enviar emails a ningún usuario real. Los mensajes están disponibles en la barra de depuración web (más adelante se explica la sección del mailer en la barra de depuración web).

También se trata de la mejor estrategia para el entorno de pruebas, donde el objeto sfTesterMailer permite la introspección de los mensajes sin tener que enviarlos realmente (como se explica más adelante en la sección de pruebas).