Положим есть сайт, где можно свободно подписаться на рассылку, со временем пользователи меняют адреса или изначально указывают невалидные. Письма не уходят и в общем тормозят работу сервера. Аналогичная ситуация возникнет при отправке писем зарегистрированным пользователям (например, уведомления с форума).
Как избавиться от таких адресов?
[spoiler]
Хочу сразу оговориться, что далее речь идёт о сайте на выделенном сервере или VPS (на разделяемом хостинге это проблема хостера).
Чаще всего при отправке почты функцией mail() адрес получателя не проверяется (и это, в принципе, правильно), почта складывается в очередь почтового сервера, и он последовательно рассылает все сообщения. Обычно все неотправленные сообщения возвращаются отправителю, в нашем случае это будет скорее всего системный аккаунт пользователя, под которым работает веб сервер (в случае windows тоже куда-то должны складываться такие письма ). А значит достаточно пробежаться по таким письмам, выбрать почтовые адреса и отписать пользователей от рассылки.
Итак, что нам потребуется?
- данные почтового ящика, на который возвращаются письма от веб сервера;
- модуль "почта";
- и... немного сообразительности
Будем проверять вернувшуюся почту и удалять невалидных подписчиков.
1. Добавляем в систему вышеуказанный почтовый ящик.
2. Создаём новое правило. Здесь особое внимание обращаем на поле "Условие на PHP скрипте", сюда будем вставлять проверку и обработку:
В распоряжении имеем справку:
Где говорится, что в поле доступен массив $arMessageFields содержащий всё письмо.
Служебное письмо сервера имеет вид:
This is a MIME-encapsulated message. --B2FB437C30.1218522354/myserver.com Content-Description: Notification Content-Type: text/plain This is the Postfix program at host myserver.com. I'm sorry to have to inform you that your message could not be delivered to one or more recipients. It's attached below. For further assistance, please send mail to <postmaster> If you do so, please include this problem report. You can delete your own text from the attached returned message. The Postfix program <my@email.com>: host email-com.mr.outblaze.com[208.36.123.16] said: 550 <my@email.com>: No thank you rejected: Account Unavailable: Possible Forgery (in reply to RCPT TO command) |
Далее идёт само письмо. В моём случае невалидный адрес идёт после надписи "The Postfix program" в угловых скобках в теле сообщения. Значит будем работать с переменной $arMessageFields['MESSAGE_TEXT'] $arMessageFields['BODY'].
К сожалению, АПИ модуля почты слабо освещён в документации, поэтому пришлось узнать список полей массива $arMessageFields по исходному коду (файл bitrix/modules/mail/classes/general/mail.php).
В итоге код для условия может быть примерно такой:
if (!CModule::IncludeModule("subscribe")) return; if (preg_match("#The Postfix program[^<]+<([^>]+)>#",$arMessageFields['MESSAGE_TEXT'],$regs)) { $email = $regs[1]; // адрес, который надо исключить из рассылки $rs=CSubscription::GetByEmail($email); $f = $rs->Fetch(); CSubscription::Delete($f['ID']); // удаляем адрес из рассылки return true; } else return false; |
Теперь если вручную или автоматически забирать почту из этого ящика после рассылки, недобросовестные подписчики будут удалены и в дальнейшем не будут бестолку нагружать сервер.
Можно вместо (или вместе) удаления из рассылки удалять или деактивировать пользователя с таким email. Всё зависит от конкретного проекта.
Текущее изложение скорее не howto, а proof of concept того, как решается данная проблема.
Для тех кто захочет повторить - надо использовать вместо $arMessageFields['MESSAGE_TEXT'] (т.к. он пустой) - $arMessageFields['BODY'] (содержит все письмо)
Рад, что помогло.
Я думаю - можно смело добавлять такой функционал в возможности Bitrix (надо только собрать основные ответы серверов).
Ну и раз пошла такая пьянка...
Можно вставлять код не во вкладке "Условия" - а во вкладке "Действия", поле "Действие на PHP скрипте" - в таком случае не надо ничего возвращать.
Денис, вот пока пытался понять почему Ваш код не работал - пытался вывести в файл весь массив $arMessageFields
(чтоб разобраться почему не работает) - но print_r почему то выдавал 1 (единицу) вместо ожидаемого массива. Почему?
(Из-за этого пришлось разбираться с файлом файл bitrix/modules/mail/classes/general/mail.php и выискивать нужный ключ)
Надеюсь цепочку правильно сделал.. Создал правило, в Условие на PHP скрипте добавил код: