Одним из возможных применений 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: PHP4Content-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,
перепроверка почтового ящика отправителя и
т.д.
Это уже функциональные излишества, которые каждый может добавить по
мере необходимости.