Contact Form 7 で NG ワードと「ひらがなが入っているか」でスパムを弾く(必須の欄は textarea* にも付ける)

WordPress 6.4.3
広告WordPress・PHP を学べる本

Amazonのアソシエイトとして、WordPress functions.phpは適格販売により収入を得ています。

概要説明

Contact Form 7 のお問い合わせフォームで、本文に NG ワードがあるときや、ひらがなが 1 文字もない英語だけの営業メールを送信できないようにする functions.php のコード。必須の欄は wpcf7_validate_textarea* にも付けないと動かない点と、コードを書かない方法も。

コード:本文(your-message)の欄をチェックする

お問い合わせフォームに届く、英語だけの営業メールや決まった言葉の入ったスパムを、Contact Form 7 の入力チェックで弾く方法です。本文(your-message)に NG ワードが入っているとき、またはひらがなが 1 文字もないときに、送信できないようにします。

functions.php
/*----------------------------------------------------
 Contact Form 7:NG ワードと、ひらがなが入っているかでスパムを弾く
----------------------------------------------------*/
if ( ! function_exists( 'fs_wpcf7_spam_check' ) ) {
	function fs_wpcf7_spam_check( $result, $tag ) {
		if ( 'your-message' !== $tag->name ) {
			return $result; // 本文(your-message)だけを見る
		}
		$text = isset( $_POST[ $tag->name ] ) ? wp_unslash( (string) $_POST[ $tag->name ] ) : '';
		if ( '' === trim( $text ) ) {
			return $result; // 空のときは「必須」の判定に任せる
		}

		// NG ワードが入っていたら弾く(大文字・小文字は区別しない)
		$ngwords = array( '禁止ワード', 'NGワード' );
		foreach ( $ngwords as $word ) {
			if ( false !== mb_stripos( $text, $word ) ) {
				$result->invalidate( $tag, '送信できません。' );
				return $result;
			}
		}

		// ひらがなが 1 文字もなければ弾く(英語だけの営業・スパムの対策)
		if ( ! preg_match( '/[ぁ-ん]/u', $text ) ) {
			$result->invalidate( $tag, '日本語で入力してください。' );
		}
		return $result;
	}
	// 必須(textarea*)と必須でない(textarea)は別のフィルターなので、両方に付ける
	add_filter( 'wpcf7_validate_textarea', 'fs_wpcf7_spam_check', 20, 2 );
	add_filter( 'wpcf7_validate_textarea*', 'fs_wpcf7_spam_check', 20, 2 );
}
  • $ngwords に、弾きたい言葉を足していきます。大文字・小文字は区別しません。
  • 本文の欄の名前が your-message でないときは、'your-message' をフォームの欄の名前に変えてください(フォームの [textarea* your-message] の部分)。
  • ひらがなの判定は、英語だけの文を弾くためのものです。英語のお問い合わせも受けるサイトでは、この部分を外してください。

必須の欄(textarea*)にも付ける

Contact Form 7 の入力チェックのフィルターは、欄の種類ごとに名前が違います。必須の本文の欄([textarea* your-message])は wpcf7_validate_textarea* で、必須でない欄([textarea your-message])は wpcf7_validate_textarea です。

以前この記事に載せていたコードは wpcf7_validate_textarea にしか付けていなかったので、本文を必須にしている多くのフォームではチェックが動いていませんでした。上のコードは両方に付けています。

前のコードから直したところ

  • wpcf7_validate_textarea* にも付けた(必須の欄で動くように)。
  • エラーは $result->invalidate( $tag, 'メッセージ' ) で伝える(Contact Form 7 の今の書き方)。
  • $_POST の値は wp_unslash() してから見る。
  • 本文の欄だけを見るようにした(ほかのテキストエリアの欄には効かない)。
  • 空のときは何もしない(「必須」のチェックに任せる)。

確認した結果

作業環境(WordPress 7.1・Contact Form 7 6.2.1)で、本文を必須にしたフォームに 3 通り送りました。

本文 前のコード 上のコード
英語だけ(Hello, we offer SEO services…) 弾かれない 「日本語で入力してください。」で送信できない
日本語(お見積りをお願いします。) 通る 通る
NG ワードを含む 弾かれない 「送信できません。」で送信できない

コードを書かずにできること

  • WordPress の「コメント禁止キー」:設定 → ディスカッション の「コメント禁止キー」に書いた言葉は、Contact Form 7 でもスパムとして扱われます(送信はスパムとして失敗します)。NG ワードだけなら、コードを書かずにこちらでも足ります。
  • reCAPTCHA:Contact Form 7 の「インテグレーション」で reCAPTCHA(v3)を設定すると、ボットからの送信を減らせます。

入力チェックで弾くと、画面に理由が出ます。スパムを送る側に「どの言葉で弾かれたか」を知られたくないときは、NG ワードは「コメント禁止キー」に追加して、スパムとして扱うほうがよいです。

参考

Contact Form 7 で NG ワードと「ひらがなが入っているか」でスパムを弾く(必須の欄は textarea* にも付ける)