スパムメールが来ないようにする
このページは、スパム対策メアド表示ツールの技術解説です。
Webページを作り、感想が欲しくてメールアドレスを表記する。
するとやがて、メールアドレスに続々と、欲しくもない広告メールが送られてくるようになる。
いわゆる「スパムメール」だ。
誰もがスパムメールに悩まされ、対策している。
スパムメールがくるのはしかたがない、と考えれば、受け取った後でスパムを見つけ出す、メールフィルタを導入することになる。
メールアドレスを公開しなければスパムがまったくこない、という保証はないが、公開するよりはずっと少ないだろう。
友人からメールをもらいたいだけなら、なにもWebページに書く必要はなく、友人にメモを渡せばよい。
でも、やっぱりWebページにメールアドレスを公開したい、ということはある。
そのようなニーズに合わせて、多くの手法が編み出されている。
そして、多くの手法が、スパム業界の一角…メールアドレス収拾を行う業者の手によって、無意味なものにされてきた。
現在のところ、有力でありつづけている手法が2つある。
その方法は、どちらも問題を抱えている。
1つは、画像によるアドレス公開。
一部のメールアドレス収拾プログラム(以下、ボットと呼ぶ)は、OCRでこれを読み解くらしいが、OCRという原理自体が不確定要素を孕むため、ボットを回避する手段としてはかなり強力だ。
ただし、ボットだけでなく、人間も回避されてしまう。
…メールアドレスは確かに表示されているが、メールを送ろうとは思わなくなる。わざわざメーラーを自分で起動し、送信先を手入力しなくてはならないからだ。
OCRしにくいように工夫された画像の場合、人間の読み取りミスも増えるため、さらに問題が悪化する。
もう1つの方法は、Javascriptによるアドレス偽装。
単にJavascriptを使えばよい、というわけではない。HTML読み込み完了時に起動し、最初の描画時点でデコードされたアドレスが表示される、というようなタイプでは、ボットに読み込まれる可能性が高い。
Webブラウザと同じ動作を行うボットは簡単に作れるからだ。
有効な偽装方法は、閲覧者がメールを送信したいと思う、その瞬間まで、メールアドレスの秘密を保持しつづけるタイプである。
先に Web ブラウザと同じ動作を行うボットは簡単に作れる、と書いたが、表示後のユーザーの操作の可能性まで考慮すると、可能性が膨大になる。
だから、ユーザーが操作しないとメールアドレスを解読しない、と言う作りにしておけば、ボットに解読される可能性は激減するはずだ。少なくとも現在のところは、このタイプの偽装が少ないこともあって、かなり有効な手段である。
この方法の問題は、Javascriptが実行されない環境では動作しないことだ。
また、大抵はメールアドレス1行の表示の代わりに、膨大なJavascriptプログラムを必要とする。
実は、上の2つの方法は併用が可能だ。
メールアドレスを画像で示し、クリックされたらJavascriptでメール送信の準備を整える。
これなら、画像だけと違ってメールアドレスを手入力してもらう必要はないし、Javascriptが実行されない場合でも、画像だけの場合と同じ問題は残るが、メールアドレスを示すことはできる。
だけど、この場合も別の問題が残る。
すでに多くのサイトで「メールアドレス画像にはリンクがない」ことに慣れてしまった人が多いため、わざわざクリックしてみよう、なんて思ってくれないのだ。
画像のOCR問題も解決していないし、Javascriptが無駄に長い問題も解決していない。
というわけで、この問題を解決しよう、というのが今回のプログラムのスタート地点である。
OCRの原理は長くなるので解説しないが、単純に言えば、縦横に隙間がある部分で画像を切り取り、「文字」に分解してから認識を行っている。
なので、筆記体のように文字がつながっていると認識率が極端に落ちる。
じゃぁ、メールアドレスを筆記体で書けばよい…というのは早合点である。筆記体は人間でも読みにくい。文章なら雰囲気で読めても、1文字間違えたら無意味になってしまう、メールアドレスでは使えない。
じゃぁ、普通の文字でも、無理やりつなげてしまえば…これは、OCRソフトの性能にもよるが、効果がある。
アンダーラインを引いただけでも、文字が読めなくなるソフトはある。多少癖のあるフォントを使えば、ほとんどのソフトで認識できなくなる。
アンダーラインで文字をつなげることには、もう一つのメリットがある。
Webブラウザの多くが、文字にリンクがつけられていることを、色とアンダーラインで示すのだ。
文字の色を他のリンク文字と同じにして、アンダーラインをつけて表示すれば、多くの人はリンクテキストだと考えるだろう。
マウスカーソルを乗せたとき、カーソルの形が「人差し指」に変われば、リンクであることを確信する。
これで、OCR対策と、リンクの存在アピールの2つの問題は解決した。
残るは、Javascriptが長すぎる問題だ。
これについては…説明しても、真のプログラマでないとわからない話が延々と続くだけだし、真のプログラマならそんなことは説明されないでもわかっているだろう。
まぁ、「汎用性」に対する思い切った割り切りと、細かなテクニックをコマゴマと駆使して短くしただけだ。
というわけで、詳細は割愛。
実は、もうひとつ考慮しておきたい問題がある。ボットそのものの動作原理だ。
これはボットによって当然異なるが、絶対に共通しているのは「取得した WEB ページから、メールアドレスと思われる文字列を取り出す」ということだ。
なにを当然のことを、と思われるかもしれないが、基本を抑えることは重要。この基本を抑えれば、当然「WEB ページを取得すると言っても、その URL は、どうやって決めるの?」という疑問がでてくるからだ。
この疑問の回答も簡単に思いつく。WEB ページ内のメールアドレスを取り出す際に、同時に「別のページの URL」も取り出して、次のページを取得する際のヒントにしているのだろう。
メールアドレスも、一番わかりやすいのは URL の一種として mailto: に続けて書かれている場合だ。つまり、メールアドレス収集ボットは、リンクをたどり続けるという、通常の WEB クローラーの動作となんら変わっていないことがわかる。
ということは、ボットによって程度の違いこそあれ、リンクタグが重要なキーであることは間違いないだろう。
さて、今回の手法では「OCR できない画像でメールアドレスを表示して、画像をクリックするとメーラーが起動し、アドレスが入力された状態にする」のが目標である。
普通、クリック可能な部分を作成するには、リンクタグを使う。クリックしたら Javascript が動作する、というようにするなら、URL 部分に Javascript: で始まる文字列を指定する。
でも、ボットがリンクタグを重視しているのであれば、リンクを作ることがボットに対するヒントになるのではないか? javascript: と書いてあったら、とりあえず javascript 部分を評価してみる、というボットだっていないとは限らないのだ。
そこで、ボットに対するヒントを少しでも減らすため、メールアドレスの表示に a タグは使わない、と決めてみる。
これには、もうひとつ利点がある。無駄なタグを排除するために、全体のコード量が減るのだ。これは、先の「Javascript が長すぎる」問題の解消にもつながる。
そこで今回は、画像を表示するための img タグに、直接 onClick 属性をつけることにした。onCLick 属性内に書くのは Javascirpt 、と最初から決まっているため、URL 部分への記述と異なり、javascript: の文字も不要となる。よいことずくめだ。
結果、出来上がったものは、たった一つの img タグである。オプションが多くてちょっと長いけど、設置は難しくない。
HTML コード量としては、「ボット対策しない場合」の普通のメールアドレス表示の2倍程度。ボット対策に払うコストとしては、許容してもらえる範囲ではないかと思う。
(HTML コード以外に、メールアドレス画像が必要だけど)
最後に、これらの手法でメールアドレスを表示する方法を、自動で生成するプログラムを作ってみた。
実は、この部分が一番楽しかった。
先の部分で「プログラムを短くする」ことに熱中したので、生成プログラム側を短くする必要はないのに、できる限り短く書いてみた。
とはいえ、こちらはそれなりの機能を持たせたかったので、それほど「割り切り」は行っていない。
PCのインストールフォントをある程度自動認識する部分など、応用範囲もそれなりにありそうだ。