Автоматическое исключение из рассылки нерабочих email адресов

в 12:03, , рубрики: email, ruby on rails, Блог компании centos-admin.ru, Веб-разработка, рассылка, метки: ,

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

который можно использовать.

Автор: kanfet

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js