WordPressプラグインThrows SPAM Awayを使ってContact Form 7にIP制限などのバリデーションを追加する方法

`2020/08/11 許可リスト　と　拒否リスト　を利用した判定がわかりにくかったため「拒否リスト」を使った判定で再編集しました。`

## WordPressで使える超ステキなメールフォーム Contact Form 7
すでに超有名ですので私の説明はいらないですね。
[Contact Form 7](https://wordpress.org/plugins/contact-form-7/)

## 公式サイト
[Contact Form 7](http://contactform7.com/ja/)

以前、Throws SPAM Awayを使って mw wp form にスパム対策バリデーションをつけた記事を投稿しました。
[WordPressプラグインThrows SPAM Awayを使ってMW WP FormにNGワード指定などのバリデーションを追加する方法](http://qiita.com/gtijp/items/65bf0af75140fe2774a1)

今回はこれの「Contact Form 7」版を作ってみたいと思います。

で・・・一応 Throws SPAM Away のご紹介
## WordPressのコメントスパム対策プラグインといえば・・・Throws SPAM Away
手前ミソですみません。

Throws SPAM Away というプラグインは「WordPressへの海外からのスパムコメントを排除する」目的で作られた純国産のプラグインで・・・私が作りました。

WordPressプラグインページ
[Throws SPAM Away](https://wordpress.org/plugins/throws-spam-away/)

公式サイト
[Throws SPAM Away](https://gti.co.jp/throws-spam-away)

# この２つを使って作れるメールフォーム用 国内のIPだけに制限するバリデーション
今回のサンプルは Throws SPAM Away バージョン 2.8.1 以降で動作します。

もちろんThrows SPAM Awayの設定どおりバリデーションが効きますのでNGワードやリンクの数、英語のみは弾くなど出来ますが今回は通信内容を書く欄だけチェックしますのでその他の項目にも適用する場合は項目数分functions.phpに追記する必要があります。

前提条件として上述の２つのプラグインをWordPressにインストールして有効化しておいてください。

## Contact Form 7のフックを利用し作成しました。
今回利用したフックの詳細です。

### バリデーションを追加するために利用したフック
wpcf7_validate

これを使ってContact Form 7へ Thows SPAM Awayの機能を利用したバリデーションを追加したサンプルです。

まず、Contact Form 7の方のメールフォームはこんな感じで作ってある前提です。
※Contact Form 7 メールフォーム設定

```
<p>お名前 (必須)<br />
    [text* your-name] </p>

<p>メールアドレス (必須)<br />
    [email* your-email] </p>

<p>題名<br />
    [text your-subject] </p>

<p>メッセージ本文<br />
    [textarea your-message] </p>

<p>[submit "送信"]</p>
```

これに対して利用中テーマのfunctions.phpには下記の通り追記します。
今回は　メッセージ本文　your-message に対してバリデーションをかけますので
コード中の「your-message」はWordPressのコメント同様にバリデーションをかけたい項目の名称に変更してください。

```lang:functions.php
/**
 *  IPアドレスチェック（許可リストチェック・拒否リストチェック）
 *  で引っかかった場合は「不明なエラーで送信できません」と返却し
 *  その他のチェックはそれぞれエラー文言を返却します。
 *  Throws SPAM Awayの設定どおりチェックしますので設定を忘れずに。
 */
function wpcf7_validate_your_message( $result, $tag ) {

 include_once( WP_PLUGIN_DIR.'/throws-spam-away/throws_spam_away.class.php');

        $throwsSpamAway = new ThrowsSpamAway();

        $args = array(
              'post_id' => NULL
            );
        $value = esc_attr( $_POST['your-message'] );

        if ( !empty( $value ) ) {

            // IPアドレスチェック
            $ip = $_SERVER['REMOTE_ADDR'];
            // 許可リスト判定は IPが許可リストに入っていることがOKだった経緯から
            // 入っていることがTRUEで入っていないことがFALSEになっています。
            // そのため、一見ややこしいですが、IPアドレスチェックと合わせるためフラグを反転しています。
            $white_ip_check = !$throwsSpamAway->white_ip_check( $ip );

            // こちらのIPアドレスチェックは拒否リスト判定ですので入っている=FALSEです。
            $chk_ip = $throwsSpamAway->ip_check( $ip );

            /** 許可リスト　と　拒否リスト　で判定する場合、下記のコメントアウトで調整してください。 */

            // 許可リストに入っていない または 拒否リストに入っている 場合はエラーとします。
//            if ( ! $white_ip_check || ! $chk_ip ) {
            // 許可リストに入っていない  場合はエラーとします。
//            if ( ! $white_ip_check ) {
            // 拒否リストに入っている 場合はエラーとします。
            if ( ! $chk_ip ) {

              $result['valid'] = false;
              // エラー文言はなんでもいいのですがIP制限しているのがバレたくない場合は
              // うやむやなエラー文言が良いと思います。
              $result['reason'] = array( 'your-message' => '不明なエラーで送信できません :');
              return $result;
            }

            // IPアドレスチェックを超えた場合は通常のスパムチェックが入ります。
            $chk_result = $throwsSpamAway->validate_comment( "", $value, $args);

            // エラーがあればエラー文言返却
            if ( !$chk_result ) {
                // エラータイプを取得
                $error_type = $throwsSpamAway->error_type;
                $message_str = "";
                /** 
                    エラー種類
                    'must_word'         必須キーワード
                    'ng_word'           NGキーワード
                    'url_count_over'    リンク数オーバー
                    'not_japanese'      日本語不足
                */
                switch ( $error_type ) {
                    case "must_word":
                        $message_str = "必須キーワードが入っていないため送信出来ません ";
                        break;
                    case "ng_word":
                        $message_str = "NGキーワードが含まれているため送信できません ";
                        break;
                    case "url_count_over":
                        $message_str = "リンクが多すぎます ";
                        break;
                    case "not_japanese":
                        $message_str = "日本語が含まれないか日本語文字数が少ないため送信出来ません ";
                        break;
                    default:
                        $message_str = "エラーが発生しました:".$error_type;
                }
                $defaults = array(
                    'message' => $message_str
                );
                $result['valid'] = false;
                $result['reason'] = array( 'your-message' => $message_str);
                return $result;
            }

        }
  return $result;
}
add_filter( 'wpcf7_validate', 'wpcf7_validate_your_message', 10, 2 );


```

これでThrows SPAM Awayの設定どおり your-message 項目に対してバリデーションが効くようになりました。

上記コードでは許可リストに存在するIPアドレスからの送信かを確認するようになっています。

```

            $white_ip_check = !$throwsSpamAway->white_ip_check( $ip );

```

この部分です。

これによるIPアドレスチェックで国内のIPアドレスのみに制限したい場合はThrows SPAM Awayの設定で下記の箇所を調整します。

![ThrowsSPAMAWay_WhiteList.png](https://qiita-image-store.s3.amazonaws.com/0/37489/644d6417-1a45-f93c-852c-676dfcfbc136.png)

IP制御免除 許可リスト　となっていますがIPアドレス一覧を入力するテキストエリアの下のチェックを入れると逆にこのIPアドレスからの送信のみ受け付けるようになります。

## 国内のIPアドレス
国内のIPアドレスの取得は下記ブログを参考にしてください。
[WordPressプラグイン Throws SPAM Away バージョン2.8リリース](https://blog.gti.jp/post-8074/)
こちらに一応国内のIPアドレス一覧を掲載しています。

多分時が経てば変わるものですので最新の国内IPアドレスについては下記が参考になります。
http://qiita.com/tt2004d/items/6ffd26612f6c9c9ba047

## 実験したところ

### 試しにIPアドレスを 127.0.0.1 にして外部の誰もが投稿できない状態にしたら・・・

![ThrowsSPAMAway_WhiteListError.png](https://qiita-image-store.s3.amazonaws.com/0/37489/ae28809b-091b-ddbd-4da0-c7c59d0d8390.png)

こんな感じにエラーになります。
「不明なエラー」にしているのはIPアドレスで蹴られているのがわかられると困るかな・・・と思っただけなので
エラーメッセージも適宜変更してください。

IPアドレスを国内のIPアドレスだけ・・・の設定に戻したあとはこんな感じ

### 日本語が含まれない場合
![ThrowsSpamAway_not_japanese.png](https://qiita-image-store.s3.amazonaws.com/0/37489/ad110e2a-63a7-e019-744b-f57093a21a90.png)

### リンクが多すぎる場合
![ThrowsSpamAway_link_ippai.png](https://qiita-image-store.s3.amazonaws.com/0/37489/e6726f13-5dd1-c433-c7a2-6b3776c26c5d.png)

# 上記の場合、すべての設定はThrows SPAM Awayの設定画面で行います。
今回のサンプルではすべてのThrows SPAM Awayの設定を活かすようになっています。
ですので、コメントへの判定とすべて同期してしまいます。
コメントの設定はそのままでContact Form 7は違う設定にしたい場合は下記のように設定すれば良いです。

```
        $throwsSpamAway = new ThrowsSpamAway();

        $args = array(
              'post_id' => NULL,
              'tsa_on_flg' => 0,    // 日本語利用していなくても可
              // 下の行がなければThrows SPAM Awayで設定されたNGワードが禁止文字として有効になります。
              'tsa_ng_keywords' =>  "私はたわし,馬鹿"    // NGワード指定（カンマ区切りでいくつでも可）
            );
        $value = $this->Data->get( $key );
        $chk_result = $throwsSpamAway->validate_comment( "", $value, $args);
```

$args には下記のパラメータをセット出来ます。

```
$args = array(
'post_id' => NULL,  // コメントの場合だけ使用するので必ずNULL
'tsa_on_flg' => 1,  // 日本語が存在しない場合エラー 1: する それ以外： しない
'tsa_japanese_string_min_count' => 3, // 日本語の最低文字数 デフォルト３
'tsa_ng_keywords'	=>	"馬鹿", // NGワード（カンマ区切りで複数）
'tsa_must_keywords'	=>	"私", // マストキーワード（懸賞応募などに使えるかな・・・）
'tsa_url_count_check'	=>	1,  // URL数チェック 1:する それ以外： しない
'tsa_ok_url_count'	=>	3,  // URL数許容数（３なら３つまで許容）
);
```


参考まで・・・。