When purchasing a product in WooCommerce, it sends several emails by default. This delays the actual process, which already can take very long. Thus, a good strategy would be to send them asynchronously via a cron job.

What’s a cron job?

A cron job is a task that is executed on a certain point in time. WordPress allows to define recurring tasks as well as single events (we use the latter here for every email). By default, it get’s triggered via an asynchronous request from any user in the frontend, which requests the /wp-cron.php file.

On a highly frequented website (or when you want to control the exact moment the cron jobs are executed), you probably want to disable this builtin mechanic via \define( 'DISABLE_WP_CRON', true ) in your wp-config.php and define a system cron job or timer to regularly request the file (or use WP-CLI).

The solution

Luckily, we don’t even need to reinvent the wheel, since the solution is already available since 2015 on Stack Overflow. This is not limited to WooCommerce emails, but delays all emails to be only sent via cron job.

<?php
/**
 * Email Async.
 *
 * We override the wp_mail function for all non-cron requests with a function that simply
 * captures the arguments and schedules a cron event to send the email.
 */
if ( ! \defined( 'DOING_CRON' ) || ( \defined( 'DOING_CRON' ) && ! \DOING_CRON ) ) {
    function wp_mail() {
        // Get the args passed to the wp_mail function
        $args = \func_get_args();
        // Add a random value to work around that fact that identical events scheduled within 10 minutes of each other
        // will not work. See: http://codex.wordpress.org/Function_Reference/wp_schedule_single_event
        $args[] = \mt_rand();

        // Schedule the email to be sent
        \wp_schedule_single_event( \time() + 5, 'cron_send_mail', $args );
    }
}

/**
 * This function runs during cron requests to send emails previously scheduled by our
 * overrided wp_mail function. We remove the last argument because it is just a random
 * value added to make sure the cron job schedules correctly.
 *
 * @hook    cron_send_mail  10
 */
function example_cron_send_mail() {
    $args = \func_get_args();

    // Remove the random number that was added to the arguments
    \array_pop( $args );
    \call_user_func_array( 'wp_mail', $args );
}

/**
 * Hook the mail sender. We accept more arguments than wp_mail currently takes just in case
 * they add more in the future.
 */
\add_action( 'cron_send_mail', 'example_cron_send_mail', 10, 10 );
Code language: PHP (php)

Just save this code and place it inside /wp-content/mu-plugins/asynchronous-emails.php (if the directory does not exist, create it) and it will be automatically executed by WordPress as a ā€œmust useā€ plugin. That way, you can probably save a second in the checkout.

Reposts

Leave a Reply

Your email address will not be published. Required fields are marked *

To respond on your own website, enter the URL of your response which should contain a link to this post's permalink URL. Your response will then appear (possibly after moderation) on this page. Want to update or remove your response? Update or delete your post and re-enter your post's URL again. (Learn more about webmentions)