Copicode 日本語トップ

ロリポップのPHPメールフォームにスパム投稿が来る時のTurnstile確認順番

久しぶりにロリポップのWebメーラーを開いたら、問い合わせフォーム経由らしきスパムメールが大量に届いていた。そんな時は、メール本文や送信処理だけでなく、フォーム送信前の確認を入れると被害を減らしやすくなります。

この記事では、無料で使えるCloudflare TurnstileをPHPメールフォームへ入れる時の考え方を、ロリポップで運用している小さなサイト向けに整理します。

確認日と対象

確認日: 2026年5月19日。ロリポップで自作PHPメールフォームを運用していて、海外スパム、URLだらけの投稿、短時間の連投が届く人向けです。

WordPressプラグイン固有の設定、Cloudflare WAF全体の設計、大量配信システムは対象外です。まずフォームにTurnstileを表示し、PHP側でトークン検証してからメール送信へ進む形にします。

Turnstileを入れる流れ

site keyでフォームに表示し、送信されたトークンをPHP側でsecret keyと一緒に検証してからメール送信へ進みます。

Cloudflare TurnstileをPHPメールフォームに導入する時にsite key、secret key、HTML表示、PHP側検証、送信処理、追加スパム対策を順番に確認する図解
大事な注意: secret key はPHP側だけで使います。HTMLやJavaScriptに書いて公開しないでください。

Cloudflare Turnstileでできること

Cloudflare Turnstileは、問い合わせフォームなどに設置できるスパム・自動投稿対策です。reCAPTCHAの代わりとして使われることもあり、フォームにウィジェットを表示し、送信時に発行されたトークンをPHP側で検証します。

公式ドキュメントでも、クライアント側の表示だけでなくサーバー側の検証が必要と説明されています。検証先は https://challenges.cloudflare.com/turnstile/v0/siteverify です。

実際に見る順番

Turnstileは「フォームに表示しただけ」では不十分です。スパムを止めたい場合は、PHP側の検証結果でメール送信を止めるところまで確認します。

順番見る場所分かること
1スパム投稿の内容URL連投、英語だけ、短時間連投などの傾向
2Cloudflareのsite keyフォーム表示用のキーが正しいか
3Cloudflareのsecret keyPHP側だけで使う秘密キーがあるか
4HTMLフォームcf-turnstile が送信ボタン前に表示されるか
5POSTされたトークンcf-turnstile-response がPHPへ届いているか
6Siteverify APIの結果success がtrueの時だけ送信しているか
7ログと追加対策失敗理由、honeypot、URL数、連投制限を見られるか

発行するキー

キー使う場所注意
site key HTMLフォーム側 公開されてもよいキー。ウィジェット表示に使う
secret key PHP側 絶対に公開しない。Cloudflareへ検証リクエストを送る時に使う

HTMLフォームにTurnstileを表示する

フォームの送信ボタン付近にTurnstileの表示エリアを置きます。YOUR_SITE_KEY はCloudflareで発行したsite keyに置き換えます。

<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>

<form action="/contact-submit.php" method="post">
  <label>お名前</label>
  <input type="text" name="name" required>

  <label>メールアドレス</label>
  <input type="email" name="email">

  <label>お問い合わせ内容</label>
  <textarea name="message" required></textarea>

  <div class="cf-turnstile" data-sitekey="YOUR_SITE_KEY"></div>

  <button type="submit">送信する</button>
</form>

PHP側でsecret keyを使って検証する

Turnstileを表示しただけでは不十分です。送信された cf-turnstile-response をPHP側でCloudflareへ送り、success がtrueか確認してからメール送信処理へ進みます。

<?php
$turnstile_secret = 'YOUR_SECRET_KEY';
$turnstile_token = $_POST['cf-turnstile-response'] ?? '';

$verify_response = file_get_contents(
  'https://challenges.cloudflare.com/turnstile/v0/siteverify',
  false,
  stream_context_create([
    'http' => [
      'method' => 'POST',
      'header' => "Content-Type: application/x-www-form-urlencoded\r\n",
      'content' => http_build_query([
        'secret' => $turnstile_secret,
        'response' => $turnstile_token,
        'remoteip' => $_SERVER['REMOTE_ADDR'] ?? null,
      ]),
      'timeout' => 10,
    ],
  ])
);

$turnstile_result = json_decode($verify_response, true);

if (empty($turnstile_result['success'])) {
  exit('セキュリティ確認に失敗しました。時間をおいて再度お試しください。');
}

// ここから先でメール送信処理を行う
?>

ロリポップで導入する時の注意点

Turnstileだけに頼らない追加対策

スパム投稿は一つの対策だけで完全に止まるとは限りません。フォーム側では、次のような軽い対策も組み合わせると安全寄りになります。

対策内容
honeypot人には見えない入力欄に値が入っていたら拒否する
URL数チェック本文にURLが多すぎる投稿を拒否する
文字数制限極端に短い・長い本文を弾く
連投制限短時間に何度も送信される場合に止める
ヘッダー対策Fromは自分のドメイン、返信先はReply-Toに分ける

うまく動かない時の確認

正常な問い合わせまで止めていないか確認する

Turnstileを入れた後は、スパムが減ったかだけでなく、正常な問い合わせが送信できているかも確認します。送信できたか、失敗したか、どこで止まったかを残す場合は、PHPメールフォームが送信できたか分からない時のログ確認順番も合わせて確認してください。

AIに相談する時のメモ

AIに相談する時は、site keyは貼ってもよいですが、secret keyは貼らないでください。検証結果やエラーコードだけを共有します。

ロリポップのPHPメールフォームにスパム投稿が来るため、Cloudflare Turnstileを入れています。

フォームURL:

起きている症状:
例: Turnstileを入れたのにスパムが届く / 正常送信も失敗する / tokenがPOSTされない

HTML側で確認したこと:
- api.jsを読み込んでいるか:
- cf-turnstileのdivが表示されるか:
- site keyが正しいか:

PHP側で確認したこと:
- cf-turnstile-responseが届いているか:
- siteverifyへPOSTしているか:
- successがtrueの時だけメール送信しているか:
- error-codes:

ログに残した内容:

追加対策:
- honeypot:
- URL数チェック:
- 文字数制限:
- 連投制限:

secret key、管理画面URL、個人情報は伏せています。
初心者向けに、次に見る順番を教えてください。

公式情報で確認するところ

確認したいこと公式情報この記事での使い方
Turnstileの全体手順 Cloudflare公式 Turnstile Get started site key、secret key、フォームへの設置の前提を確認します。
サーバー側検証 Cloudflare公式 Validate the token siteverifysecretresponse、失敗コードの確認に使います。
フォームへの表示 Cloudflare公式 Embed the widget HTML側の cf-turnstile とスクリプト読み込みを確認します。

関連記事