Ver índice de contenidos del libro

4.11. Recetas

4.11.1. Enviando emails mediante Gmail

Si no dispones de un servidor SMTP pero tienes una cuenta de correo electrónico de Gmail, utiliza la siguiente configuración para enviar los mensajes a través de los servidores de Google:

transport:
  class: Swift_SmtpTransport
  param:
    host:       smtp.gmail.com
    port:       465
    encryption: ssl
    username:   tu_nombre_de_usuario_de_gmail
    password:   tu_contrasena_de_gmail

Sustituye el valor de las opciones username y password por tus credenciales de Gmail y ya puedes empezar a enviar emails.

4.11.2. Personalizando el objeto mailer

Si necesitas una configuración mayor que la proporcionada por el archivo de configuración factories.yml, puedes utilizar el evento mailer.configure para personalizar todavía más el objeto mailer.

Puedes conectar tu aplicación con este evento directamente en la clase ProjectConfiguration, tal y como se muestra a continuación:

class ProjectConfiguration extends sfProjectConfiguration
{
  public function setup()
  {
    // ...
 
    $this->dispatcher->connect(
      'mailer.configure',
      array($this, 'configurarMailer')
    );
  }
 
  public function configurarMailer(sfEvent $event)
  {
    $mailer = $event->getSubject();
 
    // hacer algo con el objeto mailer
  }
}

La siguiente sección muestra un caso práctico de esta técnica.

4.11.3. Utilizando los plugins de Swift Mailer

Los plugins de Swift Mailer plugins requieren el uso del evento mailer.configure explicado en la sección anterior:

public function configurarMailer(sfEvent $event)
{
  $mailer = $event->getSubject();
 
  $plugin = new Swift_Plugins_ThrottlerPlugin(
    100, Swift_Plugins_ThrottlerPlugin::MESSAGES_PER_MINUTE
  );
 
  $mailer->registerPlugin($plugin);
}

Nota La sección "Plugins" de la documentación oficial de Swift Mailer describe todas las características de los plugins incluidos en la librería.

4.11.4. Personalizando el comportamiento de la cola

El comportamiento por defecto de las colas es muy simple. Se seleccionan todos los emails de la cola de forma aleatoria y se envían.

Puedes configurar una cola para que se limite el tiempo (en segundos) dedicado al envío de los mensajes o para que se limite el número de mensajes a enviar:

$spool = $mailer->getSpool();
 
$spool->setMessageLimit(10);
$spool->setTimeLimit(10);

En esta sección se explica cómo crear un mecanismo de prioridad para la cola y se muestra todo lo necesario para desarrollar nuestra propia lógica.

En primer lugar se añade en el esquema una columna de prioridad:

# para Propel
mail_message:
  message:    { type: clob, required: true }
  created_at: ~
  priority:   { type: integer, default: 3 }
 
# para Doctrine
MailMessage:
  actAs: { Timestampable: ~ }
  columns:
    message:  { type: clob, notnull: true }
    priority: { type: integer }

Cuando se envía un email, se establece la cabecera de prioridad (siendo 1 la máxima prioridad):

$mensaje = $this->getMailer()
  ->compose('[email protected]', '[email protected]', 'Asunto', 'Cuerpo')
  ->setPriority(1)
;
$this->getMailer()->send($mensaje);

A continuación, redefine el método setMessage() por defecto para modificar la prioridad del propio objeto MailMessage:

// para Propel
class MailMessage extends BaseMailMessage
{
  public function setMessage($mensaje)
  {
    $msg = unserialize($mensaje);
    $this->setPriority($msg->getPriority());
 
    return parent::setMessage($mensaje);
  }
}
 
// para Doctrine
class MailMessage extends BaseMailMessage
{
  public function setMessage($mensaje)
  {
    $msg = unserialize($mensaje);
    $this->priority = $msg->getPriority();
 
    return $this->_set('message', $mensaje);
  }
}

Ten en cuenta que la cola serializa los mensajes, así que es necesario deserializar el mensaje antes de obtener su prioridad. A continuación es necesario crear un método que ordene los mensajes por prioridad:

// para Propel
class MailMessagePeer extends BaseMailMessagePeer
{
  static public function getSpooledMessages(Criteria $criteria)
  {
    $criteria->addAscendingOrderByColumn(self::PRIORITY);
 
    return self::doSelect($criteria);
  }
 
  // ...
}
 
// para Doctrine
class MailMessageTable extends Doctrine_Table
{
  public function getSpooledMessages()
  {
    return $this->createQuery('m')
      ->orderBy('m.priority')
    ;
  }
 
  // ...
}

El último paso consiste en definir en el archivo de configuración factories.yml el método que se invoca para obtener los mensajes de la cola:

spool_arguments: [ MailMessage, message, getSpooledMessages ]

Y eso es todo lo que hay que hacer. Ahora, cuando ejecutes la tarea project:send-emails, los mensajes se enviarán de acuerdo a su prioridad.