メール・運用NOTE 19 / OPERATION

お問い合わせフォームのスパム・セキュリティ対策|最低限やるべきこと

フォームのスパム対策とセキュリティ対策を分けて整理。サーバー側の入力検証、出力時のエスケープ、CSRF対策、添付ファイルや公開前の確認事項を解説します。

お問い合わせフォームを公開すると、実際のユーザーだけが利用するとは限りません。大量の営業メールや意味のない文字列が送られてきたり、ボットによる自動送信が繰り返されたりすることがあります。また、フォームは外部からデータを受け取る仕組みなので、入力値の扱いやファイル添付の実装によっては、スパムとは別のセキュリティ上の問題にも注意しなければなりません。

結論からいうと、お問い合わせフォームでは「スパムを減らす対策」と「安全に入力データを扱う対策」を分けて考えることが重要です。サーバー側での入力チェック、出力時のエスケープ、連続送信の制限、必要に応じたボット対策、CSRFへの配慮、ファイル添付の制限などを組み合わせます。

この記事では、PHPのお問い合わせフォームを想定し、Webデザイナーが最低限知っておきたいスパム・セキュリティ対策を整理します。セキュリティを過剰に難しく考えるのではなく、「ユーザーから送られてくるデータはそのまま信用しない」という基本から理解していきましょう。

お問い合わせフォームのスパム対策とセキュリティ対策は別物として考える

お問い合わせフォームで迷惑な送信が増えると、「セキュリティが破られた」と感じることがあります。しかし、営業メッセージやボットによる大量送信と、Webサイトの脆弱性を悪用する攻撃は同じものではありません。スパム対策は不要な送信を減らすための対策であり、セキュリティ対策は不正な入力やリクエストによってシステムへ悪影響が出ないようにするための対策です。

たとえば、短時間に何十件も送信されるスパムにはレート制限やボット対策が有効です。一方、フォームへ入力された文字列を確認画面へそのまま出力することによる問題は、出力処理を安全にすることで防ぎます。ファイル添付を許可するなら、拡張子や容量、ファイルタイプなど別の対策も必要です。

一つの対策ですべてを防ごうとするのではなく、「何から守りたいのか」を整理することが重要です。お問い合わせフォームでは、正常なユーザーが使いやすい状態を維持しながら、不正な送信や想定外のデータをサーバー側で適切に拒否できる設計を目指します。

お問い合わせフォームでは入力値をサーバー側でも必ずチェックする

お問い合わせフォームの安全性を考えるうえで基本になるのが、入力されたデータをそのまま信用しないことです。HTMLにはrequiredやtype="email"などの入力補助がありますが、ブラウザー上のチェックだけでサーバーへ送られる値を完全に制御できるわけではありません。PHP側でも、必須項目、形式、文字数、選択肢などを確認します。

HTMLの入力チェックとPHPの入力チェックは役割が違う

HTMLやJavaScriptによる入力チェックは、ユーザーが入力ミスへすぐ気づけるようにするためのものです。「メールアドレスを入力してください」「文字数が多すぎます」とその場で表示できれば、フォームを使いやすくできます。

一方、PHP側では実際にサーバーへ送信された値を確認します。ブラウザー側でエラーが出ないことを前提にせず、サーバー側でも必要な条件を満たしているか判断してから確認画面やメール送信へ進めます。

必須・形式・文字数・選択肢を確認する

入力チェックでは、フォームの用途に応じて条件を設定します。単純に「値が入っているか」だけでなく、その項目として妥当な値なのかを見ることが大切です。

一般的には次のような項目を確認します。

  • 必須項目が空になっていないか
  • メールアドレスなどの形式が妥当か
  • 想定以上に長い文字列ではないか
  • 選択項目が用意された値の中にあるか
  • 必要な同意項目が選択されているか

PHPでは、たとえばメールアドレスについてfilter_var()を使って形式を確認できます。文字数制限を設ける場合も、ブラウザー側だけでなくサーバー側でチェックします。

<?php
$email = trim($_POST['email'] ?? '');
$message = trim($_POST['message'] ?? '');

$errors = [];

if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    $errors[] = 'メールアドレスの形式を確認してください。';
}

if ($message === '') {
    $errors[] = 'お問い合わせ内容を入力してください。';
}

if (mb_strlen($message) > 3000) {
    $errors[] = 'お問い合わせ内容は3000文字以内で入力してください。';
}
?>

入力チェックを厳しくしすぎれば、正常なユーザーまで送信できなくなることがあります。用途に必要な範囲で条件を決め、想定している入力例を使ってテストしましょう。

サーバー側で入力を検証する考え方は、フォームだけでなくユーザー入力を受け付けるWebアプリケーション全般の基本です。

想定していない値は受け付けない

ラジオボタンやセレクトボックスでは、HTMLに表示されている選択肢だけが送られてくるとは限りません。サーバー側では、受け取った値が事前に定義した選択肢の中に存在するか確認する方法があります。

「ブラウザーに表示していないから送られてこない」と考えず、PHP側で受け取った値を基準に判断します。フォーム項目を追加・変更したときは、入力画面だけでなくサーバー側の許可値も合わせて更新しましょう。

確認画面へ入力内容を表示するときは出力時のエスケープを行う

お問い合わせフォームでは、入力された内容を確認画面へ表示することがあります。このとき、ユーザーが入力した文字列をそのままHTMLとして出力しないことが重要です。HTMLとして意味を持つ文字が含まれている場合、意図しない形でページへ解釈される可能性があるためです。

PHPでは表示する場所に合わせて値を処理する

HTML本文へ文字列として表示する場合には、htmlspecialchars()などを使ってHTMLとして解釈されない形へ変換します。これは入力値そのものを変更するためではなく、「HTML上へどのように安全に表示するか」という出力時の処理です。

たとえば確認画面では次のように記述できます。

<p>
<?= htmlspecialchars($message, ENT_QUOTES, 'UTF-8') ?>
</p>

入力チェックとエスケープは同じ処理ではない

メールアドレスの形式を検証したからといって、HTMLへ安全に表示できるようになるわけではありません。逆に、htmlspecialchars()を使用したからといって、その値が正しいメールアドレスになるわけでもありません。

それぞれの役割を整理すると次のようになります。

  • 入力チェック:受け取った値が想定した内容か確認する
  • 出力時の処理:表示先に合わせて安全な形で出力する
  • メール送信処理:メールとして利用する値を適切に扱う

ユーザー入力を一度「安全な文字列」に変換すれば、どこでもそのまま使えるわけではありません。HTML、メールヘッダー、URLなど、値を利用する場所によって必要な処理が異なります。

特にWeb制作案件では、入力値を確認画面、管理者通知、自動返信など複数の場所で使用します。それぞれの用途に合わせて扱うことが大切です。

確認画面だけでなくエラー時の再表示にも注意する

入力エラーが発生したときに、入力済みの値をフォームへ戻すことがあります。この場合も、HTMLのvalue属性やtextarea内へユーザー入力をそのまま出力しないようにします。

正常時だけでなく、「入力エラーで戻ったとき」「確認画面から修正するとき」など、入力値を再表示するすべての経路を確認しましょう。

お問い合わせフォームのスパム対策は複数の方法を組み合わせる

スパム対策では、一つの仕組みだけですべての迷惑送信を止めることは難しいため、サイトの状況に応じて複数の方法を組み合わせます。送信回数を制限する、ボットが入力しやすい隠し項目を利用する、必要なら外部のボット判定サービスを使うなど、方法にはそれぞれ特徴があります。

短時間の連続送信を制限する

通常のユーザーが数秒間に何十回も同じお問い合わせフォームを送ることは多くありません。そのため、一定時間内に大量の送信が繰り返される場合に制限する仕組みは、単純な自動送信への対策になります。

ただし、同じIPアドレスを複数人が共有している場合などもあるため、「同じIPなら永久に送信禁止」のような極端な制限は避けます。時間や回数を適切に設定し、正常なユーザーまでブロックしないようにします。

ハニーポットは目立たないスパム対策として使える

ハニーポットは、一般ユーザーには入力させない項目をフォーム内に用意し、自動ボットがその項目まで入力した場合に送信を拒否する方法です。ユーザーに追加操作を求めないため、フォームの見た目や入力体験を大きく変えずに導入できます。

スパム対策として検討できる方法には、たとえば次のようなものがあります。

  • 短時間の連続送信を制限する
  • ハニーポットを利用する
  • 送信までの時間など不自然な挙動を判定する
  • 必要に応じてボット判定サービスを利用する
  • 明らかな大量送信をログから検知する

ハニーポットだけですべてのボットを防げるわけではありません。仕組みを認識する高度なボットも存在するため、スパム量が多い場合は別の対策と組み合わせます。

また、スパム対策を強くしすぎると、実際のユーザーが問い合わせできなくなる可能性があります。導入後も誤判定が発生していないか確認しましょう。

CAPTCHAなどを導入する場合は使いやすさも考える

スパムが多いサイトでは、人間と自動プログラムを判定するサービスを利用する方法もあります。ただし、追加の認証操作が必要になる方式では、ユーザーの入力負担が増えることがあります。

「スパム対策を入れること」自体を目的にせず、実際のスパム量と正常ユーザーへの影響を見ながら導入を判断します。小規模サイトでスパムがほとんどない段階から複雑な仕組みを大量に追加する必要はありません。

CSRF対策はスパム対策ではなく意図しないリクエストへの防御として考える

お問い合わせフォームのセキュリティを調べると「CSRF対策」という言葉を見かけることがあります。CSRFは、ユーザーのブラウザーを利用して、本来意図していないリクエストを別のサイトから送らせる攻撃です。セッションやCookieを使って状態を管理するフォームや、何らかの状態変更を伴う処理では、フォームの構成に応じて対策を検討します。

CSRFトークンを利用する方法がある

一般的な対策の一つとして、サーバー側でランダムなトークンを生成し、フォームへ埋め込み、送信されたトークンとサーバー側の値が一致するか確認する方法があります。

PHPのセッションを利用する簡単な考え方は次のようになります。

<?php
session_start();

if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
?>

<form method="post" action="confirm.php">
<input
type="hidden"
name="csrf_token"
value="<?= htmlspecialchars($_SESSION['csrf_token'], ENT_QUOTES, 'UTF-8') ?>"
>
</form>

送信されたトークンをサーバー側で検証する

フォームから送信されたトークンを、セッションに保存した値と比較します。一致しない場合は、通常のフォーム操作ではない可能性があるため処理を進めません。

対策を考えるうえでは次の点を意識します。

  • トークンは十分に予測しにくい値として生成する
  • サーバー側で値を検証する
  • 重要な状態変更をGETリクエストで行わない
  • セッションやCookieの設定も合わせて確認する

ただし、CSRFトークンはスパムボットを見分ける仕組みではありません。「CSRFトークンを入れたからスパム対策も完了」と考えないようにしましょう。

セキュリティ機能にはそれぞれ目的があります。入力検証、スパム対策、CSRF対策を一つの機能として扱わず、何を防ぐためのものなのか理解して利用します。

フォームの構成に合わせた対策を選ぶ

ログイン機能を持つ大規模なWebアプリケーションと、一般公開されたシンプルなお問い合わせフォームではリスクや必要な仕組みが異なります。フォームがセッションをどのように利用しているか、どんな処理を実行するかを確認したうえで必要な対策を設計します。

インターネットで見つけたセキュリティ処理を理由もわからず大量に追加するより、それぞれの目的を理解して実装することが重要です。

ファイル添付があるお問い合わせフォームではアップロード処理を厳しく制限する

採用フォームの履歴書や、お問い合わせフォームの参考画像などを受け付ける場合は、通常の文字入力とは別にファイルアップロードの対策が必要です。ファイルは文字列より扱う範囲が広く、不正な形式や極端に大きなデータを受け付けないようにします。

拡張子だけを信用しない

ファイル名が.jpgだから安全な画像だと判断するのは十分ではありません。ファイル名やブラウザーから送られる情報だけではなく、サーバー側でも想定したファイルタイプなのか確認します。

必要な業務に使う形式だけを許可し、それ以外は受け付けない方式が基本です。たとえば履歴書の受付なら、必要もない実行形式まで許可する理由はありません。

容量・件数・ファイル形式を限定する

ファイル添付では、何でも無制限にアップロードできる状態を避けます。業務に必要な範囲を決めて、サーバー側で制限します。

確認したい項目として次のようなものがあります。

  • 許可するファイル形式
  • 1ファイルあたりの最大容量
  • 一度に添付できるファイル数
  • 実際のファイルタイプ
  • 保存する場合のファイル名と保存場所

特にユーザーが指定したファイル名をそのままサーバー上の保存名として利用する設計は避け、保存が必要な場合はアプリケーション側で管理できる名前へ変更する方法を検討します。

FreelanceFormでも用途によってファイル添付の有無や対応形式が異なります。標準で利用できる機能についてはPHPお問い合わせフォームの機能一覧から確認してください。

不要になった一時ファイルを残さない

確認画面を挟むフォームでは、送信完了まで一時的にファイルを保存する構成があります。その場合、送信を途中でやめたファイルや送信完了後の一時データが残り続けないよう、削除する仕組みも必要です。

アップロードできることだけでなく、「どこに保存されるのか」「いつ削除されるのか」まで含めて設計しましょう。

公開前にはメール設定・HTTPS・エラー表示・認証情報まで確認する

お問い合わせフォームのセキュリティはPHPコードだけでは決まりません。サイトがHTTPSで公開されているか、SMTPの認証情報が公開されていないか、PHPの詳細なエラーが一般ユーザーへ表示されていないかなど、運用環境も確認する必要があります。

フォームをHTTPSで利用する

お問い合わせフォームでは、名前、メールアドレス、電話番号などユーザー情報を送信することがあります。公開サイトではHTTPSを利用し、ブラウザーとサーバー間の通信を暗号化できる状態にします。

現在のWebサイト制作ではフォームだけをHTTPSにするのではなく、サイト全体をHTTPSで提供する構成が一般的です。SSL/TLS証明書が正常に設定されているか公開前に確認しましょう。

SMTPなどの秘密情報を公開しない

SMTPのパスワードやAPIキーなどの認証情報は、ブラウザーから読めるHTMLやJavaScriptへ記述しません。また、GitHubなどの公開リポジトリへ誤ってアップロードしないよう注意します。

公開前には次の項目を確認しておくと安心です。

  • SMTPの認証情報が公開領域へ露出していない
  • 本番環境でPHPの詳細なエラーを一般公開していない
  • HTTPSでフォームを利用できる
  • 管理者通知と自動返信が正常に届く
  • 不要なテストファイルや設定ファイルが残っていない

制作中はエラー原因を確認するため詳細情報が必要ですが、本番サイトでは内部のパスや設定値を不必要に画面へ表示しないようにします。

また、クライアントへ納品するときは、どのメールアカウントやサーバー設定を使用しているのかも整理して引き継ぎます。制作担当者しかわからない状態を残さないことも運用上重要です。

正常系だけでなく異常系をテストする

公開前のテストでは、正しい情報を入力してメールが届くことだけを確認して終わらせないようにします。入力欄を空にする、長い文章を入力する、不正なメールアドレスを入れる、確認画面から戻るなど、想定外の操作も試します。

サーバーやSMTPの準備を含めた導入の流れについては、FreelanceFormの導入方法でも確認できます。

提言:フォームのセキュリティは「絶対安全」を目指すより基本を重ねよう

セキュリティという言葉を見ると、駆け出しWebデザイナーには急に専門外の世界へ感じられるかもしれません。しかし、お問い合わせフォームで最初に重要なのは、難しい技術を大量に追加することではありません。ユーザー入力を信用しすぎない、サーバー側で確認する、表示時に適切に処理する、秘密情報を公開しない、といった基本を一つずつ積み重ねることです。

また、スパム対策とセキュリティ対策を分けて理解することも大切です。ボットを減らすための仕組みと、入力値を安全に扱う仕組みでは目的が違います。ファイル添付があるなら追加の制限が必要になるように、フォームの機能が増えれば確認項目も増えていきます。

FreelanceFormは、WebデザイナーがPHPの送信処理を毎回ゼロから構築するのではなく、用意されたフォームを案件に合わせて導入・カスタマイズすることを想定しています。フォーム制作の負担を抑えながら必要な仕組みを理解したい方は、FreelanceFormの特徴・強みも参考にしてください。

お問い合わせフォームのスパム・セキュリティ対策に関するよくある質問

お問い合わせフォームにCAPTCHAは必ず必要ですか?

必須ではありません。スパムの量が少なければ、連続送信の制限やハニーポットなど、ユーザーへ追加操作を求めない方法から検討することもできます。

ボットによるスパムが多い場合にはCAPTCHAなどの導入を検討しますが、正常なユーザーの入力負担とのバランスも考えましょう。一つの対策ですべてを防ごうとせず、状況に応じて組み合わせます。

HTMLのrequiredを設定すればPHP側の入力チェックは不要ですか?

不要にはなりません。requiredなどのHTML属性はユーザーの入力を助けるために便利ですが、サーバーへ送信された値についてはPHP側でも確認します。

必須、形式、文字数、選択肢など、フォームの仕様に合わせてサーバー側で検証してください。ブラウザー側とサーバー側のチェックは、それぞれ異なる役割を持っています。

CSRFトークンを入れればスパムメールも防げますか?

CSRFトークンは、主に意図しない外部サイトからのリクエストを防ぐための仕組みであり、一般的なスパムボットを判定するための機能ではありません。正規のフォーム画面を取得して送信するボットなら、トークン付きで送信できる場合もあります。

スパム対策には、連続送信制限、ハニーポット、必要に応じたボット対策サービスなど、別の仕組みを検討します。目的の異なる対策を混同しないことが重要です。

お問い合わせフォームでファイル添付を使うと危険ですか?

ファイル添付そのものが危険なのではなく、何でも無制限に受け付ける実装に注意が必要です。必要なファイル形式だけを許可し、容量、件数、ファイルタイプなどをサーバー側で確認します。

保存する場合は保存先やファイル名、一時ファイルの削除も考えます。採用フォームでPDFだけを受け付けるなど、業務に必要な範囲へ絞ると管理しやすくなります。

お問い合わせフォームを公開する前に最低限何をテストすればいいですか?

正常な送信だけでなく、必須項目の未入力、不正なメールアドレス、長い文字列、確認画面からの修正、連続送信なども試します。ファイル添付がある場合は、許可していない形式や容量超過の動作も確認します。

さらに本番サーバーで管理者通知と自動返信を実際に受信し、HTTPS、SMTP設定、エラー表示、秘密情報の配置なども確認してから公開しましょう。

まとめ:スパム対策と安全な入力処理を一つずつ積み重ねる

お問い合わせフォームでは、サーバー側の入力チェック、出力時の適切な処理、連続送信への対策、必要に応じたボット対策、CSRFへの配慮、ファイル添付の制限など、複数の観点から安全性を考えます。すべてを一つの「セキュリティ機能」で解決できるわけではなく、それぞれ守る対象が異なります。

重要なのは高度な仕組みを闇雲に増やすことではありません。ユーザーから届く値をそのまま信用しない、秘密情報を公開しない、必要以上のファイルを受け付けない、本番環境で異常系までテストする。こうした基本を積み重ねることで、Webデザイナーでもお問い合わせフォームの安全性を意識した制作ができるようになります。

ファイルを受け付ける案件では、添付フォームの容量・形式・一時保存の確認事項も参照してください。PDFや画像の受信まで含めたテスト例をまとめています。

THANKS FOR READING.ページの先頭へ
YOUR NEXT STEPFROM KNOWING TO MAKING. ↗

学んだことを、
次の制作案件へ。

フォームの土台があれば、デザインにもっと向き合える。HTML・CSSで編集できる、買い切りのお問い合わせフォーム。

FreelanceFormを見てみる HTML・CSSで編集 / 10デザイン / 買い切り