2026年5月20日
2026年5月20日
WordPressのwp_mail()関数の使い方(HTMLメール・CC/BCC・添付・エラー処理)
wp_mail() は、WordPress でメールを送るための関数です。WordPress に含まれるメール送信ライブラリ PHPMailer を使って送信し、フィルターやアクションで送信内容や送信方法を変えられます。WordPress 本体のパスワード再設定メールやコメント通知も、この関数で送られています。
この記事のコードは、2026年11月時点の WordPress 7.1 の wp_mail() の実装で確認しています。
引数と戻り値
// wp-includes/pluggable.php での定義(処理の中身は省略)
function wp_mail( $to, $subject, $message, $headers = '', $attachments = array(), $embeds = array() ) { /* ... */ }
| 引数 | 内容 |
|---|---|
$to |
宛先。メールアドレスの配列か、カンマ区切りの文字列 |
$subject |
件名 |
$message |
本文 |
$headers |
追加のヘッダー(省略可)。配列か、改行区切りの文字列 |
$attachments |
添付するファイルのパス(省略可)。配列か文字列 |
$embeds |
HTML メールに埋め込む画像のパス(省略可、WordPress 6.9 で追加) |
戻り値は true か false です。true は「PHPMailer がエラーなく送信処理を終えた」という意味で、相手に届いたことまでは示しません。迷惑メールとして扱われたり、受信側のサーバーで拒否されたりした場合も true になります。
呼び出す場所
wp_mail() は、テーマの functions.php などに直接書くと、ページが表示されるたびに実行され、そのたびにメールが送られます。「記事が公開されたとき」「フォームが送信されたとき」のように、きっかけになるフックの中で呼びます。
記事が公開されたときに管理者へ知らせる例です。
<?php
// 投稿が初めて公開されたときに、管理者メールアドレスへ知らせる
add_action( 'transition_post_status', function ( $new_status, $old_status, $post ) {
if ( 'publish' !== $new_status || 'publish' === $old_status || 'post' !== $post->post_type ) {
return;
}
wp_mail(
get_option( 'admin_email' ),
'記事が公開されました: ' . $post->post_title,
get_permalink( $post )
);
}, 10, 3 );
HTML メールを送る
標準では、本文はテキスト(text/plain)として送られます。HTML として送るには、Content-Type ヘッダーを付けます。本文に差し込む値は esc_html() でエスケープします。
<?php
function kw_send_order_mail( $to, $order_no, $total ) {
$subject = 'ご注文の確認';
$message = '<p>ご注文ありがとうございます。</p>'
. '<p>注文番号: <strong>' . esc_html( $order_no ) . '</strong></p>'
. '<p>合計金額: ' . esc_html( number_format( $total ) ) . '円</p>';
$headers = array( 'Content-Type: text/html; charset=UTF-8' );
return wp_mail( $to, $subject, $message, $headers );
}
すべてのメールを HTML にする wp_mail_content_type フィルターもありますが、使うと WordPress 本体のテキストのメール(パスワード再設定など)まで HTML として送られ、改行が消えるなどの表示崩れが起きます。必要なメールだけ、上のようにヘッダーで指定します。
HTML メールの文字化けについては「WordPressのwp_mail()でHTMLメールが文字化けする場合の原因と対処法」で説明しています。
複数の宛先・CC・BCC・返信先を指定する
<?php
$to = array( 'user1@example.com', 'user2@example.com' );
$subject = 'お知らせ';
$message = 'サイトからのお知らせです。';
$headers = array(
'From: サイト名 <noreply@example.com>',
'Cc: admin@example.com',
'Bcc: log@example.com',
'Reply-To: support@example.com',
);
wp_mail( $to, $subject, $message, $headers );
$toに複数のアドレスを渡すと、1通のメールの宛先に全員が並びます。お互いのアドレスを見せたくない場合は、1人ずつwp_mail()を呼ぶか、BCC を使います。From:を省略すると、送信元はwordpress@サイトのドメインになります。送信元のアドレスは、サイトのドメインのものにします。ほかのドメイン(フリーメールなど)を指定すると、SPF などの送信元の確認に失敗し、届きにくくなります。送信元の変え方は「WordPressのメール送信元(From)アドレスと送信者名を変更する方法」で説明しています。
添付ファイルを付ける
$attachments には、サーバー上のファイルのパスを渡します。URL では添付できません。
<?php
$attachments = array(
get_attached_file( 123 ), // メディアライブラリの ID 123 のファイル
WP_CONTENT_DIR . '/uploads/report.pdf', // パスを直接指定
'月次レポート.pdf' => '/path/to/report-2026-11.pdf', // キーを文字列にすると添付ファイル名になる
);
wp_mail( 'user@example.com', '月次レポート', '添付のレポートをご確認ください。', '', $attachments );
配列のキーを文字列にすると、そのキーが受信者に見える添付ファイル名になります(WordPress 6.2 で追加)。ファイルが見つからない添付は、送信時に飛ばされます。
HTML メールに画像を埋め込む(WordPress 6.9 以降)
WordPress 6.9 で追加された6番目の引数 $embeds を使うと、画像をメールに埋め込み、本文の <img> から cid:キー で参照できます。
<?php
$message = '<p><img src="cid:logo" alt="ロゴ"></p><p>いつもご利用ありがとうございます。</p>';
$headers = array( 'Content-Type: text/html; charset=UTF-8' );
$embeds = array(
'logo' => get_stylesheet_directory() . '/images/logo.png', // キー logo が cid になる
);
wp_mail( 'user@example.com', 'お知らせ', $message, $headers, array(), $embeds );
WordPress 6.8 以前では6番目の引数は無視されるため、画像は表示されません。
送信の失敗を記録する
送信に失敗すると、wp_mail_failed アクションに WP_Error が渡されます。エラーの内容をログに書く例です。
<?php
add_action( 'wp_mail_failed', function ( $error ) {
error_log( '[wp_mail failed] ' . $error->get_error_message() );
} );
$sent = wp_mail( 'user@example.com', '件名', '本文' );
if ( ! $sent ) {
// 送信できなかったときの処理(画面にエラーを出す、あとで再送するなど)
}
error_log() の書き込み先は PHP の設定で決まります。wp-config.php で WP_DEBUG と WP_DEBUG_LOG を true にすると、wp-content/debug.log に書かれます。ここでメールを送って知らせようとすると、同じ理由で失敗するため、ログに残すだけにします。
送信が成功したときは wp_mail_succeeded アクション(WordPress 5.9 で追加)が呼ばれます。
ステージング環境ではメールを送らない
本番のデータをコピーしたステージング環境から、本物の利用者にメールが届く事故を防ぐ例です。WordPress 5.5 で追加された wp_get_environment_type() で環境を判定します。環境は wp-config.php で define( 'WP_ENVIRONMENT_TYPE', 'staging' ); のように指定します(指定しなければ production)。
<?php
// 本番以外では送信せず、宛先だけログに残す
add_filter( 'pre_wp_mail', function ( $return, $atts ) {
if ( 'production' !== wp_get_environment_type() ) {
error_log( '[wp_mail skipped] to: ' . implode( ', ', (array) $atts['to'] ) );
return true; // 送信したことにして、実際には送らない
}
return $return;
}, 10, 2 );
pre_wp_mail(WordPress 5.7 で追加)で null 以外を返すと、wp_mail() は送信せずにその値を返します。
宛先を開発チームに差し替えて送りたい場合は、wp_mail フィルターで引数を書き換えます。ただし、ヘッダーに Cc: や Bcc: があると、そちらには元の宛先のまま届く点に注意します。
<?php
add_filter( 'wp_mail', function ( $args ) {
if ( 'staging' === wp_get_environment_type() ) {
$args['to'] = 'dev-team@example.com';
$args['subject'] = '[STAGING] ' . $args['subject'];
}
return $args;
} );
SMTP サーバーから送る
標準の wp_mail() は、サーバーの PHP の mail() 機能で送ります。届きにくい場合は、phpmailer_init アクションで PHPMailer の設定を変え、メールサービスの SMTP サーバーから送ります。
<?php
// wp-config.php に自分で定義した定数(SMTP_HOST など)を使って SMTP で送る
add_action( 'phpmailer_init', function ( $phpmailer ) {
$phpmailer->isSMTP();
$phpmailer->Host = SMTP_HOST;
$phpmailer->Port = SMTP_PORT; // 587(STARTTLS)か 465(SSL/TLS)
$phpmailer->SMTPAuth = true;
$phpmailer->Username = SMTP_USER;
$phpmailer->Password = SMTP_PASS;
$phpmailer->SMTPSecure = 'tls'; // 587 なら 'tls'、465 なら 'ssl'
} );
SMTP_HOST などは WordPress 本体の定数ではなく、パスワードをコードに直接書かないために wp-config.php で自分で定義するものです(例: define( 'SMTP_HOST', 'smtp.example.com' );)。設定の手順やプラグインを使う方法は「WordPressのメールをSMTP送信に変更する方法」で説明しています。
送信を試す
WP-CLI が使える環境では、次のコマンドで wp_mail() を1回だけ実行し、戻り値を確かめられます。
wp eval 'var_dump( wp_mail( "you@example.com", "Test", "wp_mail test" ) );'
bool(true) が表示されても届かない場合は、迷惑メールフォルダー、送信元アドレスのドメインと SPF の設定を確認します。調べ方は「WordPress の確認メールが届かないときの対処法」で説明しています。
注意点
- メールマガジンのような大量の送信には向きません。1通ごとに送信処理が走るため時間がかかり、サーバーの送信数の上限にかかることもあります。大量送信は、メール配信サービスを使います。
- 利用者が入力した値を件名や本文に入れるときは、HTML メールなら
esc_html()でエスケープします。ヘッダーには、利用者が入力した値をそのまま入れないようにします。 wp_mail()はpluggable.phpで定義された関数で、プラグインが丸ごと置き換えることがあります。SMTP 系のプラグインを入れている場合は、この記事のフックの動きがプラグインの設定に左右されることがあります。
まとめ
wp_mail( $to, $subject, $message, $headers, $attachments, $embeds )で送り、戻り値のtrueは「送信処理が成功した」だけを示す- 直接書かず、フックの中で呼ぶ
- HTML メールは
Content-Type: text/html; charset=UTF-8ヘッダーで、送るメールごとに指定する - 失敗は
wp_mail_failedでログに残し、ステージングではpre_wp_mailで送信を止める - 届きにくい場合は
phpmailer_initで SMTP から送る