お問い合わせフォームは、壊れていても気づきにくい部品です。
送った人には「送信しました」と出て、サイトの運営者には何も届かない、という壊れ方をします。
この記事では、Snow Monkey Formsのフォームを、REST API経由の送信処理とテスト専用受信箱への到達を定期確認する仕組みを作ります。
reCAPTCHAは外しません。
合言葉を付けた送信だけ、サーバー側で判定を通す形にします。
この記事で分かること
- 通常送信のreCAPTCHAを維持し、認証したテスト送信だけスパム判定を通す考え方
- Snow Monkey Formsのどのフックを使うか
- 送信から、メールが届くまでを確かめるスクリプト
- 週1回の定期実行と、異常のときの知らせ方
- この仕組みを動かした初日に見つかった障害
結論:合言葉つきの送信だけ、スパム判定を通す
Snow Monkey Formsは、送信のたびに snow_monkey_forms/spam/validate というフィルターでスパムかどうかを判定します。
reCAPTCHAの判定も、このフィルターの中で動きます。
ここに自分のフィルターを後から足し、HTTPヘッダーの合言葉が合ったときだけ「通す」と返します。
合言葉は推測を困難にするために、32バイトの乱数を16進数にした64文字を使います。
HTTPSで送り、サーバー側と実行端末で秘密として管理します。
公開コード・ログ・エラー通知には含めないでください。
合言葉がない送信は、今までどおりreCAPTCHAで判定されます。
通常送信のreCAPTCHAは残りますが、テスト送信には判定を通す例外経路を追加します。
対象フォーム・宛先・頻度を限定し、合言葉が漏えいした場合は例外を停止して秘密値を交換できるようにしてください。
| やること | やらないこと |
|---|---|
| 合言葉つきの送信だけ判定を通す | reCAPTCHAのキーを外す |
| フォームごとのDB条件付き更新で10分間隔を制御(実際の並行負荷は未確認) | 判定を全部スキップする |
| テストのメールに印を付ける | 本物の問い合わせと混ぜる |
この方式は、自分が管理するサイトのテスト送信に限って例外を設けるものです。
通常利用者のreCAPTCHAの無効化や自動突破を目的にしません。
例外経路ではreCAPTCHAの通常の判定を確認できません。
通常送信への防御が保たれているかは別に確認する必要があります。
仕組みの全体
| 部品 | 役割 |
|---|---|
| サーバー側(Code SnippetsのPHP) | 合言葉の確認、メールへの印、結果の記録 |
| 手元側(Pythonのスクリプト) | フォームのページを読み、本番と同じ形で送信し、届いたかを確かめる |
| 定期実行 | Windowsのタスクスケジューラ(Macならlaunchd、サーバーならcron) |
| 知らせ | 異常のときだけSlackに投稿(任意) |
送信は、ブラウザのJavaScriptが使っているのと同じREST APIに送ります。
フォームのREST APIへ送信し、トークン・リファラー・必須項目の検査とメール送信を確認する方式です。
ブラウザーのJavaScript操作と、テスト送信で通過させるreCAPTCHAの判定は、この自動テストの確認範囲に含みません。
だから「フォームの画面は出るのにメールが出ない」という壊れ方も見つけられます。
必要なもの
- Snow Monkey Forms(記事の確認は13.0.0)とCode Snippets
- Python 3(requestsを入れる)
- SSH・WP-CLIで送信記録を読む手段と、IMAPでテスト専用受信箱を確認する手段(掲載スクリプトは両方を使用)
- reCAPTCHAを設定済みのフォーム(設定していなければ、この仕組みは要らない)
この仕組みで分かったこと
筆者のサイトで初めて動かした日、テストは「管理者メールの送信に失敗」で止まりました。
原因は、サーバー移転の前に作ったSMTPの設定が、移転前のサーバー名のままだったことです。
フォームの画面は正常に出ていて、問い合わせた人には何も異常が見えません。
運営者にメールが来ないだけなので、自分では気づけませんでした。
設定を直した直後のテストで、2通(管理者宛と自動返信)が24秒で届くことを確かめられました。
確認記録は筆者サイトのSnow Monkey Forms 13.0.0での送信・受信です。
他のフォーム構成やサーバー、ブラウザー操作まで確認したものではありません。
移転後の手動確認はメール確認チェックリストをご覧ください。
旧実装の監査記録:追加の確認範囲:2026年10月12日に掲載7コード枠の全文を静的に確認し、PHPとPythonの構文確認を行いました。
合言葉の比較は hash_equals を使っています。
ただし、掲載のPHP例には対象フォームIDの許可リストがなく、共通の合言葉を持つ送信をフォーム横断で扱います。
頻度制限の読み取りと保存は別処理なので、同時送信時に「10分に1回」が守られるとは限りません。
テスト専用の管理者宛先が未設定・無効の場合は、元の宛先が残ります。
2026年10月13日の改修例は、Snow Monkey Forms 13.0.0公式ZIPのフック引数とサーバー側の Setting::get("form_id") を照合しました。
初期状態ではテスト例外を無効にし、運営者が明示的に有効化・設定したフォームID、64桁の秘密値、HTTPS、テスト専用の宛先と送信元を確認します。
間隔はフォームごとのDB条件付き更新で制限し、失敗送信でも間隔を消費します。
管理者通知・自動返信の宛先を固定し、元の本文・ヘッダー・添付を引き継ぎません。
通知とログにはID・時刻・固定イベントだけを残します。
SSHは絶対パスをシェル用に引用して終了状態を確認し、IMAPは読取専用で管理者通知と自動返信を区別して確認してから接続を終了します。
HTTPとSlackはタイムアウトを設け、リダイレクトしません。
代替DB・HTTP・SSH・IMAP・Slackを使った模擬検証で確認した範囲です。
実WordPress、DB競合、メール配送、SMTPプラグイン、実SSH・IMAP・Slack・スケジュール実行は未確認です。
reCAPTCHA等の例外有効化は安全性に影響するため、運営者の判断で検証用サイトに限定して確認してください。
本サイトへの導入・送信・設定変更はしていません。
以下に掲載するのは改修後の例です。
旧実装に対する指摘と、改修後の確認結果は区別してください。
検証環境での実際のメール配送・受信・定期起動まで確認できた状態を、本番導入の前提にします。
ここから先は、スニペットの全文、送信と確認のスクリプト、定期実行の設定、運用で踏んだ注意点です。
LocalのWordPress・DBで確認した送信制御の範囲
2026年10月13日、新規Local環境のWordPress 7.1.3・PHP 8.1.23・MySQLとSnow Monkey Forms 13.0.0の設定オブジェクトを使い、掲載例のPHP側を24ケース確認しました。
架空フォームを対象にWordPressのフックとDBを実行した確認です。
テスト用の有効化定数・照合値・HTTPSの状態はCLIプロセス内だけに置き、WordPressの設定ファイルや公開フォームへ例外を導入していません。
通常のスパム判定・メール引数を保つこと、未設定・不正な照合値・対象外フォーム・HTTP扱いを拒否することを確認しました。
許可した架空フォームだけを受け付け、管理者通知と自動返信の両方で送信先・本文・ヘッダー・添付を限定すること、宛先違いとBccを拒否することを確認しています。
DBでは599秒以内を拒否し600秒で許可する条件と、古い状態を条件にしたSQLが新しい状態を上書きしないことを確認しました。
失敗記録には許可した項目だけを残しています。
この確認ではメール送信、フォームへのHTTP送信、reCAPTCHAの設定変更、SSH・IMAP・Slack接続、定期実行を行っていません。
実際のSMTP・送信プラグイン・受信箱・外部通知・本番構成・並行負荷は未確認です。
現在のログイン済みChromeでは公開ページの全7コード枠が保存原稿と一致し、PC幅1280px・スマホ幅375pxで表示を確認しました。
購入者の別アカウントも未試験です。
以前の未確認注記は、その時点の記録として残しています。
この記事だけ読みたい方は単品購入、ほかの有料記事も読みたい方は購読プランをご確認ください。
購読対象の記事・料金は、下のプラン案内で確認できます。
役に立った記事を、ブログやSNSで紹介しませんか?
紹介制度の対象記事・購読プランを購入した方は、codocで専用リンクと報酬条件を確認できます。
専用リンク経由で購入されると、設定された紹介報酬が発生します。
購読プランの紹介報酬は初回課金のみが対象です。
紹介時は、広告・PRであることが読者に分かるように明記してください。



