投稿(店舗など)ごとに問い合わせ先メールアドレスがカスタムフィールドに登録されている場合に、1つのContact Form 7フォームで送信先を動的に切り替える方法を紹介します。宛先が大量にあっても、フォームを宛先ごとに用意せず、カスタムフィールドの更新だけで運用できます。ここではオープンリレー(迷惑メールの踏み台)にならない安全な実装を解説します。
- URLの
post-idパラメータで対象投稿を渡す - 送信時に サーバー側でカスタムフィールドから宛先を再取得する
wpcf7_mail_componentsと CF7「メール」タブの設定- クライアントのhidden値を宛先に使ってはいけない理由(セキュリティ)
hiddenフィールドの値はブラウザの開発者ツールで誰でも書き換えられます。その値をそのままメール宛先に使うと、攻撃者が任意のアドレスへ送信できる「オープンリレー」になり、あなたのサーバーが迷惑メールの踏み台にされます。
sanitize_email() は形式を整えるだけで改ざんは防げません。安全にするには、クライアントからは投稿IDだけを受け取り、メールアドレスはサーバー側でカスタムフィールドから取得します。投稿ページのリンクに投稿IDを付ける
各投稿に置くフォームへのリンクに、その投稿のIDを post-id パラメータとして付けます。
<a href="/contact/?post-id=<?php echo get_the_ID(); ?>">お問い合わせフォームへ</a>
フォームに投稿IDのhiddenフィールドを置く
Contact Form 7のフォームに、投稿IDを受け取るhiddenフィールドを追加します。default:get を付けると、URLの post-id パラメータの値が自動で入ります。
[hidden post-id default:get]
旧来よく紹介される「宛先メールアドレスをhiddenに入れて送る」方法は前述のとおり危険です。この実装では運ぶのは投稿IDだけ。投稿IDを改ざんされても、たどり着けるのは実在する投稿に登録済みのアドレスだけで、任意のアドレスは指定できません。
送信時にサーバー側で宛先を再取得する
functions.php に次のコードを追加します。送信時に wpcf7_mail_components フィルターで、送られてきた post-id からカスタムフィールドのメールアドレスを取得し直して宛先に設定します。
function my_cf7_dynamic_recipient($components, $form, $mail) {
$target_form_id = 77; // 対象フォームのIDに置き換えてください
if ($form->id() != $target_form_id) {
return $components;
}
$submission = WPCF7_Submission::get_instance();
if (!$submission) {
return $components;
}
$posted = $submission->get_posted_data();
// クライアントから受け取るのは投稿IDだけ。整数化する
$post_id = isset($posted['post-id']) ? absint($posted['post-id']) : 0;
if (!$post_id) {
return $components;
}
// 宛先は「サーバー側で」カスタムフィールドから取得し直す(hidden値は信用しない)
$email = get_post_meta($post_id, 'contact_mail', true); // 実際のキーに置き換え
// 取得した値が正当なメール形式のときだけ採用
if ($email && is_email($email)) {
$components['recipient'] = $email;
}
return $components;
}
add_filter('wpcf7_mail_components', 'my_cf7_dynamic_recipient', 10, 3);
宛先は
$posted['recipient-email'] のような送信された値からは取りません。post-id を absint() で整数化し、get_post_meta() でサーバー側のデータから取り直し、is_email() で検証してから設定します。これで改ざんされても任意送信を防げます。CF7「メール」タブの設定
上のフィルターで宛先を上書きしますが、CF7の「メール」タブの「送信先」欄にはフォールバック用の管理者メールアドレスを入れておきます。カスタムフィールドが未設定だった場合(フィルターが宛先を上書きしない場合)に、ここに届くので取りこぼしを防げます。フォーム自体のカスタマイズ(class/id付与など)はContact Form 7でformタグにclass・idを設定する方法を参照してください。
関連して、送信できないトラブルの切り分けはContact Form 7で「送信できない」時の原因と解決チェックリスト、送信前に入力内容を加工する方法はユーザーの入力内容を一部加工して送信する方法も参考になります。
よくある質問(FAQ)
sanitize_email() は形式を整えるだけで改ざんは防げません。クライアントからは投稿IDだけを受け取り、宛先はサーバー側で get_post_meta() から取得し直してください。default:get(URLパラメータから)などの初期値オプションが使えます。投稿のカスタムフィールド値を入れたい場合は wpcf7_form_tag フィルターでタグの値を動的に書き換えるか、JavaScriptでページ読み込み後に設定します。wpcf7_mail_components フィルターで $components(recipient・subject・body 等)を条件分岐で書き換えます。宛先を切り替える場合も、送信値を直接使わず、サーバー側で許可された値に解決してから設定するのが安全です。まとめ
- 運ぶのは投稿IDだけ:リンクに
?post-id=、フォームに[hidden post-id default:get] - 宛先はサーバー側で再取得:
wpcf7_mail_componentsでget_post_meta()+is_email() - hidden値を宛先に使わない:改ざんによるオープンリレーを防ぐ
- メールタブ:フォールバック用に管理者アドレスを入れておく
「クライアントからはIDだけ、宛先はサーバー側で確定」を守れば、複数宛先のフォームを安全に1つで運用できます。

