Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending emails asynchronously: spool, queue, and cronjob/daemon

I want to send emails asynchronously for faster and lighter http responses, but I'm struggling with many new concepts.

For example, the documentation talks about spool. It says I should use spool with a file, and then send emails with a command. But how should I be running that command? If I set a cronjob to execute that command every 1 minute (the minimum available in cron), users will have to wait an average of 30 secs for their emails to be sent (eg, the registration email).

So I thought of using a queue instead. I'm already using RabbitMQBundle for image processing (eg, thumbnail creation). But I only use this one periodically, so it is consumed from within a cronjob.

Maybe I should create a daemon that is always waiting for new messages to arrive the email queue and deliver them ASAP?

like image 293
ChocoDeveloper Avatar asked Nov 24 '12 16:11

ChocoDeveloper


2 Answers

The solution is to send every email to a queue, and then consume that queue with a service. My service is very simple, it just takes items out of the queue, where each item is an array with from, to, body, etc., and sends that email. I'm using Thumper which makes Rabbit easier to use: github.com/videlalvaro/Thumper . And I make sure the service is always up using 'sv' (from Runit): smarden.org/runit/sv.8.html . You can use any other service or daemon manager you like.

like image 175
ChocoDeveloper Avatar answered Sep 29 '22 00:09

ChocoDeveloper


I have the same problem as you had. How you finally solved your problem?

For the moment I run a little script in the crontab in order to run in loop:

<?php
include('/var/www/vendor/symfony/symfony/src/Symfony/Component/Filesystem/LockHandler.php');
use Symfony\Component\Filesystem\LockHandler;

$lock = new LockHandler('mailer:loop');
if ($lock->lock()) {
    system('cd /var/www && php app/console swiftmailer:spool:send');
    sleep(1);
    $lock->release();
    shell_exec('cd /var/www && php LoopMailer.php > /dev/null 2>/dev/null &');
}

It's not very clean but it does his job.

like image 23
Alexandre Avatar answered Sep 29 '22 01:09

Alexandre