Почтовые функции в РНР
Одним из возможных применений imap функций
является создание почтового демона, который будет управлять
подпиской и отпиской пользователей от вашей почтовой рассылки. Для
реализации этой задачи, обычно в рассылках используются два метода.
Первый предполагает, что пользователь должен зайти на некую страницу
и подтвердить свои действия, второй требует отправки письма. Второй
так же требует, чтобы скрипт-обработчик регулярно запускался cron
daemon?om. Из-за этого он не настолько популярен как первый способ.
Но, как можно заметить, наиболее серьезные рассылки используют
второй способ. Поэтому, если у вас есть возможность использования
crond, воспользуйтесь им.
Собственно, разобраться в функциях не так сложно. Человек,
который раньше работал на РНР, без труда поймет, как с ними
работать. Некоторые затруднения могут возникнуть с разбором
заголовков писем, которые будет обрабатывать скрипт.
Алгоритм работы самого скрипта придумать несложно. Демон
устанавливает соединение с почтовым сервером, и проверяет наличие на
нем писем. В случае если писем нет, работа скрипта
прекращается. Если письма есть, то происходит разбор заголовков
первого письма. Просматривается поля from и subject. Если поле
subject содержит один из двух допустимых вариантов заголовка
(подписка или отписка), то запись, которой соответствует значение
поля from либо становится активной (подтвержденной), либо удаляется
из таблицы. В обоих случаях на адрес, указанный в поле from
посылается соответствующее извещение о действиях скрипта. После
этого письмо помечается для удаления. В случае если subject не
содержит допустимых тем, посылается уведомление об ошибке, и письмо
так же помечается для удаления. Затем скрипт переходит к следующему
письму. Закончив разбор всех писем, он очищает ящик.
Не буду утомлять читателя блок-схемами, так что сразу перейдем к
делу. Для открытия ящика используется функция imap_open. Поскольку
РНР поддерживает работу с несколькими протоколами, то необходимо
явно указать, какой протокол используется для работы с ящиком. В
нашем случае это POP3 на 110 порту (стандарт). Присваиваем результат
выполнения скрипта переменной $my_box.
$my_box =
imap_open("{you.pop.host/pop3:110}", "login",
"password");
В дальнейшем вы увидите, что эта переменная будет
использоваться пратически во всех imap функциях. Далее проверяем
ящик на наличие писем. Проверку выполняет функция imap_num_msg.
$n = imap_num_msg($my_box);
В результате переменная $n будет содержать количество писем в
ящике. Число это может быть или больше нуля, или равно ему (если
ящик пуст). Если письма есть, то в цикле while выполняем разбор
писем, последовательно увеличивая номер письма на единицу. Обратите
внимание, что первое письмо в ящике будет иметь номер 0, как, и
первый элемент массива. Для увеличения номера письма, присваиваем
переменной $m значение 0, а потом в условиях выполнения цикла
увеличиваем ее на единицу $m++.
Для разбора интересующих нас заголовков достаточно двух функций:
imap_header и imap_fetch_overview. Для выполнения каждой из их,
помимо ящика, нужно указывать номер письма. В нашем случае, внутри
цикла он будет равен переменной $m.
Imap_header возвращает в результате выполнения объект, содержащий
исчерпывающую информацию о заголовке письма. Среди всего прочего,
этот объект содержит массив from, в котором содержаться четыре
значения. Это personal, adl, mailbox и host. Нас из них интересуют
только mailbox и host. Подставляя их, мы получим адрес, с которого
было отправлено письмо.
$h = imap_header($my_box, $m); $h =
$h->from; : foreach ($h as $k => $v) { $mailbox =
$v->mailbox; $host = $v->host; $personal =
$v->personal; $email = $mailbox . <@> . $host;
imap_fetch_overview - позволит нам узнать тему письма. Для
этих же целей можно было бы использовать и imap_header но по ряду
причин это, иногда может не сработать. Из массива, который
возвращает эта функция, нам нужно только поле subject
$s = imap_fetch_overview($my_box,
$m); foreach ($s as $k => $v) { $subj =
$v->subject; }
Дальнейшие наши действия сводятся к тому, чтобы вытащить
email из базы, и в случае наличия его там, пометить всю строку с
этой записью как <проверенную>, либо удалить. Предположим, что после
заполнения формы рассылки на сайте, подписчику присваивается статус
0, а после подтверждения подписки он меняется на 1.
if ($subj == "SUBSCRIBE")
{ mysql_query("UPDATE subscribe SET stat=1 WHERE
email=$my_email"); $del = imap_delete($my_box,
$m); mail($email, $add_sbj, $add_text, $headers); } elseif
($subj == "UNSUBSCRIBE") { mysql_query("DELETE FROM subscribe
WHERE email = $my_email"); $del = imap_delete($my_box,
$m); mail($email, $del_sbj, $del_text, $headers); } else
{ $del = imap_delete($my_box, $m); mail($email, $err_sbj,
$err_text, $headers); }
как уже говорилось выше, после выполнения всех действий
скрипт очищает ящик.
$clear = imap_expunge($my_box);
Данная простейшая программа, лишь демонстрация того, что на
РНР можно писать не только динамически изменяющиеся сайты, но и
сервисы, которые пользователю вообще не видны. Конечно, по части
написания скриптов для shell, рнр неприменим, в отличие от своего
конкурента Perl, но тем не менее:
Листинг всей программы за исключением параметров соединения с
базой (db.php):
<? include "db.php"; $my_box =
imap_open("{you.pop.host/pop3:110}", "login", "password"); $n =
imap_num_msg($my_box); $m = 0; $add_text = "
Спасибо за подтверждение вашей подписки
"; $add_sbj = "You added!"; $del_text = "
Вы были удалены из списка рассылки.
"; $del_sbj = "Delete from list"; $err_text = "
Извините но этот почтовый ящик
используется только для администрирования рассылки"; $err_sbj
= "Error"; $headers = "From: Subscribe Robot
<You@mail.box>
X-mailer: PHP4
Content-type: text/plain;
charset=windows-1251 "; if($n != 0) { while($m++ < $n)
{ $h = imap_header($my_box, $m); $s =
imap_fetch_overview($my_box, $m); $h = $h->from; foreach
($h as $k =>$v) { $mailbox = $v->mailbox; $host =
$v->host; $personal = $v->personal; $email = $mailbox .
"@" . $host; $my_email =
mysql_escape_string($email); } foreach ($s as $k =>$v)
{ $subj = $v->subject; } if ($subj == "SUBSCRIBE")
{ mysql_query("UPDATE table SET stat=1 WHERE
email=$my_email"); //print mysql_error(); $del =
imap_delete($my_box, $m); mail($email, $add_sbj, $add_text,
$headers); } elseif ($subj == "UNSUBSCRIBE")
{ mysql_query("DELETE FROM table WHERE email =
$my_email"); $del = imap_delete($my_box, $m); mail($email,
$del_sbj, $del_text, $headers); } else { $del =
imap_delete($open_box, $m); mail($email, $err_sbj, $err_text,
$headers); } } $clear =
imap_expunge($my_box); } ?>
В листинг отсутствуют некоторые детали, например возможное
конвертирование из win в koi, перепроверка почтового ящика
отправителя и т.д. Это уже функциональные излишества, которые каждый
может добавить по мере необходимости.
Автор: Сергей
Лисин
|