Más con Symfony

13.5. Enviando emails

El envío de emails es uno de los usos más comunes de las tareas. Hasta Symfony 1.3 el envío de emails no era tan sencillo como debía ser. Afortunadamente la situación ha cambiado y ahora Symfony está completamente integrado con Swift Mailer, una librería muy completa para el envío de emails.

El objeto mailer está disponible en las tareas de Symfony mediante el método sfCommandApplicationTask::getMailer(). Por tanto, acceder al mailer y enviar emails es tan sencillo como se muestra en el siguiente ejemplo:

public function execute($arguments = array(), $options = array())
{
  $mailer = $this->getMailer();
  $mailer->composeAndSend($remitente, $destinatario, $asunto, $contenido);
}

Nota Como la configuración del mailer se obtiene a partir de la configuración de la aplicación, para utilizar el mailer es obligatorio que la tarea utilice una opción llamada application.

Nota Si utilizas la estrategia de envío spool, los emails sólo se envían cuando se ejecuta la tarea project:send-emails.

Normalmente el contenido del email no se encuentra en una variable mágica llamada $contenido esperando a que lo envíes, sino que debes generarlo de alguna forma antes de enviarlo. En Symfony no existe una forma estándar de generar el contenido de los emails, pero puedes seguir los consejos mostrados en las próximas secciones para facilitar tu trabajo.

13.5.1. Delegar la generación del contenido

Se puede crear en la tarea un método protegido que devuelva el contenido del email que se va a enviar:

public function execute($arguments = array(), $options = array())
{
  $this->getMailer()->composeAndsend($remitente, $destinatario, $asunto, $this->getContenido());
}

protected function getContenido()
{
  return 'Hola Mundo';
}

13.5.2. Utilizar el plugin decorator del Swift Mailer

Swift Mailer incluye un plugin llamado Decorator que básicamente es un sistema de plantillas muy simple pero eficiente. Este plugin recibe los datos que dependen del destinatario y los sustituye en el contenido del email preparado.

Puedes leer la documentación de Swift Mailer para obtener más información.

13.5.3. Utilizar un sistema de plantillas externo

Integrar una librería externa de plantillas es muy sencillo. Se puede utilizar por ejemplo el nuevo componente de plantillas que forma parte del proyecto Symfony Components. Descarga el código del componente, copialo por ejemplo en el directorio lib/vendor/templating/ y utiliza el siguiente código en la plantilla:

protected function getContenido($template, $vars = array())
{
  $engine = $this->getTemplateEngine();
  return $engine->render($template, $vars);
}

protected function getTemplateEngine()
{
  if (is_null($this->templateEngine))
  {
    $loader = new sfTemplateLoaderFilesystem(sfConfig::get('sf_app_dir').'/templates/emails/%s.php');
    $this->templateEngine = new sfTemplateEngine($loader);
  }

  return $this->templateEngine;
}

13.5.4. Combinando lo mejor de cada uno

Todavía existe otra forma de hacerlo. El plugin Decorator de Swift Mailer es genial porque se encarga de realizar las sustituciones que dependen del destinatario del mensaje. Esto significa que en el contenido del mensaje se definen los elementos que dependen del destinatario y Swift Mailer se encarga de reemplazar los tokens con el valor correcto en función del destinatario del email que se envía. El siguiente código muestra cómo integrarlo con el componente de las plantillas:

public function execute($arguments = array(), $options = array())
{
  $message = Swift_Message::newInstance();

  // obtiene la lista de usuarios
  foreach($users as $user)
  {
    $replacements[$user->getEmail()] = array(
      '{username}'      => $user->getEmail(),
      '{specific_data}' => $user->getSomeUserSpecificData(),
    );

    $message->addTo($user->getEmail());
  }

  $this->registerDecorator($replacements);

  $message
    ->setSubject('User specific data for {username}!')
    ->setBody($this->getMessageBody('user_specific_data'));

  $this->getMailer()->send($message);
}

protected function registerDecorator($replacements)
{
  $this->getMailer()->registerPlugin(new Swift_Plugins_DecoratorPlugin($replacements));
}

protected function getMessageBody($template, $vars = array())
{
  $engine = $this->getTemplateEngine();
  return $engine->render($template, $vars);
}

protected function getTemplateEngine($replacements = array())
{
  if (is_null($this->templateEngine))
  {
    $loader = new sfTemplateLoaderFilesystem(sfConfig::get('sf_app_template_dir').'/emails/%s.php');
    $this->templateEngine = new sfTemplateEngine($loader);
  }

  return $this->templateEngine;
}

El archivo apps/frontend/templates/emails/user_specific_data.php contiene el siguiente código:

Hi {username}!

We just wanted to let you know your specific data:

{specific_data}

¡Y eso es todo! Ahora ya dispones un completo sistema de plantillas para crear el contenido de tus emails.