Webアプリでメールアドレスを確認する「正しい」方法

プログラミング言語あるいは通信プロトコル上のテクニックで 「メールアドレスかどうか調べる」という話題はいつもどこかに転がっている。

上記で紹介したような話をそれぞれよーく読むと、

「ユーザーが入力したそのメールアドレスで本当に連絡が取れるかを確認したい」
という本来の要求仕様=やりたいこと=がいつのまにか
「メールアドレスの書式として正しいかを確認したい」
にすりかわっていることに気がつく。 かなりいじわるな見方ではあるが、しかし、背景までをも考えればそういうことである。

そう、正確に言うと、内容が間違っているのではなく本来導くべき方向性が間違っている。

この状態がさらに悪化すると例えば次のようなことになる。

Firefoxで登録フォームのペースト禁止方法について -OKWave
コードの一部の「email確認用」となっているところにご注目。 つまりメールアドレスの入力欄を2つ置いて ベリファイチェックしようとしている。そこでのコピペは許さない、という仕様にしようとしている。

これなどは要求仕様の誤解がさらにおかしな仕様を生み出し、 最終的にあさっての方向を向いて、恐ろしいことにそれが実現されようとしているケースだ。 結果として完成するのはユーザーに対する嫌がらせとしか思えない画面である。

そもそも論として、

  1. メールアドレスが正しいかどうかをプログラミング言語上のテクニックだけで判断する方法は事実上存在しない。
  2. したがって、メールアドレスが正しいかどうかを判断するにはそのアドレスにメールを1本送ってみて、それが無事届くかどうかをもって判断するしかない。
ということをまず理解しておくべきだろう。

たとえば、山田さんのアドレスが yamada@example.com であるとして、 Web上のフォームに入力するときに tamada@example.com と間違って入力したとする。tとyは隣同士だ。よくあるタイプミス。 これは、先の記事で紹介されているいかなるチェック用コードを使ってもエラーとして引っかからない。

それならSMTPのVRFYコマンドを使えなどとマニアックなことを言う人もいるが、 迷惑メール全盛の世の中、そんなメールアドレスがダダ漏れしそうなコマンドを一般開放しているメールサーバーを探すほうが難しい。

あるいは、あるYahooメールのユーザーであるオバサンは、 自分のメールアドレスが yamada@yahoo.ne.jp であると固く信じていたりする。 そんな人はWeb上のフォームにメールアドレス入力欄が2個あろうと3個あろうとそこでコピペが禁止されようと、 力いっぱい @yahoo.ne.jp と入力し続けるだろう。

国内の携帯キャリアのアドレスを含めるともっと面倒なことになるのはこの前も話したとおりだ。 hoge..fuga.@docomo.ne.jp というアドレスは「正しい」。docomoメソッドにおいては。 しかしインターネットの標準にそって正しく作られたチェック用コードのいくつかでは、「これは連続ドットや@直前のドットを含む」と「正しく」判断し、エラーとしてしまう。

まともなプログラマーは気づく。「これ、なんかもう無理があるんじゃね?」と。 javaでもperlでもphpでも話はすべて一緒である。 コーディングしていて何か無理を感じたときは、テクニック不足を疑うばかりではなく、 そもそも要求されている仕様がなんであるのか?に立ち戻り、 そして設計あるいは設計思想のほうを見直してみるのがシステム構築の基本だ。

注文フォームでも問い合わせフォームでもなんでもいいが、次のような設計が多い。

a.php (<form>タグで包まれたフォーム。ここでtextフィールドでメールアドレスを入力させる)

↓ submitボタンでPOSTリクエスト

b.php (情報をDBに格納したり、確認メールを生成してメールサーバに託したりするコード)
画面遷移の設計として一番直感的であり、 かつ初心者向けのPHP本などにはたいていこんなふうな画面構成を想定して書かれているためだろう。 しかしこれではb.phpにPOSTされてきたメールアドレスが正しいことは保証できない。

相手のメールアドレスなんてどうでもいいという程度の要求であればこれで十分である。 しかしそれでは困るケースももちろんある。その場合の真の要求仕様は、 「ユーザーが入力したそのメールアドレスで本当に連絡が取れるかを確認したい」 である。

だったら、まずメールを送って「送ったから、読んでね」と言えばいい。

a.php (<form>タグで包まれたフォーム。textフィールドなどでメールアドレスやその他の情報を入力させる)

↓ submitボタンでPOSTリクエスト

b.php (POSTされた情報をDBやキャッシュファイルに一時的に保存しつつ、「メールを送ったから読んでクリックしてね!URLをクリックしないと注文確定しないよ!」というメールを送る。メール上には一時情報を示すURLを掲載しておく)

↓(ユーザーがメーラーで受信して、その本文上のhttp://example.jp/c.php?tempid=012345...をクリックする)

c.php(一時的に保存しておいた情報を「正式な」情報としてしかるべく処理する)
こんな感じ。二重サブミット対策とかいろいろ考えるともうちょっと複雑な遷移を取ることもあるし、フレームワークの種類によっては途中でリダイレクトがかかったりするのだが、細かい話はおいといて。

場合によってはa.php上のフォームに書かせる情報はメールアドレス「だけ」にして、c.php 以降のほうでそのほかの情報を書かせるようにすることでも、メールアドレスの到達性を確保することができる。サイトの特性と確保したいユーザビリティによって使い分けるべきだろう。

ここで書いたような話はまったくめずらしい方法論ではない。 既に多くのWebサイトで実装され、ユーザーは目にしていることである。 しかし、いざ「自分でつくれ」と言われると、経験の浅い人は何も考えずにa.php →(POST)→b.php(完了!) みたいな設計をついついやってしまう。

see also:

トラックバックURL

このエントリーのトラックバックURL:
http://www.ywcafe.net/mt/mt-tb.cgi/782

コメントする

(初めてのコメントの時は、コメントが表示されるためにこのブログのオーナーの承認が必要になることがあります。承認されるまでコメントは表示されませんのでしばらくお待ちください)


画像の中に見える文字を入力してください。