Лучший подход для процедуры массовой рассылки PHP?

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

Текущий подход:

Пользователи помещаются в таблицу базы данных «очереди рассылки» с указанием их идентификатора, времени получения и флага отправки.

Затем я каждую минуту запускаю скрипт CRON, который выполняет следующие действия:

  1. Забрать из очереди рассылки все, что не отправлено, со временем получения меньше или равным текущему моменту.
  2. Просматривайте пользователей, присоединяясь к таблице предпочтений, чтобы получить выбранные ими категории (до 30 на пользователя).
  3. Для каждой категории найдите последние 3 статьи
  4. Подготовьте электронное письмо в формате HTML с этим содержимым с помощью PHPMailer
  5. PHPMailer использует Mailgun SMTP, чтобы избежать перегрузки моего SMTP-сервера
  6. Отправить письмо пользователю, отметить как отправленное в базе данных

На данный момент мои наблюдения:

  1. При тестировании скрипта в браузере он работает очень медленно в течение нескольких минут, а затем истекает время ожидания (без отправки электронных писем).
  2. При запуске через CRON каждую минуту он отправляет намного больше писем (около 1400) в течение 40 минут, я полагаю, потому что скрипт перекрывает сам себя, и флаг отправления не обновляется надежно.

Большинство пользователей настроены на получение электронной почты в одно и то же время, поэтому я провожу тестирование "наихудшего сценария" на этой основе

Вопросы

  1. Не слишком ли тяжел мой сценарий, запрашивая базу данных и генерируя содержимое электронной почты HTML для каждого пользователя на лету? Мне интересно, не лучше ли сгенерировать контент заранее и сохранить его для пользователя в очереди рассылки.
  2. Может ли администратор очередей, например Beanstalkd, помочь? Я изучал это, но изо всех сил пытаюсь понять, как внедрить в свой распорядок.

В конечном итоге мне нужно, чтобы электронные письма были надежно отправлены каждому пользователю в нужное время.

Любой совет очень ценится!


person James B    schedule 16.11.2020    source источник


Ответы (1)


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

Отправка больших объемов электронной почты во время загрузки страницы не работает - это может быть проблематично даже для отдельных сообщений, но многие все же пытаются. Подойдите к этому так:

  • Сохраните свой список в базе данных.
  • Если вы хотите отправить, создайте запись, представляющую каждое сообщение для отправки (по сути, копию списка).
  • У вас должен быть демон (длительная задача) или задание cron, которое отправляет сообщения кусками.
  • Создавайте сообщения по одному и отправляйте их на локальный почтовый сервер.
  • Используйте подписи DKIM.
  • По мере отправки каждого сообщения помечайте их как отправленные в базе данных, но вам нужно хорошо знать, как работают транзакции и блокировки базы данных, чтобы это работало безопасно и избегало дублирования - делайте это правильно, и перекрывающиеся процессы работают нормально.
  • Вы можете создавать сообщения так быстро, как хотите, а ваш почтовый сервер будет обрабатывать очереди, дальнейшую доставку, повторные попытки и отказы.
  • Используйте адресацию VERP и передавайте отказы в обработчик отказов (имейте в виду, писать это не весело !), и сделайте так, чтобы в будущем они не отправлялись на обратные адреса.

Этот подход работает хорошо - именно так моя собственная система ([Smartmessages.net] (https://info.smartmessages.net/, встроенный в PHP) работает, и я могу поддерживать более 200 сообщений в секунду, используя несколько генераторов сообщений, работающих параллельно (транзакции базы данных FTW!).

Если вы находите все это слишком большим (это очень сложно), вам, вероятно, лучше использовать коммерческую службу отправки (например, мою собственную) или разместить самодельное решение, такое как Mailcoach от моих хороших друзей из Spatie. Любой из них будет работать хорошо, и ваш список довольно невелик - я часто работаю со списками, превышающими 100000.

person Synchro    schedule 17.11.2020
comment
Большое спасибо за ваш совет. В идеале я хотел бы продолжать следовать текущим направлениям, поскольку я перестраиваю систему, которая уже выполняет то, что я пытаюсь сделать, но не могу определить, как это сделать, из кодовой базы! Согласились, что отправка с одного скрипта обречена на неудачу. Возможно, маршрут диспетчера заданий / очередей окажется удачным. - person James B; 18.11.2020