Автор: fox++
http://foxweb.net.ru/
9 августа 2005 года
Оригинальная защита e-mail адресов от сканирования спам-роботами. Мы не будем
кодировать адреса, мы будем их… рисовать!
О защите e-mail адресов от сканирования спам-роботами в Интернете писалось
немало. Скорее наоборот, очень много. Однако все способы сводятся в основном к
одному – кодирование адресов таким образом, чтобы спам-роботы не смогли его
распознать, а для человека это не составило бы труда. Чаще всего мне встречались
такие варианты: name[at]server.ru, name(a)server.ru и даже
name(Shift+2)server.ru. Вариант, конечно, тоже хороший, но спам-роботы быстро
«учатся». Опытный интернетчик догадается, что [at] нужно заменить на «@», но
некоторые люди копируют адрес name[at]server.ru прямо в почтовую программу, а
потом удивляются – почему письма не доходят :) Вначале проблема спама не так
беспокоила меня, пока однажды горы рекламных писем не посыпались на мой ящик. В
этот же день нашёл простой выход: «собачку» можно показывать как картинку, всё
остальное – как символы. Внешне – обычный e-mail, а скопировать не получится.
Предлагаю вашему вниманию простой и доступный способ публикации e-mail адресов
без опасения, что его просканирует спам-робот. Хотя, возможно, и просканирует,
но для этого он должен обладать искусственным интеллектом :) Требования: наличие
PHP с библиотекой GD. Многие наверно догадались, что мы будем делать с адресами.
Мы будем их… рисовать! Назовём наш скрипт email.php. Алгоритм достаточно прост:
Одним из способов скрипт получает на вход е-mail адрес:
Получим адрес автора из базы данных, указав например id статьи или записи в
гостевой книге (каталоге файлов, ссылок и т.д.).
Передадим адрес скрипту в явном виде: email. php?adr=name@server.ru (но это
чревато тем, что e-mail всё-таки «засвечен»). Такая защита равносильна её
отсутсвию.
Передадим адрес скрипту в неявном виде: email. php?name=name&server=server. ru
Передадим адрес скрипту в зашифрованном виде: email.php?adr=anzr@freire.eh
(воспользовавшись функцией str_rot13() , которая смещает коды всех латинских
букв вверх на 13).
Скрипт расшифровывает данные, генерирует картинку с изображением адреса и
возвращает её браузеру.
Для начала рассмотрим процесс «рисования», так как он впоследствии останется
неизменным:
$size = 2;
$im = imagecreate(imagefontwidth($size)*strlen($adr), imagefontheight($size));
Здесь нет ничего особенного. Исходные данные: $adr – адрес, который надо
«нарисовать», $size – размер шрифта на картинке (легко подбирается по размеру и
«жирности», внешне похож на Tahoma, Verdana, Arial). Функция imagecreate()
создаёт картинку и помещает указатель на неё в переменную $im. Однако для этого
вычислим размеры будущей картинки, исходя из размера шрифта и количества
символов в строке.
imagefontwidth($size) – определяет ширину одного символа при размере $size.
Умножим её на длину строки strlen($adr) и получим ширину будущей картинки.
Высота картинки вычисляется функцией imagefontheight($size). Добавляем в палитру
изображения цвета фона и надписи (соответственно белый и красный)
$bg = imagecolorallocate($im, 255, 255, 255);
$black = imagecolorallocate($im, 0x00, 0x00, 0x00);
Если цвет фона вашего сайта не белый, сделаем так:
imagecolortransparent($im,$bg);
Цвет $bg в палитре станет прозрачным, поэтому $bg может быть любым цветом. Цвет
символов задаётся в соответствии с вашими потребностями.
Делаем надпись:
imagestring($im, $size, 0, 0, $adr, $black);
И выводим картинку :
header('Content-type: image/png');
imagepng($im);
Вот весь скрипт целиком (добавьте нужный вам способ получения адреса):
<?php
$size = 2;
$im = imagecreate(imagefontwidth($size)*strlen($adr), imagefontheight($size));
$bg = imagecolorallocate($im, 255, 255, 255);
$black = imagecolorallocate($im, 0x00, 0x00, 0x00);
imagecolortransparent($im,$bg);
imagestring($im, $size, 0, 0, $adr, $black);
header('Content-type: image/png');
imagepng($im);
?>
Вывод картинки вместо реального e-mail делается примерно так:
Ваш e-mail: <a href="mailto:name@server.ru">name@server.ru</a>
Ваш e-mail: <img src="email.php?adr=name@server.ru">
Теперь, когда мы знаем, как заменять e-mail адреса, можно написать функцию,
которая будет производить такие замены в заданном тексте при помощи регулярных
выражений. Это может потребоваться при тотальной фильтрации всего вывода,
пакетной обработке HTML-файлов, выводе информации из БД.
Разделим адрес на 3 части:
(Имя)@(Домен).(Зона)
И того уже имеем паттерн типа:
(.*)@(.*).(.*)
Под эту формулу подойдут миллиарды выражений, но мы идём дальше по спецификации
e-mail адреса. Имя пользователя должно состоять из "a-z", "A-Z", "0-9", а также
".", "_" и "-". Если не ошибаюсь, строгих правил по этому поводу никогда не
было, где-то разрешены и другие символы, это основа. "A-Z" добавлено на случай
если пользователь любит прописывать своё мыло "покруче". Длина имени от 2-х до
256-ти символов (см. RFC). Дальше домен, тоже самое – "a-z", "A-Z", "0-9", ".",
"-" и всё! Длина доменного имени та же, единственная загвоздка – если мыло
находится не в домене второго уровня, а, скажем, третьего или даже четвёртого.
Тут снова в RFC кидаться надо, поскольку и сама служба DNS не лишена "ответа"
типа HTTP 414 :). Длина домена не может превышать 256 символов, но вот входят ли
в это число поддомены – не помню. Зона – здесь просто "a-z", "A-Z" от 2-х до 4-х
символов.
В итоге получается что-то такое:
([a-zA-Z0-9|.|-|_]{2,256})@(([a-zA-Z0-9|.|-]{2,256}).([a-z]{2,4}))
Можно проверить, не начинаются ли (или заканчиваются) подвыражения \\1, \\2
символами типа "." или "-", дальше – на что фантазии хватает. Используя
вычисленное регулярное выражение (невольно вспоминаются лекции по матанализу),
напишем функцию, которая будет заменять все адреса e-mail в строке на тэг IMG и
возвращать изменённую строку. В качестве функции замены я использовал
preg_replace() с синтаксисом Perl RegExp.
email_ replace. php
<?php
// функция замены e-mail адресов
function email_replace($text)
{
$exp = '/([a-zA-Z0-9|.|-|_]{2,256})@(([a-zA-Z0-9|.|-]{2,256}).([a-z]{2,4}))/';
return preg_replace($exp, '<img src=email.php?name=\\1&server=\\2 border=0>',
$text);
}
// исходная строка со множеством e-mail адресов
$text =<<<END
По всем вопросам пишите на мои e-mail:
f_mulder@list.ru,
fox58@list.ru,
admin@foxweb.net.ru,
kurepin@sura.ru,
fox58@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.com
(это реальный адрес!!!)";
END;
echo $text; // исходная строка
echo "<br>";
echo email_replace($text); // изменённая строка
?> |