Представьте, что у Вас есть веб-приложение и одной из его функций является массовая рассылка новостей Вашим пользователям.
По некоторым причинам часть email адресов пользователей нерабочие или неверно заполненные. Хорошо бы таких пользователей автоматически отписать от рассылки?
В отправляемые сообщения рассылки можно добавить специальный заголовок
Return-Path: <noreply@my-application.com>
На этот адрес будут приходить уведомления от почтового сервера о провалившихся доставках.
В итоге вся задача сводится к чтению этих уведомлений, извлечению email адреса, и пометки пользователя с этим адресом как недоступного для рассылки.
А теперь реальный пример.
В одном из наших приложений почтовый сервер добавляет прямо в тело таких уведомлений несколько полезных строк:
Final-Recipient: rfc822; nonexistent@example.com Original-Recipient: rfc822;nonexistent@example.com Action: failed Status: 5.1.1
Для ruby есть IMAP-клиент в стандартной библиотеке. Подключаемся к нашему «noreply@my-application.com» ящику и читаем уведомления:
imap = Net::IMAP.new('mail.my-application.com', port: 993, ssl: true) imap.login("noreply@my-application.com", "mysecretpassword") imap.select("INBOX") # здесь может быть другая папка в ящике, куда отфильтровываются уведомления imap.search('ALL').each do |message_id| # чтение тела сообщения message = imap.fetch(message_id, 'BODY[TEXT]')[0].attr['BODY[TEXT]'] match = message.match(/^Original-Recipient: rfc822;(.*)$/) email = match[1].strip if match # rails-зависимый код приложения для отписки пользователя от рассылки if email user = User.where(email: email).first user.unsubscribe if user end # перемещаем уведомление в другую папку почтового ящика imap.copy(message_id, 'Processed') imap.store(message_id, '+FLAGS', [:Deleted]) end imap.expunge imap.logout imap.disconnect
Для чистоты можно еще проверять код статуса. Код 5.X.X свидетельствует о неустранимой ошибке доставки, например, email адрес не существует, код 4.X.X — о временной ошибке, например, сервер-получатель не отвечает.
Данный код запускается периодически в фоне с помощью Resque, Delayed::Job, cron, или любого другого инструмента используемого в приложении. Задача решена: рассылка отправляется только на рабочие существующие email адреса.
Задача была подготовлена и решена совместно с olemskoi
P.S.: В Вашем приложении подобные уведомления возможно не будут настолько многословны, но нерабочий email все равно можно будет попытаться как-либо извлечь. Например, если использовать gmail для отправки писем, то уведомления о провалившейся доставке от него будут содержать специфический заголовок:
X-Failed-Recipients: nonexistent@example.com
который можно использовать.
ссылка на оригинал статьи http://habrahabr.ru/company/centosadmin/blog/200534/
Добавить комментарий