Отдать письмо вебхуку вместо приёмника

http-delivery queue type
Обработчик, который живёт где угодно

Очередь вида http-delivery отдаёт письмо не приёмнику и не программе, а адресу в сети: запросом POST с типом application/json, по одному письму на запрос. Тело — объект JSON с сырым письмом и адресами конверта.

Успех — только ответ 2xx. Всё остальное считается временной неудачей: письмо остаётся в очереди и повторяется, а когда уйдёт в отказ, решает bounce-after. Это принципиальное отличие от вида pipe: там недоступность обработчика ничем не отличается от его поломки, здесь она честно превращается в очередь.

Что приходит в теле. Поле email_rfc822 — само письмо; msg_from и rcpt_to — адреса конверта; headers — массив заголовков парами «имя — значение». Если в письме встретился символ вне 7-битного ASCII, всё письмо кодируется base64, и рядом появляется email_rfc822_is_base64 со значением true.

Главная ловушка — обработчик отвечает 200 на всё. Тогда узел считает доставленным и то, что обработчик не смог разобрать, и письмо теряется без следа. Обратная ошибка не менее частая: обработчик отвечает 4xx на письмо, которое ему не нравится, а узел считает это временной неудачей и повторяет его до самого срока отказа.
Что делает Хаб. Не задействует, но это ближайший к нему вид доставки: обработчик отказов и жалоб у Хаба уже есть и живёт по HTTP. Разница только в том, что сегодня письма попадают в него не от узла напрямую. Когда дойдёт — брать надо именно этот вид, а не pipe: он переживает недоступность Хаба очередью, а не потерей.
Пример в конфигурации
# жалобы уходят обработчику, авторизация — из файла заголовков
<domain feedback.example.com>
    type http-delivery
    http-delivery-url https://hub.example.com/api/v1/feedback    http-delivery-extra-headers /etc/pmta/http-delivery-headers.txt
</domain>
Адрес обязан быть абсолютным, со схемой http или https, без учётных данных, строки запроса и якоря. Порт по умолчанию — 443 для https и 80 для http.
жёлтым — — имена директив, голубым — блоки. Так же они подсвечены и в тексте карточки.
▲

Типичные ошибки и проблемы

что делают не так и чем это кончается3 ошибки▶

Обработчик отвечает 200 на всё

§ 8.5

Чем чреватоУзел считает доставленным всё, включая то, что обработчик не смог разобрать. Письма исчезают без следа — ни в очереди, ни в отказах их нет.
Как заметитьВ учёте сплошные доставки, а в обработчике данных меньше, чем писем.
Как правильноОтвечать 2xx только после успешной обработки; на разбор, который не удался, — код вне 2xx.

Отвечают 4xx на письмо, которое обработчику не нужно

§ 8.5

Чем чреватоЛюбой ответ вне 2xx узел считает временной неудачей и повторяет письмо до срока отказа. Ненужное письмо будет стучаться в обработчик сутками.
Как заметитьОдни и те же письма приходят в обработчик снова и снова.
Как правильноПринимать такие письма ответом 2xx и отбрасывать у себя — различия между «не могу» и «не хочу» у этого вида нет.

Не обрабатывают base64

§ 8.5

Чем чреватоПри символе вне 7-битного ASCII всё письмо кодируется целиком, и email_rfc822 перестаёт быть читаемым текстом. Обработчик, не смотрящий на флаг, разберёт мусор.
Как заметитьЧасть писем разбирается неверно — обычно те, где есть кириллица.
Как правильноПроверять поле email_rfc822_is_base64; его отсутствие означает, что письмо не закодировано.
Совместимость
PowerMTA 6.0
описана в руководстве этой версии · платформа: любая
С какой версии директива доступна, вендор указывает не для всех — здесь пометки нет. Имя встречается и в издании руководства 5.0.
⇄

Связанные записи

4 связи

Как проверить на узле
Работает ли обработчик, видно по очереди: при недоступном адресе она растёт, а не теряет письма:
pmta show settings feedback.example.com/vmta1 | grep -E '^type|^http-delivery'
pmta show queues | grep -i feedback.example.com
Растущая очередь означает ответы не из семейства 2xx — обработчик недоступен или отвечает ошибкой. Хаб этот вид пока не задействует.
В Хабе
Цена ошибки
обратимо: вредит, пока стоит
Сценарии
Приём входящей почты · Инфраструктура трекинга