WordPress で問合せフォームを設置する時に使用する定番プラグインと言えば、「Contact Form 7」。簡単な設定だけですぐにフォームが設置できるものの、何も対策をせずに放置していてスパムが来るようになり頭を抱えている人もいるのではないかと思います。もし今大丈夫でも、ある日突然スパムが来るようになる可能性が高いので今のうちから対策しておきましょう。
ここで紹介する対策は、メールの本文に日本語が含まれていない場合はエラーを返しメール送信できないようにするというものです。WordPress 5.4 で動作確認済み。もし英語のメールを受け取ることを想定しているような場合は、最後に紹介する「Contact Form 7」の「クイズ」機能を使った方法を試してください。
コンテンツ
日本語/全角の割合をチェック(厳しめ)
日本語が含まれていない場合にエラーを返す方法については、いくつかのサイトで紹介されていますが、それらは日本語が1文字以上入ってさえいれば送信できてしまうものが多いため、ここでは日本語/全角文字が全体の文字数に対して特定の割合以上含まれているかどうかチェックするという少し厳しめのバリデーションを紹介します。
各コードの$field_name = 'your-message';の部分は、利用しているフォームのチェックしたいフィールド名に変更してください。
日本語が指定の割合以上含まれているかチェック
下記の例では、正規表現で指定したぁ-んァ-ヶー一-龠0-9、。のとおり、「ひらがな」「カタカナ」「漢字」「全角数字」「、」「。」にマッチする文字が全体の50%未満の場合はエラーを返すようにしています。
50% ルールは、ルー大柴(古っ)みたいに、チョイチョイ英単語を混ぜるような人でない限りまずはエラーにはなりませんが、心配であれば$min_rate = 30;(30%)などに下げておいても良いでしょう。
functions.php
function wpcf7_validate_mb_char( $result, $tag ) {
$field_name = 'your-message'; //チェックしたいフォームフィールド名
$value = str_replace(array("\r", "\n", ' ', ' '), '', $_POST[$field_name]); //改行とスペースを取り除く
$min_rate = 50; //(%)最小日本語文字数の割合(これ以上でなければエラー)
$str_l = mb_strlen($value , "UTF-8"); // 文字数取得(ダブルクオーテーション必須)
$str_ja = preg_match_all("/[ぁ-んァ-ヶー一-龠0-9、。]/u", $value, $matches); //日本語の文字数を取得
$str_mb_rate = ($str_ja / $str_l) * 100; // 日本語文字数の割合を計算
if (!empty($value)) {
if ($str_mb_rate < $min_rate) {
$result['valid'] = false;
$result['reason'] = array($field_name => '日本語以外の言語が多く含まれています');
}
}
return $result;
}
add_filter( 'wpcf7_validate', 'wpcf7_validate_mb_char', 10, 2 );
全角文字が特定の割合以上含まれているかチェック
これは日本語かどうかではなく、全角かどうかのチェックです。
mb_strwidth 関数は、半角を1、全角を2とした文字列の幅を返し、mb_strlen 関数は、半角全角に関係なく文字数を返すため、mb_strwidth - mb_strlenで全角の文字数を取得することができます。
ただし、mb_strwidth 関数は韓国語や中国語も全角として扱うということ、また一部の日本語記号を半角として扱う特徴があります。より厳密に日本語だけに限定したい場合は上のコードを使いましょう。
functions.php
function wpcf7_validate_mb_char( $result, $tag ) {
$field_name = 'your-message'; //チェックしたいフォームフィールド名
$value = str_replace(array("\r", "\n", ' ', ' '), '', $_POST[$field_name]); //改行とスペースを取り除く
$min_rate = 50; //(%)最小日本語文字数の割合(これ以上でなければエラー)
$str_l = mb_strlen($value , "UTF-8"); // 文字数取得(ダブルクオーテーション必須)
$str_w = mb_strwidth($value, "UTF-8"); // 文字幅(半角1、全角2でカウント)
$str_mb = $str_w - $str_l; // 日本語(マルチバイト)の文字数取得
$str_mb_rate = ($str_mb / $str_l) * 100; // 日本語文字数の割合を計算
if (!empty($value)) {
if ($str_mb_rate < $min_rate) {
$result['valid'] = false;
$result['reason'] = array($field_name => '日本語の割合が少ない' . $str_mb_rate . '/' . $min_rate);
}
}
return $result;
}
add_filter( 'wpcf7_validate', 'wpcf7_validate_mb_char', 10, 2 );
日本語/全角が含まれるかチェック(緩め)
一応参考までに、他サイトで紹介されているような方法も紹介しておきます。これは文字数の割合はチェックしていないため、たとえ1文字だけでもバリデーションを通過する文字列が含まれれば送信できてしまいます。しかし通常はこれで十分だと思います。
ひらがなが含まれているかチェック
正規表現で、ひらがなが1文字以上含まれているかどうかチェックし、なければエラーを返します。
functions.php
function wpcf7_validate_mb_char( $result, $tag ) {
$field_name = 'your-message'; //チェックしたいフォームフィールド名
$value = str_replace(array("\r", "\n", ' ', ' '), '', $_POST[$field_name]); //改行とスペースを取り除く
if (!empty($value)) {
if (!preg_match('/[ぁ-ん]/u', $value)) {
$result['valid'] = false;
$result['reason'] = array($field_name => '日本語でお願いします');
}
}
return $result;
}
add_filter( 'wpcf7_validate', 'wpcf7_validate_mb_char', 10, 2 );
半角英数字のみかどうかチェック
半角英数字のみだった場合はエラーを返します。半角英数字以外の文字列が1文字でも含まれていれば許可されるため、この中では一番緩いバリデーションとなります。
functions.php
function wpcf7_validate_mb_char( $result, $tag ) {
$field_name = 'your-message'; //チェックしたいフォームフィールド名
$value = str_replace(array("\r", "\n", ' ', ' '), '', $_POST[$field_name]); //改行とスペースを取り除く
if (!empty($value)) {
if (preg_match('/^[!-~]+$/', $value)) {
$result['valid'] = false;
$result['reason'] = array($field_name => '日本語でお願いします');
}
}
return $result;
}
add_filter( 'wpcf7_validate', 'wpcf7_validate_mb_char', 10, 2 );
Contact Form 7 のクイズ機能を使う
「Contact Form 7」の「クイズ」機能を使用することで、スパム対策を実現できます。
特別なコードを追加する必要ないため、比較的簡単に導入できるものの、実は今回紹介した対策法の中では一番強力なスパム対策になり得ます。
フォーム追加の画面で「クイズ」をクリックすると、クイズ設定画面が表示されますので、質問と答えを半角パイプ(|)で分けて登録します(例:質問|答え)。改行して複数登録しておくと、その内の1つが毎回ランダムで表示されます。
英語のメールを受け取る可能性がある場合など、送信者の使用言語に関係なくスパム対策したい場合は、下記などのクイズを設定すると良いでしょう。
10+5=|15
3x3=|9
100-50=|50
今回紹介した方法以外にもっと画期的な方法などあれば是非コメント欄で教えてください。