Подача по HTTPS на своём приёмнике, по образцу SparkPost

Transmissions API
Вход со своим всем — портом, ключами и источником

Письмо подаётся запросом HTTP, и один запрос может нести как одного получателя, так и нескольких. Тело письма можно собирать подстановками по образцу слияния.

Собирается вход из трёх частей. Приёмник <transmissions-api-listener> — обязательно с сертификатом, потому что снаружи это HTTPS. Блок <transmissions-api> — там живут ключи api-key и настройки журналирования. И блок источника с зарезервированным именем {transmissions-api}, через который к такой почте применяются обычные настройки подачи: разрешения на служебные заголовки, выбор потока и всё прочее.

Постоянные соединения поддерживаются по правилам RFC 7230. Но с оговоркой, которая ловит клиентов: каждый запрос в таком соединении обязан нести Content-Length, иначе ответом будет 400 bad request. Заголовок keep-alive со своими параметрами MTA не понимает.

Форма запроса намеренно близка к интерфейсу SparkPost — вплоть до того, что неподдерживаемые поля того интерфейса названы причиной отказа. Клиент, написанный под SparkPost, чаще всего работает, а где не работает — получает внятный отказ.

Главная ловушка — забытый Content-Length в постоянном соединении. Отказ приходит не на письмо, а на запрос — 400 bad request, — и клиент, который прекрасно работал без постоянных соединений, начинает сыпаться при их включении. Причина при этом в заголовке, а не в содержимом.

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

Что делает Хаб. Не задействует: ни блока входа, ни приёмника в его конфигурации нет — подача идёт обычным SMTP под логином.

Собственный HTTP-вход у Хаба на узле всё-таки есть, но другой: веб-монитор и API управления с ключом http-api-key. Он про управление узлом, а не про подачу почты, и путать их не стоит.

Пример в конфигурации
# три части входа: приёмник с сертификатом, ключи и настройки источника
<transmissions-api-listener 1.2.3.4:8585>
    tls-certificate /etc/pmta/transmissions-api-certificate.pem</transmissions-api-listener>

<transmissions-api>
    api-key 14ac5499cfdd2bb2859e4476d2e5b1d2bad079bf
    max-message-size 100M
</transmissions-api>

<source {transmissions-api}>
    process-x-virtual-mta yes
    process-x-job yes
</source>
Имя источника здесь зарезервировано — им MTA называет почту, пришедшую этим входом. Без такого блока обычные настройки подачи к ней не применятся.
жёлтым — — имена директив, голубым — блоки. Так же они подсвечены и в тексте карточки.
▲

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

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

Включают постоянные соединения без Content-Length

§ 8.1

Чем чреватоКаждый запрос в таком соединении обязан нести длину тела, иначе ответом будет 400 bad request. Клиент, работавший без постоянных соединений, начинает сыпаться сразу после их включения.
Как заметитьОтветы 400 на запросы, которые прежде проходили.
Как правильноДобавить Content-Length в каждый запрос либо отключить постоянные соединения у клиента.

Настраивают вход без блока источника

§ 8.1.1

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

Принимают сжатые запросы без предела на размер

§ 8.1

Чем чреватоРуководство советует ограничивать наибольший размер письма именно из-за сжатия: без предела сжатый запрос разворачивается в памяти узла во что угодно.
Как заметитьРасход памяти узла растёт на запросах небольшого размера.
Как правильноЗадать предел строкой размера в блоке входа — она для этого и нужна.
Совместимость
PowerMTA 6.0
описана в руководстве этой версии · платформа: любая
С какой версии директива доступна, вендор указывает не для всех — здесь пометки нет. Имя встречается и в издании руководства 5.0.
Как проверить на узле
Настроен ли вход — видно по трём блокам сразу; работает ли — проверяется запросом:
grep -n -A4 '^<transmissions-api' /etc/pmta/config
curl -sS -o /dev/null -w '%{http_code}\n' -H 'Authorization: <ключ>' https://<адрес-узла>:8585/api/v1/transmissions
Ответ 400 при постоянном соединении обычно означает не отказ в подаче, а отсутствие Content-Length в запросе. Отсутствие блоков означает, что вход не настроен вовсе.
В Хабе
Цена ошибки
обратимо: вредит, пока стоит
Сценарии
Подключить платформу отправки · Шифрование соединений