2026年5月20日

2026年5月20日

WordPressのメールキューを管理して大量メール送信を安定化する方法

はじめに

会員サイトやECサイトでニュースレターや注文通知を大量送信する場合、一度に全員に送るとSMTPのレート制限に引っかかり送信失敗が続くことがあります。メールキューを実装することで安定した配信が可能になります。

解決手順

ステップ1:メールキューテーブルを作成する

// プラグイン有効化時にテーブルを作成
function create_mail_queue_table() {
    global $wpdb;
    $sql = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}mail_queue (
        id          BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
        to_email    VARCHAR(255) NOT NULL,
        subject     TEXT NOT NULL,
        message     LONGTEXT NOT NULL,
        headers     TEXT,
        status      ENUM('pending','sending','sent','failed') DEFAULT 'pending',
        attempts    TINYINT UNSIGNED DEFAULT 0,
        created_at  DATETIME NOT NULL,
        sent_at     DATETIME,
        PRIMARY KEY (id),
        KEY status (status),
        KEY created_at (created_at)
    ) {$wpdb->get_charset_collate()};";
    require_once ABSPATH . 'wp-admin/includes/upgrade.php';
    dbDelta($sql);
}
register_activation_hook(__FILE__, 'create_mail_queue_table');

ステップ2:キューにメールを追加する

// キューにメールを追加する関数
function enqueue_mail(string $to, string $subject, string $message, array $headers = []): bool {
    global $wpdb;
    return (bool) $wpdb->insert(
        $wpdb->prefix . 'mail_queue',
        [
            'to_email'   => $to,
            'subject'    => $subject,
            'message'    => $message,
            'headers'    => wp_json_encode($headers),
            'status'     => 'pending',
            'created_at' => current_time('mysql'),
        ],
        ['%s', '%s', '%s', '%s', '%s', '%s']
    );
}

// 使用例:1000件の会員に一括送信をキューに追加
$users = get_users(['role' => 'subscriber', 'fields' => ['user_email']]);
foreach ($users as $user) {
    enqueue_mail($user->user_email, 'お知らせ', 'ニュースレターです。');
}

ステップ3:WP Cronでキューを処理する

// functions.php — 5分ごとにキューを処理
add_filter('cron_schedules', function($schedules) {
    $schedules['every_5_minutes'] = [
        'interval' => 300,
        'display'  => '5分ごと',
    ];
    return $schedules;
});

if (!wp_next_scheduled('process_mail_queue')) {
    wp_schedule_event(time(), 'every_5_minutes', 'process_mail_queue');
}

add_action('process_mail_queue', function() {
    global $wpdb;
    // 1回のバッチで10件処理
    $emails = $wpdb->get_results(
        "SELECT * FROM {$wpdb->prefix}mail_queue WHERE status='pending' LIMIT 10"
    );

    foreach ($emails as $email) {
        $wpdb->update(
            $wpdb->prefix . 'mail_queue',
            ['status' => 'sending'],
            ['id' => $email->id]
        );

        $headers = json_decode($email->headers, true) ?: [];
        $sent    = wp_mail($email->to_email, $email->subject, $email->message, $headers);

        $wpdb->update(
            $wpdb->prefix . 'mail_queue',
            [
                'status'   => $sent ? 'sent' : 'failed',
                'attempts' => $email->attempts + 1,
                'sent_at'  => $sent ? current_time('mysql') : null,
            ],
            ['id' => $email->id]
        );
    }
});

ステップ4:WP-CLIでキューを手動処理する

# キューの状態を確認
wp db query "SELECT status, COUNT(*) as count FROM wp_mail_queue GROUP BY status;"

# キューを手動で即時処理
wp eval "do_action('process_mail_queue');"

# 失敗したメールを再送
wp db query "UPDATE wp_mail_queue SET status='pending', attempts=0 WHERE status='failed';"

注意事項

  • WP Cronはサイトへのアクセスがないと実行されません。本番環境ではサーバーの crontab から wp cron event run --due-now を定期実行することを推奨します
  • 1バッチの送信件数はSMTPプロバイダーのレート制限(例:Mailgun 600通/分)に合わせて調整してください
  • 送信失敗時のリトライ回数(attempts)に上限を設け、無限ループを防いでください

まとめ

メールキューは「キューテーブルへの追加 → WP Cronでバッチ処理」の2ステップで実装できます。大量送信の場合は1バッチ10〜50件に制限し、SMTPプロバイダーのレート制限を超えないようにしてください。

お気軽にご相談ください

お見積りへ お問い合わせへ