Email Integration in WordPress

WordPress sends emails using the wp_mail() function, which is a wrapper around PHP’s mail() function. While it works for simple setups, it is unreliable in production environments because many hosting providers block or throttle PHP mail. Professional deployments typically use an SMTP or API-based email service. A commonly recommended solution is Amazon SES (Simple Email Service), which provides scalable and reliable email delivery.

wp_mail() basics

The wp_mail() function sends emails using the WordPress mail system. It supports plain text and HTML emails and allows attachments and custom headers.

Basic usage:

$to = 'user@example.com';
$subject = 'Welcome to Our Website';
$message = 'Thank you for registering.';
$headers = array('Content-Type: text/plain; charset=UTF-8');

wp_mail($to, $subject, $message, $headers);

Sending HTML email:

add_filter('wp_mail_content_type', function () {
    return 'text/html';
});

$to = 'user@example.com';
$subject = 'Account Created';
$message = '<h1>Welcome</h1><p>Your account has been created successfully.</p>';

wp_mail($to, $subject, $message);

remove_filter('wp_mail_content_type', '__return_false');

Adding attachments:

$to = 'user@example.com';
$subject = 'Report';
$message = 'Please find the attached report.';
$attachments = array(WP_CONTENT_DIR . '/uploads/report.pdf');

wp_mail($to, $subject, $message, array(), $attachments);

Using hooks to modify outgoing emails:

add_filter('wp_mail', function ($args) {
    $args['headers'][] = 'Reply-To: support@example.com';
    return $args;
});

Using Amazon SES for WordPress email delivery

Amazon SES is a cloud-based email service designed for reliable transactional email delivery. Instead of relying on PHP mail, SES uses SMTP or API-based sending.

Benefits of SES:

Reliable email delivery
Better reputation management
High scalability
Detailed email analytics
Cost-effective at scale

Typical architecture:

WordPress → SMTP/API → Amazon SES → Recipient Mail Server

SES SMTP configuration example:

add_action('phpmailer_init', function ($phpmailer) {

    $phpmailer->isSMTP();
    $phpmailer->Host       = 'email-smtp.us-east-1.amazonaws.com';
    $phpmailer->SMTPAuth   = true;
    $phpmailer->Port       = 587;
    $phpmailer->Username   = 'SMTP_USERNAME';
    $phpmailer->Password   = 'SMTP_PASSWORD';
    $phpmailer->SMTPSecure = 'tls';

    $phpmailer->From       = 'noreply@example.com';
    $phpmailer->FromName   = 'My Website';

});

Best practices for production email

Always use SMTP or API-based email services instead of PHP mail
Verify domains and email addresses in SES
Use dedicated transactional email addresses (e.g., noreply@domain.com)
Log outgoing emails for debugging
Use queue/background processing for bulk emails

Testing email delivery with MailHog

MailHog is a developer email testing tool that captures outgoing emails from applications and displays them in a web interface. Instead of actually sending emails to recipients, MailHog intercepts them and stores them locally.

This allows developers to inspect:

Email content
Headers
Attachments
HTML rendering

MailHog workflow:

WordPress → SMTP → MailHog → Web UI

Typical MailHog SMTP configuration:

SMTP host: localhost
SMTP port: 1025
Web UI: http://localhost:8025

Example configuration in WordPress:

add_action('phpmailer_init', function ($phpmailer) {

    $phpmailer->isSMTP();
    $phpmailer->Host = 'localhost';
    $phpmailer->Port = 1025;
    $phpmailer->SMTPAuth = false;

});

Testing email in a plugin during development:

function rt_send_test_email() {

    $to = 'test@example.com';
    $subject = 'MailHog Test Email';
    $message = 'This email should appear in MailHog UI.';

    wp_mail($to, $subject, $message);
}

add_action('init', 'rt_send_test_email');

Important development considerations

If a third-party email plugin (SMTP plugin, transactional email plugin, etc.) is active in a development environment, MailHog may not intercept emails properly. Such plugins often override the mail transport and send emails directly to the external provider.

For safe development:

Disable third-party email plugins locally
Use MailHog SMTP configuration
Avoid using real customer email addresses in development environments

Background Processing in WordPress

Background processing allows long-running tasks to execute asynchronously without blocking user requests. Instead of performing heavy operations during a page load, tasks are queued and processed separately.

Problems with synchronous processing

Slow page loads
PHP timeout errors
Poor user experience
Server resource spikes

Example of synchronous processing problem:

foreach ($users as $user) {
    send_email_to_user($user);
}

If thousands of users exist, this process can take several seconds or minutes.

Background processing architecture

User action → Queue task → Background worker → Task execution

In WordPress, background processing can be implemented using:

WP_Cron
Custom queues
Action Scheduler

WP_Cron limitations

WP_Cron is a pseudo-cron system triggered by site visits. It has several limitations:

Depends on traffic
Unreliable timing
Limited scalability
Not suitable for large queues

Action Scheduler

Action Scheduler is a scalable background job processing library developed by the WooCommerce team. It is widely used in production WordPress systems for reliable task scheduling.

Features:

Persistent queue storage
Batch processing
Retry handling
Error logging
Scalable background execution

Installing Action Scheduler

It can be bundled with plugins or installed via Composer.

Composer installation:

composer require woocommerce/action-scheduler

Scheduling a background task

as_schedule_single_action(
    time() + 60,
    'rt_send_background_email',
    array('user_id' => 123)
);

Hook to process the scheduled task:

add_action('rt_send_background_email', 'rt_process_email');

function rt_process_email($user_id) {

    $user = get_user_by('ID', $user_id);

    if (!$user) {
        return;
    }

    wp_mail(
        $user->user_email,
        'Background Email',
        'This email was sent from a background process.'
    );
}

Recurring scheduled task:

as_schedule_recurring_action(
    time(),
    HOUR_IN_SECONDS,
    'rt_hourly_cleanup'
);

Task handler:

add_action('rt_hourly_cleanup', function () {
    global $wpdb;

    $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_%'");
});

Checking scheduled actions

$actions = as_get_scheduled_actions(array(
    'hook' => 'rt_send_background_email',
    'status' => ActionScheduler_Store::STATUS_PENDING
));

Background processing use cases in WordPress plugins

Bulk email sending
Import/export operations
API synchronization
Generating reports
Image processing
Data migrations

Using Supervisor for background workers

Supervisor is a process control system used on servers to monitor and manage background worker processes. It ensures that background workers remain active and automatically restart if they fail.

Typical use cases:

Queue workers
Long-running background processes
Monitoring background scripts

Example worker command:

php wp-content/plugins/my-plugin/worker.php

Supervisor configuration example:

[program:wp-background-worker]
command=php /var/www/html/wp-content/plugins/my-plugin/worker.php
autostart=true
autorestart=true
stderr_logfile=/var/log/worker.err.log
stdout_logfile=/var/log/worker.out.log

Benefits of using background processing in plugins

Improved performance
Better user experience
Reduced request time
Reliable task execution
Scalable job management

Practical plugin pattern combining email and background jobs

Instead of sending emails during a request:

User registers → Queue email job → Background worker sends email

Example:

add_action('user_register', function ($user_id) {

    as_schedule_single_action(
        time(),
        'rt_send_welcome_email',
        array('user_id' => $user_id)
    );

});

Email processor:

add_action('rt_send_welcome_email', function ($user_id) {

    $user = get_user_by('ID', $user_id);

    if (!$user) {
        return;
    }

    wp_mail(
        $user->user_email,
        'Welcome',
        'Thanks for joining our website.'
    );

});

This pattern ensures fast user registration while the email is handled asynchronously in the background.