Необходимо чтобы поступающая почта передавалась PHP (вместе с аттачментом) для совершения каких-то действий, например, для публикации комментария к записи в блоге.
Основное условие — сообщения не должны теряться. То есть если сервер с PHP лежит, сообщение должно быть обработано им позже.
Особенность задачи — почтовых адресов, с которых нужно получать почту, может быть создано очень много. Эти почтовые адреса будут работать также на отправку почты.
Пока что я вижу несколько вариантов реализации:
1. Вызывать PHP скрипт при приеме почты и передавать туда сообщения. В данном случае не понятно как обеспечить надежность доставки — сообщения могут теряться.
2. Найти способ взаимодействия почтового сервера с сервером AMQP, отправлять сообщения туда. В таком случае, почтовый сервер, вероятно, должен уметь отвечать на письмо ошибкой, если AMQP вдруг лежит.
3. По крону вызывать PHP скрипт, который будет подключаться к почтовым ящикам, проверять наличие новой почты и делать с ней операции. Не возникнет ли здесь проблема в том, что почтовых адресов может быть очень много? Кроме того, вызывает сомнения масштабируемость такого решения.
Сталкивались ли вы с такой задачей и какой вариант реализации вы могли бы предложить? Есть ли рекомендации по конкретным технологиям и библиотекам (postfix и т.д.)?
Решение 1 в случае с Postfix просто и элементарно. Почему вы так боитесь за надёжность доставки в этом случае? Очередь сделает для вас Postfix, а скрипту он будет скармливать письма по одному на stdin: отдал одно письмо, скрипт завершился — запускает следующий процесс и следующее отдаёт ему. У одного из наших клиентов такая схема работает уже несколько лет, только на приёмке скрипт не на PHP а на Python (когда-то был на TCL, но поддерживать это при условии глючности TCLной библиотеки MIME было неудобно). Все письма перенаправляются туда с помощью always_bcc, т.е. скрипт фактически обрабатывает вообще всю почту, порядка сотни адресов.
Решение 2 — вы добавляете между почтовым сервером и скриптом лишний слой, задачу которого вообще-то решает менеджер очередей самого почтового сервера.
Решение 3 — работает много где, но с большим числом ящиков неудобно. Завернуть всех в один и прверять его — возможно, но опять же между скриптом и почтовым сервером появляется дополнительный слой. С другой стороны, оно универсально, вы сможете любой сервер подружить с любым скриптом. Этот подход, например, используется внутри OTRS.
Что если в решении 1 сервер с PHP лежит или лежит сервер базы данных (php ничего не запишет и вернет ошибку)? Если я верно понимаю, то письмо не будет обработано в этом случае.
Думаю, решение такое — postfix всегда будет обращаться к локальному PHP скрипту, который уже сам разберется с тем, лежит ли сервер приложения или нет и при необходимости повторит попытку.
Решали такую задачу.
По совокупности параметров и с учетом ограниченности бюджета сделали так.
Со всех адресов идет форвард/копия на один адрес, откуда они и забираются пхп скриптом по крону.
Тупо, просто, надежно, масштабируемо… дешево. Можно было сделать лучше, но было бы дороже:)
Они все чисто 20/80. То есть болшинство писем да, распарсят. А вот с остальным придётся нехило подолбаться. Вы же не скажете конечному пользователю «Ну это ваш яху/аутлук/of365 письмо не правильно составляют, идите нахрен». У них то всё в почтовых клиентах открывается. На резонный вопрос «почему они могут, а вы нет», ответ прост — они этим(парсингом) всю историю продукта занимаются.
Например, ни одна библиотека из перебраных мной не обрабатывает то, что генерирует комманда*, более того иногда такие вещи приводят к натуральному отказу в обслуживании (бесконечные циклы)
И это еще самая простая проблема.
*)
uuencode filz.zip file.zip | mail -s testmessage test@test.test
P.S. если формат действительно не соответствует rfc5381/5382, я пошлю с этой программой. Не обязан разбирать. Есть стандарт, остальное — за дополнительные очень большие деньги.
Конечно не соответствует. Аргумент в другом. У пользователеля в почтовом клиенте все открывается, в вашей программе нет и пользователю внезапно плевать на RFC и т.д.