Emails - Cron or no Cron

Hi, i have built a custom site using Codeigniter.

My site allows users to post a story to the site… then other users can comment on the story.

There is an option under the users Settings to choose whether you want to be notified by email if:

A - MY STORY
a user comments on my story

B - MY COMMENTS ON OTHER USER’S STORIES
another user comments on a story that i have commented on

I don’t think i need any special script or service to handle email A, as it is just one email to one user, however Email B is a different story as 1000 users might have commented on a story and then 1000 users might need to receive an email each time a new user comments on the same story they have commented on, so:

1 - is there a 3rd party service that i should use in conjunction with codeigniter to handle these bulk emails

2 - should i process all of these batch emails using a cron… if so can someone recommend the best way to run this process

Thanks in advance for your help…

I would strongly recommend that you use a service to send the e-mails as you will run into lots of issues with spam and batching otherwise. We used to send our e-mails through cron, but have now switched to Mandrill and haven’t looked back. Some other good choices are http://sendgrid.com, http://postmarkapp.com, Amazon SES, etc.

I have the same situation on one of my sites so I can share with you how I implemented it, it works well so far. Whenever I want to send an email I add it to the message queue - the queue is a table in the database which holds all message information like email, subject, body, etc. Then I have a script for sending messages from the queue, let’s name it sendFromQueue.php - this script reads the queue from the db and sends the messages one by one. It has a defined maximum execution time (like 1 minute) and if it runs too long it simply quits and the remaining emails will be sent on the next run. It also has a locking mechanism so that only one instance can be run at the same time, otherwise it quits (you can use mysql’s GET_LOCK() function for this).

sendFromQueue.php is launched in two separate ways:

  • by cron, for example every 2 minutes
  • by the running php application whenever something needs to be sent immediately - I run it by starting a http connection to the script with a timeout - in this way the sending script is kept separate from the main application, I can launch it like a deamon and it will work independently on its own. A very simplified example:

// user has posted a comment so now we need to send emails to all subscribed users
foreach ($subscribedUsers as $user) {
  // we add each user to the queue
  $db->query("INSERT INTO message_queue SET email='$user->email', subject='$subject', body='$body', status='new', time_added=NOW()");
}

// now we launch sendFromQueue.php so that sending of the messages is started
// immediately (we don't have to wait for the cron)
$ctx = stream_context_create(array(
	'http' => array(
		'timeout' => 1
		)
	)
);

// put the URL of your site here
$cron_script = "http://mysite.example.com/sendFromQueue.php";

// this will take maximum 1 second because this is the timeout set in $ctx,
// but the external script will continue running in its own thread
@file_get_contents($cron_script, false, $ctx);

// redirect user to the next page
// ...

You can also use CURL instead of file_get_contents(). The locking mechanism in sendFromQueue.php is important because it can happen that the sending script will be called both by cron and by the above script at the same time and you don’t end up with duplicate emails sent to users.

This method is simple enough to work on a shared hosting service, if you don’t have access to cron you can even make your own pseudo-cron that will launch sendFromQueue.php at certain time intervals when users visit your site.

And of course, I use swiftmailer for sending emails via SMTP account created for this purpose.