Ayer, agregamos un servicio de solo lectura a Jobeet. Los Afiliados pueden ahora crear una cuenta pero esta necesita ser activada por el administrador antes de poder usarla. Para que el afiliado consiga su token, aún necesitaremos implementar la notificación por email. Eso es lo que haremos el dia de hoy.
El framework Symfony viene con una de las mejores soluciones PHP de correo: Swift Mailer. Por supuesto, la librería esta completamente integrada con Symfony, con algunas características interesantes agregadas por encima de las caracteríticas predeterminadas.
note
Symfony 1.3/1.4 usa Swift Mailer versión 4.1.
Envíando Emails simples
Vamos a empezar enviando un simple email para notificar al afiliado cuando su cuenta ha sido confirmada y darle el token.
Reemplace la acción activate
con el siguiente código:
// apps/backend/modules/affiliate/actions/actions.class.php class affiliateActions extends autoAffiliateActions { public function executeListActivate() { $affiliate = $this->getRoute()->getObject(); $affiliate->activate(); // send an email to the affiliate $message = $this->getMailer()->compose( array('jobeet@example.com' => 'Jobeet Bot'), $affiliate->getEmail(), 'Jobeet affiliate token', <<<EOF Your Jobeet affiliate account has been activated. Your token is {$affiliate->getToken()}. The Jobeet Bot. EOF ); $this->getMailer()->send($message); $this->redirect('jobeet_affiliate'); } // ... }
note
Para que el código funcione debidamente, deberas cambiar jobeet@example.com
por una dirección de email real.
La gestión del Email en Symfony es centrada alrededor de un objeto mailer, el cual
es obtenido desde la acción con un método getMailer()
.
El método compose()
toma cuatro argumentos y devuelve un objeto de mensaje de email:
- el remitente (
from
); - destinatario(s) (
to
); - el asunto del mensaje;
- el cuerpo del mensaje;
El enviar el mensaje es entonces tan simple como llamar al método send()
desde la instancia mailer y pasarle el mensaje como un argumento. Como un atajo, puedes
solo escribir y enviar un email en un método usando composeAndSend()
.
tip
El mensaje es una instnacia de la clase Swift_Message
. Visita la
documentación oficial Swift Mailer para
aprender mas acerca de este objeto, y como hacer cosas mas avanzadas como
adjuntar archivos.
Configuración
Por defecto, el método send()
intenta usar el servidor local SMTP para el
envio del mensaje al destinatario. Por supuesto, como muchas cosas en Symfony,
esto es totalmente configurable.
Factorias
Durante los días anteriores, hemos hablado acerca de los objetos del núcleo symfony
como user
, request
, response
, o routing
. Esos objetos son
automaticamente creados, configurados, y gestionados por el framework. Ellos
son siempre accesibles desde el objeto sfContext
, y como muchas cosas del
framework, ellas son configurables via un archivo de configuración:
factories.yml
. Este archivo es configurable por entorno.
Cuando sfContext
inicializa las factorias del núcleo, este lee al archivo
factories.yml
por los nombres de clases (class
) y los parámetros
(param
) a pasar al constructor:
response: class: sfWebResponse param: send_http_headers: false
En código anterior, para crear un response factory, symfony instancia un objeto
sfWebResponse
y pasa la opción send_http_headers
como un parámetro.
Delivery Strategy
Como otros muchos objetos del núcleo, el mailer es un factory. Por eso, este es
configurado en el archivo de configuración factories.yml
. La configuració por defecto
se lee asi:
mailer: class: sfMailer param: logging: %SF_LOGGING_ENABLED% charset: %SF_CHARSET% delivery_strategy: realtime transport: class: Swift_SmtpTransport param: host: localhost port: 25 encryption: ~ username: ~ password: ~
Cuando se crea una nueva aplicación, el archivo de configuración factories.yml
sobreescribe la configuración predeterminada con algunos sensibles valores para
los entornos env
y test
:
test: mailer: param: delivery_strategy: none dev: mailer: param: delivery_strategy: none
La configuración delivery_strategy
le dice a Symfony como entregar correos. Por
defecto, Symfony viene con cuatro diferentes estrategias:
realtime
: Los Mensajes son entregados en tiempo real.single_address
: Los Mensajes son entregados a una solo dirección.spool
: Los Mensajes son guardados en cola.none
: Los Mensajes son simplemente ignorados.
No importa cual sea la estrategia, los emails son siempre registrados en el log y estan disponibles en el panel "mailer" del web debug toolbar.
Mail Transport
Los mensajes de correo son siempre enviados por un transport. El transport es configurado
en el archivo de configuración factories.yml
, y la configuración por defecto usa el servidor
SMTP del equipo local:
transport: class: Swift_SmtpTransport param: host: localhost port: 25 encryption: ~ username: ~ password: ~
Swift Mailer viene con tres clases transport diferentes:
Swift_SmtpTransport
: Usa un servidor SMTP para enviar los mensajes.Swift_SendmailTransport
: Usasendmail
para enviar los mensajes.Swift_MailTransport
: Usa la función nativa de PHPmail()
fpara enviar los mensajes.
tip
La sección "Transport Types" de la documentación oficial Swift Mailer describe todo lo que necesitas saber acerca de las clases transport y sus diferentes parámetros.
Probando Emails
Ahora qe vimos como enviar un email con symfony mailer, vamos a escribir
algunas pruebas funcionales para asegurarnos que lo hicimos bien. Por defecto,
symfony registras un tester mailer
(sfMailerTester
) para facilitar la prueba.
First, change the mailer
factory's configuration for the test
environment if your web server does not have a local SMTP server. We have to replace the current Swift_SmtpTransport
class by Swift_MailTransport
:
# apps/backend/config/factories.yml test: # ... mailer: param: delivery_strategy: none transport: class: Swift_MailTransport
Then, add a new test/fixtures/administrators.yml
file containing the following YAML definition:
sfGuardUser: admin: email_address: admin@example.com username: admin password: admin first_name: Fabien last_name: Potencier is_super_admin: true
Finally, replace the affiliate
functional test file for the backend application with the following code:
// test/functional/backend/affiliateActionsTest.php include(dirname(__FILE__).'/../../bootstrap/functional.php'); $browser = new JobeetTestFunctional(new sfBrowser()); $browser->loadData(); $browser-> info('1 - Authentication')-> get('/affiliate')-> click('Signin', array( 'signin' => array('username' => 'admin', 'password' => 'admin'), array('_with_csrf' => true) ))-> with('response')->isRedirected()-> followRedirect()-> info('2 - When validating an affiliate, an email must be sent with its token')-> click('Activate', array(), array('position' => 1))-> with('mailer')->begin()-> checkHeader('Subject', '/Jobeet affiliate token/')-> checkBody('/Your token is symfony/')-> end() ;
Cada email enviado puede ser probado con la ayuda de los métodos checkHeader()
y
checkBody()
. El segundo argumento de checkHeader()
y el primer argumento de
checkBody()
puede ser lo siguiente:
una cadena para comprobar que coincide exactamente;
una expresión regular para comprobar el valor;
una expresión regular negativa (es una que empieza con un
!
) para comprobar que el valor no coincide.
note
Por defecto, las comprobaciones son hechas en el primer email enviado. si muchos emails
se enviaron, puedes elegir uno para probarlo con el método withMessage()
.
El método withMessage()
toma un destinatario como su primer argumento. Este también
toma un segundo argumento para indicar cual email quieres probar si varios han sido
enviados al mismo destinatario.
tip
Como otros tester incluídos, puedes ver el mensaje en bruto llamando al método debug()
.
Nos vemos mañana
Mañana, vamos a implementar la última característica faltante del sitio web Jobeet, el motor de búsqueda.
This work is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported License license.