Posted on by

Automatically Sending an Email using the WordPress Cron

I occasionally get requests for a way to have an email sent automatically when a certain condition is met. For example, when it’s someone’s birthday, an email would be sent to them with a birthday greeting.

This kind of thing is possible using the WordPress cron, which can launch functions in the background.

This is a tutorial on how something like this can be set up, and requires the use of the Participants Database Email Expansion Kit, which provides a way to define email templates that can be used for any number of different purposes.

Before we get into this, I want to warn that this is not a tutorial for non-coders…you will definitely need to know php and mysql to get what you want out of this.

Please note: the line that actually sends emails has been commented out for safety. This plugin will not send email unless you un-comment line 81

Our Example

In this tutorial, we will be using the example of sending a reminder to people to keep their record updated. It is a reminder that is sent out automatically if it has been over a month since the last time they updated their record.

This example is probably different from what you might want to do, but it has all the elements you will need for your own application. Any application that sends emails automatically will need these basic parts:

  1. Set up a WordPress cron event that will be triggered in the background at regular intervals.
  2. When the cron event is triggered, it lanches a function to check the database for records that should have an email sent.
  3. We also need to check if the email has already been sent, so we don’t send them an email every time the cron event is fired.
  4. Send the email: this is done by triggering an action in the Email Expansion Kit add-on for Participants Database
  5. Log the send so that the next time the cron action is triggered we know that an email was sent to that person.

The WordPress Cron

Generally, a cron is a scheduled action on a web server. WordPress has its own built-in cron where you can schedule events to recur at specific intervals such as hourly or daily. Our example runs every day to check for possible recipients of the reminder email. There’s no need to have it run more often because we don’t really care what time the email is sent, we just want it to be within a day of when the record becomes eligible to get a reminder sent.

Checking the Database

When the cron is triggered, the plugin needs to check the database to get a list of records that qualify for the reminder email.

This is one part you will be customizing for your own application. For example, for the birthday one, you’ll need a database query that will match all records with a birth date value that matches today’s date. (You will need to determine the query needed to get the records for whatever it is you want to do.)

In this example, we get all the records where the user has not updated their record in the last 30 days. This happens in the get_late_accounts method in the example code.

Preventing Duplicate Sends

Once someone has been reminded, we probably don’t want to remind them again for a while. We handle that by logging the date and time we sent an email to them. That way, we can know how long it’s been since the last time we sent the email.

This is handled in the email_should_be_sent method. First we check for any log entry for the record and return true if an email has never been sent.

Then we check the date of the last sent email to see if we need to send another one. If the date is outside our “don’t send” window, we return true, indicating that the record is ready for another email.

Sending the Email

Sending the email is relatively simple: we need to know which email template to use, and also send the data from the record so that the template values can be filled in with data from that record. We already have the record data from checking the database.

Sending the email is handled in the send_reminder method. We first get the template from the Email Expansion Kit plugin, then we trigger the action with the template and the record data.

Logging the Send

Whenever an email is sent, we save the date and time it was sent for the record. The next time we’re considering sending an email to this record, we can check the log to see when that happened last.

The PDB Email Cron Plugin

The plugin is pretty simple, it’s really just a demonstration of how to handle sending an email on a cron.

To use this plugin, you must first configure an email template. Leave the “Send Action” blank, we are using our own send trigger to send it, so it doesn’t need to have one programmed in.

After setting up your template, note the ID number of the template. You can see this on the page where the template is defined. You will type this number in to the $template_id variable declaration near the top of the example code.

Defining the Conditions of the Send

This part is going to be the most challenging part for less-experienced coders. You will need to come up with a database query that will select the records that you might want to send an email to.

In the example, in the get_late_accounts method, we first compute the threshold date…the date where if the record is older than that, it will be selected. That date is formatted as a mysql timestamp because we will be comparing against a mysql timestamp in the database record.

We run the query and get the set of matched records. Next, we loop through those records, checking for ones that need to actually have an email sent. Your custom application will probably need to do something like that as well.

Be Careful with Email Sending

Remember you could easily send lots of emails out unintentionally. This plugin has no throttling of any kind, so if it’s possible the plugin could send hundreds of emails, you will need to throttle that down so it doesn’t try to do that.

One way to throttle it would be to count how many emails are going out in a single session. Once a certain number is reached, stop sending. The remaining records will get their emails the next time around because the code will skip the ones that got it already. You will want to increase the frequency of the cron if you’re doing that so that all the emails will eventually go out in a reasonable time.

Testing the Plugin

Be sure to test things without actually sending emails until you know it’s working as expected. Nobody wants to get a bunch of spurious “test” emails. I commented out the line that sends the email in the send_reminder method.

You should add an error_log statement that tells you that an email would be sent. I put an example of that in comments in the code. When the cron runs, the error log will show you which records would get emails sent to them.

It’s a good idea to install a plugin to help with crons, I use WP Crontrol. It lets you see which crons are scheduled, and more importantly lets you trigger a cron manually. This is a good way to test your plugin because you don’t have to wait for it to trigger on it’s own.

Get your php error log set up or Participants Database debugging. You can put error_log statements in the code to see how it is executing and if you’re getting the expected results from your database queries.

Once you’ve tested the code and it’s not going to do anything unexpected, uncomment the line that sends the email and you’re all set. If you leave Participants Database debugging on, you will see a record of the outgoing emails in the debugging log.

I also recommend you install an email logging plugin to keep a record of any outgoing emails that have been sent. I like Email Log for that.

Here’s the Code

I wrote this as a plugin, so you can easily install it and run it on your site. Check this post for instructions on how to install this code example as a plugin.

Leave a Reply
You have to agree to the comment policy.

Would you like to be notified of followup comments via e-mail? You can also subscribe without commenting.

Leave a Reply
You have to agree to the comment policy.

Would you like to be notified of followup comments via e-mail? You can also subscribe without commenting.