Наш чат в Telegram для обмена идеями, проектами, мыслями, людьми в сфере ИТ г.Ростова-на-Дону: @it_rostov

Рассылка писем на PHP с использованием imap функций

Одним из возможных применений imap функций является создание почтового демона, который будет управлять подпиской и отпиской пользователей от вашей почтовой рассылки. Для реализации этой задачи, обычно в рассылках используются два метода. Первый предполагает, что пользователь должен зайти на некую страницу и подтвердить свои действия, второй требует отправки письма. Второй так же требует, чтобы скрипт-обработчик регулярно запускался cron daemon-om. Из-за этого он не настолько популярен как первый способ.

Но, как можно заметить, наиболее серьезные рассылки используют второй способ. Поэтому, если у вас есть возможность использования cron, воспользуйтесь им.

Собственно, разобраться в функциях не сложно. Некоторые затруднения могут возникнуть с разбором заголовков писем, которые будет обрабатывать скрипт.

Алгоритм работы самого скрипта придумать несложно. Демон устанавливает соединение с почтовым сервером, и проверяет наличие на нем писем. В случае если писем нет, работа скрипта прекращается. Если письма есть, то происходит разбор заголовков первого письма. Просматривается поля from и subject. Если поле subject содержит один из двух допустимых вариантов заголовка (подписка или отписка), то запись, которой соответствует значение поля from либо становится активной (подтвержденной), либо удаляется из таблицы. В обоих случаях на адрес, указанный в поле from посылается соответствующее извещение о действиях скрипта. После этого письмо помечается для удаления. В случае если subject не содержит допустимых тем, посылается уведомление об ошибке, и письмо так же помечается для удаления. Затем скрипт переходит к следующему письму. Закончив разбор всех писем, он очищает ящик.

Для открытия ящика используется функция imap_open. Поскольку PHP поддерживает работу с несколькими протоколами, то необходимо явно указать, какой протокол используется для работы с ящиком. В нашем случае это 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);
}
else if ($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);

Данная простейшая программа, лишь демонстрация того, что на PHP можно писать не только динамически изменяющиеся сайты, но и сервисы, которые пользователю вообще не видны.

Листинг всей программы за исключением параметров соединения с базой:

include "config.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

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);
}
else if ($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);
}

В листингe отсутствуют некоторые детали, например возможное конвертирование из win в koi, перепроверка почтового ящика отправителя и т.д. Это уже функциональные излишества, которые каждый может добавить по мере необходимости.

Смотрите также:


.