Как я могу сделать электронную почту транзакционной в PHP и MySQL?

0

Я хочу отправить электронное письмо своим пользователям приложений, чтобы каждое электронное письмо отправлялось только один раз. Я буду записывать электронную почту в базе данных. Если я использую этот порядок операций:

  • Вставить в базу данных
  • Отправить электронное письмо
  • Фиксировать

Существует вероятность того, что script истечет сразу после отправки электронной почты (шаг № 2) и перед выполнением фиксации (шаг № 3). В этом случае изменение шага № 1 не будет выполнено, и задание по отправке электронной почты не сможет узнать, что письмо было успешно отправлено в последний раз, чтобы снова отправить электронное письмо.

Есть ли выход или мне приходится жить со случайными дублирующими письмами?

  • 0
    почему бы не отслеживать электронные письма, которые отправляются через БД? Чтобы вы не пересылали электронные письма? Также попробуйте метод обработки исключений try / catch для работы с таймаутами.
  • 0
    @Jakub, я имел в виду тайм-аут сценария, то есть когда веб-сервер решает, что вызываемый им скрипт слишком долго работает и его следует уничтожить. Я не знаю, может ли try / catch помочь в этом сценарии
Показать ещё 2 комментария
Теги:
transactions

4 ответа

0
Лучший ответ

Просто подумал над своим вопросом. Вот что я думаю сейчас:

Задачами отправки электронной почты были:

  • Вставить в базу данных
  • Отправить электронное письмо
  • Фиксировать

Электронная почта не может быть выполнена транзакцией, потому что шаг № 2 (выше) не является частью транзакции, даже если она выполняется во время транзакции.

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

  • Принять заявку на отправку электронной почты, но не отправлять электронную почту до тех пор, пока не будет выполнена фиксация.
  • Сделать коммит неудачным, если сообщение не отправлено.
  • Отмените отправленное задание, если транзакция отменена.

Я не знаю о таком сервере электронной почты.

Нишант в своем ответе предложил следующие шаги:

  • Вставьте данные перед отправкой почты. И установите статус отправки
  • Отправить письмо
  • на основе результата на шаге (2), обновить строку либо неудачно, либо отправлено успешно.

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

До сих пор, я думаю, мне просто придется жить со случайными дублирующимися письмами.

3

Короче говоря: вы не можете совершать транзакции по электронной почте.

В лучшем случае вы знаете, что ваш SMTP-сервер получил ваш запрос на отправку сообщения. Однако у вас нет способа узнать, было ли оно отправлено, получено или отскочено.

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

2

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

Итак, вы готовите запросы перед отправкой почты, а затем отправляете ее после отправки.

Дополнительная информация

http://dev.mysql.com/doc/refman/5.0/en/commit.html

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

1

хорошо вы можете сделать столбец status, который может быть enum или int со значениями, представляющими sending, failed, sent_successfully

Теперь вы делаете это:

  • Вставьте данные перед отправкой почты. И установите status в sending
  • Отправить письмо
  • на основе результата на этапе (2), update строки либо failed, либо sent_successfully.

Вам также может понравиться столбец tries и пакетный процесс, который отправляет письма failed каждые 30 минут, если tries < TRY_THRESHOLD. Затем установите status в failed_permanently или sent_successfully и запишите ошибку.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню