メールアドレスのバリデートはどっちが正しいの?

この記事はだいぶ前に書かれたものなので情報が古いかもしれません
本当は「かゆい うま」なんだね

この記事を三行にまとめると

メールアドレスのエラーチェックについて
...kayu...uma...
田舎に引きこもろう
CakePHPで開発しているとき、エラーチェックを実装することがありますね。別にCakePHPじゃなくても実装することはあるけども。

このエラーチェック、CakePHPの場合はある程度のバリデートルールが最初から用意されてるので、理由がない限りはそれを使わせてもらえば良いと思うんですが、その数あるバリデートの中に、メールアドレスの形式をチェックしてくれるものがあります。

自分で実装するのは面倒だから僕もよく使うんですが、果たしてこのメールアドレスのエラーチェックは、正しいのか? 否か? 田舎に引きこもるのはありか?

っていうのが今回のお話です。



基本系

とりあえず、まずはCakePHPでメールアドレスのエラーチェックをしてみましょう。

いつものようにだいぶ端折って書くけど、モデルとビューはだいたいこんな感じだね。コントローラーは省略。

//モデル
$validate = array(
  'email' => array(
    'rule' => 'email',
    'message' => '形式が不正です',
  ),
);

//ビュー
echo $this->Form->text('email');

これで、テキストボックスにメールアドレスとして不正な文字列を入れれば、エラーになります。@がなかったりとかね。



変化形

じゃあ今、こんなメールアドレスを入力してみたとする。果たしてエラーになるのか?

...kayu...uma...@bio.hazard

はい。何ともひどいもんですねww実際こんなメールアドレスを使ってる人はいないでしょう。「.hazard」って何だよ。

仮に実際にこんなメールアドレスが存在したとしても、これを入力すると、CakePHPのメールアドレスのエラーチェックは通りません。「形式が不正です」って言われる。

何でかっていうと、bio.hazardなんてふざけてるから……ではなくて、メールアドレスにはRFCとかいう文書だか形式に準拠したフォーマットでなければならないという決まりがあるそうで、上のメールアドレスは、その条件を満たしていません。

具体的に言うと、以下のような条件に該当するメールアドレスは、メールアドレスとしては無効です。

・@の前にドットがある(.@)
・ドットが連続している(…)

上記のメールアドレスは、どっちにも該当しますね。だから無効なメールアドレスであり、エラーチェックにも引っかかる。うん、どこもおかしくはないですね。



特質系

何も問題ないんだから、CakePHPのエラーチェックは正しいじゃんってことで話を終わりにしても良いんですが、これが案外そうもいかない。

ぶっちゃけ理由はよく分からないんですが、たまーに、この無効なはずのメールアドレスを使っている人がいる。ドットが連続したメールアドレスなどを実際に使っている人がいるみたいなんです。どうして使えるのかはよく分からないし、本当に使えているのかもよく分からないけど、僕は仕事でそういうクレームをいただいたことがある。「メールアドレスを登録しようとするとエラーになって登録できない。ふざけんな」っていうクレームが。調べてみたら、その人のメールアドレスはドットが連続していた。

「何言ってんすか。そのメールアドレス無効っすよ(○゚ε゚○)プププー」って返事しても良いんだけど、ってか実際にこのクレームが来た時にそれに近いことは言ったんですけど、毎回そんなんだといつかきっと怒られるので、連続ドットなどのメールアドレスをエラーに引っかけないようにするなら、CakePHPのバリデーションの方を改造する必要がある。

CakePHP2系の場合「Utility」というフォルダの中にある「Validation.php」というファイルに、バリデーションに関するものが入っている。で、この中に「email()」というメソッドがあり、そこでメールアドレスのチェックをしています。

なので、ここをちょっと書き換えてみる。

public static email($check, $deep = false, $regex = null) {
  〜 中略 〜

  //書き換える前のやつ
  //$regex = '/^[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*@' . self::$_pattern['hostname'] . '$/i';

  //書き換えた後のやつ
  $regex = '/^[a-z0-9\.!#$%&\'*+\/=?^_`{|}~-]+(?:[a-z0-9\.!#$%&\'*+\/=?^_`{|}~-]+)*@' . self::$_pattern['hostname'] . '$/i';

  〜 中略 〜
}

ほとんど何も変わってないように見えますが、ドットの位置がちょっとだけ変わってます。「a-z0-9」の後ろにバックスラッシュつきでドットが移動してる。間違い探しじゃないよ?

まあ、ここを書き換えなくても、第三引数に「$regex」を任意に指定することができるから、そこでやっても良いんですけどね。僕の場合、何ヶ所か書き換えなきゃいけなかったから、めんどくさくて丸ごとオーバーライドした。

この書き換え方が正しいかはちょっと自信ない……ってか、こんなことしちゃって大丈夫なのかも自信はないですけど、とりあえずこれで、@の前にドットがあっても、連続でドットがあっても、エラーにはならない。

あとは運用でカバーって感じかなぁ。



おまけい

ちなみに、実際にそんなメールアドレスを使用している人にメールを送るには、@の前をダブルクォーテーションで囲めば良いみたい。

"...kayu...uma..."@bio.hazard

まあ、こういう形式のメールアドレスにメールを送信する場合、CakePHPのCakeEmailなんかを使っていれば、勝手にクォーテーションをつけて送ってくれますけどね。






ということで、メールアドレスのエラーチェックに関するお話でした。

結論としては、連続ドットなどを許可しないエラーチェックは正しいってことで良いと思うんですけど、場合によっては、それじゃダメだって言われることがあるかもしれない。その辺は良かれと思う方で対処すれば良いんじゃないでしょうか。

あと、個人的にはそろそろ本当に田舎に引きこもろうと思ってるし、そういう方向で動き始めているんですけど、ありでしょうか? 別に田舎でも開発の仕事はできるしねぇ……。
 もしかしたら何か関連しているかも? 
 みんなからのコメント 
2018年02月08日 11:51:36
[…] PHP-検証フィルタ メールアドレスのバリデートはどっちが正しいの? […]