Using cron to send bulk email on a shared host

  |   By  |  4 Comments

I’m running a conference booking system at and we need to send out lots of emails to delegates and potential delegates. Our host only allows 100 emails per hour from the website, so I needed to find a way of queueing them and sending in batches…

First a mysql db table…

  `to` varchar(500) NOT NULL,
  `from_name` text NOT NULL,
  `from_email` text NOT NULL,
  `copy` text NOT NULL,
  `subject` varchar(500) NOT NULL,
  `message` text NOT NULL,
  `attachment` text NOT NULL,
  `sent` datetime NOT NULL,
  `email_id` int(11) NOT NULL auto_increment,
  PRIMARY KEY  (`email_id`)

I’ve not set up attachments yet, so that table continues everything else we need.

Here’s a function to queue messages

function QueueEmail($to,$subject,$message,$copy,$from_name,$from_email,$attachment)

    $sql="INSERT INTO (`to`,`from_name`,`from_email`,`copy`,`subject`,`message`,`sent`,`attachment`)VALUES('{$sqlsafe['to']}','{$sqlsafe['from_name']}','{$sqlsafe['from_email']}','{$sqlsafe['copy']}','{$sqlsafe['subject']}','{$sqlsafe['message']}',NOW(),'{$sqlsafe['attachment']}')";
    $result=mysql_query($sql) or die(mysql_error());
    if($result) {return TRUE;}else{return FALSE;}

I tend to call it with some basic messaging

echo "

Message to $to queued

"; } else { echo "

Message to $to NOT queued

"; }

So that handles creating messages and storing them in the database queue.

Here’s my cronemail.php file

//email sending script from db queue
define("DB_SERVER", "#");//replace # with server name
define("DB_USER", "#");//replace # with mysql username
define("DB_PASS", "#");//replace # with mysql password
define("DB_NAME", "#");//replace # with db name
// connect to database
$db=mysql_connect(DB_SERVER,DB_USER,DB_PASS)or die("Couldn't connect to database");
mysql_select_db(DB_NAME)or die("Couldn't open database".mysql_error() );

//initialise phpmailer script
$mail = new PHPMailer();
//Grab 80 messages
$sql="SELECT * FROM email ORDER BY email_id LIMIT 0,80";
{//only proceed if emails queued in db 
        $mail->SetFrom($row['from_email'], $row['from_name']);
            $mail->AddAttachment($path, $name = "", $encoding = "base64",$type = "application/octet-stream");
        $mail->Subject = $row['subject'] ;
                //successful send, so delete from DB
                $sql="DELETE FROM email WHERE email_id='".mysql_real_escape_string($row['email_id'])."'";

                mysql_query($sql)or die(mysql_error());
        $mail->ClearAllRecipients();//clears all recipients
        $mail->ClearCustomHeaders();//clears headers for next message
foreach($attachment AS $file)
    unlink($file);//gets rid of uploaded attachments from temporary folder

The code is well commented – make sure you replace the hashes!

You will also need the excellent phpmailer script

Now we need to set up our shared host to execute cronemail.php every hour!

Go to your CPANEL and click on cron jobs – on my version there is a standard link and an advanced link

I use standard!

Common settings gives you some common options – once an hour is what we want (although for testing once every five minutes would be less tedious)

The command to run took a bit longer to get right! A lot of blog posts get this bit wrong!!!

You need to find out your php path – most likely to be /usr/local/bin/php

Then you need the path to the script – best put in a non-public accessable area or in the document root if you must!


So now you can type

/usr/local/bin/php -f /home/(username)/public_html/cronemail.php

into the command to run field and press . The -f tells the php compiler to run the file. Don’t forget to change (username) to your username.

Hope it helps…
Here it is in a zip file with a tester script index.php –emailstuff. Don’t use index.php in a production environment as there is no form checking!



Andy Moyle is a church leader and web developer. His biggest project is the Church Admin WordPress plugin and app. He also runs, mainly so he can eat pizza.