Este foro ya no está activo, así que no puedes publicar nuevas preguntas ni responder a las preguntas existentes.

Cómo enviar emails sin esperas con Swiftmailer

24 de febrero de 2015

Hola:

Estoy intentando enviar emails con SwiftMailer en producción. Aquí os dejo el código:

$email = \Swift_Message::newInstance()
            ->setSubject(' Uhuru Heights Apartments–Contact Details')
            ->setFrom($this->container->get('plantilla')->empresa->getEmail())
            ->setTo($message->getEmail())
            ->setBody($this->twig->render('AppBundle:Email:contacto.html.twig', ['message' => $message]))
;
 
$this->mailer->send($email);

La cuestión es que no me los envía. Me imagino que es porque tienes que hacer el comando:

$ php app/console swiftmailer:spool:send --env=prod

La cuestión es que necesito que el email se envíe al momento. Os dejo la configuración de mi email:

mailer_transport: gmail
    mailer_host: mail.uhuruheightsa.com 
    mailer_user: [email protected]
    mailer_password: ######

Pd: encontré esto:

swiftmailer.command.spool_send:
        class: Symfony\Bundle\SwiftmailerBundle\Command\SendEmailCommand
        calls:
            - [ setContainer, ["@service_container"] ]

Y añadiendo:

$this->container->get('swiftmailer.command.spool_send')->run(new ArgvInput(array()), new ConsoleOutput());

Pero sigue sin funcionar.


Respuestas

#1

Buenas, creo que por defecto en todas las versiones de symfony, el mailer viene configurado para enviar los correos al momento, sin ejecutar comandos ni nada por el estilo.

Ahora, ¿ese código php que muestras, donde se encuentra? ¿un servico o un controlador?, ya que veo que envias el correo así $this->mailer->send($email);. Por lo que supongo que en algún lado estás seteando el servicio mailer a esa propiedad.

Por último, cuando se hace un envío de correo, cuando se trabaja en DEV ó con el profiler activo, cada correo enviado queda registrado en dicho profiler para que puedas verificar si se hizo o no el envío.

Saludos!

@manuel_j555

24 febrero 2015, 16:46
#2

El codigo lo tengo en un controlador. He echo una prueba, usando la libreria mail()

$to = $booking->getUsuario()->getEmail();
$subject = 'Your booking at Uhuru Heights Apartments';
$message = $this->twig->render('AppBundle:Email:reserva.html.twig', ['booking' => $booking]);
$headers = 'From: [email protected]' . " " . "\r\n" .
 
    'Content-type: text/html; charset=iso-8859-1' . "\r\n";
mail($to, $subject, $message, $headers, '[email protected]');

Y así, si que me lo envía, pero quiero usar Swiftmailer. Y no estoy en dev, donde sí que me lo envía correctamente. El fallo está en prod.

$kernel = new AppKernel('dev', true);
swiftmailer:
    delivery_address: [email protected]

Si necesitáis más datos, solo decídmelo.

@TsubasaAkai

24 febrero 2015, 16:52
#3

Como dice @manuel_j555, por defecto en Symfony los emails se envían inmediatamente. Si no lo hacen, es porque hay algún error en la aplicación (consulta los archivos de log en app/logs/) o porque has configurado un spool.

Un spool no es más que un archivo en el que guardas todos los emails para no enviarlos inmediatamente y así mejorar el rendimiento de la aplicación. Para que los emails no se retrasen mucho y el spool no crezca demasiado, de vez en cuando tienes que enviar los emails pendientes ejecutando el comando swiftmailer:spool:send --env=prod que indicabas anteriormente.

Así que mi recomendación es que elimines cualquier configuración relacionada con los spool y pruebes de nuevo a enviar los emails. Comprueba también que no tengas la opción disable_delivery a true en la configuración de swiftmailer del entorno que utilices.

Por último, si utilizas una versión de Symfony muy antigua (anterior a 2.3), ten en cuenta que los comandos tenían que indicar explícitamente que querías enviar los emails (ver más información).

@javiereguiluz

24 febrero 2015, 16:57
#4

No estoy seguro de si en producción los correos enviados son agregados a los logs, pero prueba a revisar el archivo app/logs/prod.log para que verifiques si aparece algo de info allí al respecto.

Por otro lado, la petición que envía el correo, ¿cuando estás en producción se ejecuta por completo sin errores?

También veo que usas delivery_address (asumo que en modo dev), por lo que quizás $message->getEmail() no sea un correo válido, y como en dev no era tomado en cuenta, no te informaba del fallo.

En el archivo app/logs/prod.log podrías encontrar muchas de las cosas que pregunto.

@manuel_j555

24 febrero 2015, 17:00
#5

Otra pequeña mejora que puedes añadir en tu código es no instanciar la clase Swift_Message a mano sino utilizar las funcionalidades que te da el bundle de SwiftMailer para crear el mensaje:

$email = $this->mailer->createMessage()
    ->setSubject('Uhuru Heights Apartments–Contact Details')
    ->setFrom($this->container->get('plantilla')->empresa->getEmail())
    ->setTo($message->getEmail())
    ->setBody($this->twig->render('AppBundle:Email:contacto.html.twig', ['message' => $message]))
;

Coincido con @manuel_j555 en que el error puede deberse por ejemplo a que el email From o To no están bien formados.

@javiereguiluz

24 febrero 2015, 17:04
#6

En la configuración de Swiftmailer tengo lo siguiente:

swiftmailer:
    transport: "%mailer_transport%"
    host:      "%mailer_host%"
    username:  "%mailer_user%"
    password:  "%mailer_password%"
    spool:     { type: memory }

¿lo del spool es lo de { type: memory }?

@TsubasaAkai

24 febrero 2015, 17:07
#7

¡Exactamente! Esa configuración le dice a tu aplicación que utilice un spool en memoria en vez de basado en un archivo. ¿Cómo funciona? Si durante una petición envías varios emails, se guardan todos en memoria y se envían todos a la vez justo antes de terminar la petición.

¿Cuál es el problema? Que si sucede un error o una excepción en la aplicación, no se envía ningún mensaje. Así que en tu caso, donde quieres enviar los emails instantáneamente y evitar estos problemas, deberías usar la siguiente configuración:

swiftmailer:
    transport: "%mailer_transport%"
    host:      "%mailer_host%"
    username:  "%mailer_user%"
    password:  "%mailer_password%"

Si quieres indicar explícitamente que no usas ningún spool, utiliza lo siguiente:

swiftmailer:
    transport: "%mailer_transport%"
    host:      "%mailer_host%"
    username:  "%mailer_user%"
    password:  "%mailer_password%"
    spool:     ~

@javiereguiluz

24 febrero 2015, 17:29