Webhook валидации email: как получать результат проверки без опроса API
Webhook валидации это HTTP-запрос, который сервис проверки сам отправляет на ваш сервер, когда задача закончилась. Вместо того чтобы раз в несколько секунд спрашивать API «готово?», вы оставляете адрес, и о готовности сообщают вам.
Схема обычная для долгих операций. Проверка списка идёт минуты, у крупной базы дольше, и держать всё это время соединение открытым незачем. Сервис принимает задачу, отдаёт её номер и уходит работать, а результат приходит потом, отдельным запросом в обратную сторону.
Webhook или опрос статуса
При опросе (polling) приложение каждые несколько секунд дёргает эндпоинт статуса, и ничего сложнее тут нет. В документации uChecker рекомендуемый интервал 5–10 секунд. Задача, которая идёт двадцать минут, при опросе раз в десять секунд даст около 120 запросов, и полезен из них последний.
С вебхуком запрос один, и приходит он сразу после завершения, а не на следующем витке опроса. У опроса свои плюсы. Его легче отлаживать, ему не нужен публичный адрес, он работает из-за NAT и с ноутбука. Скрипту, который раз в месяц чистит базу, его хватит. Вебхук окупается там, где проверок много или где за результатом стоит автоматическая цепочка.
Как это устроено в uChecker
Адрес передаётся прямо в запросе на проверку, в поле webhook_url. Его принимают оба метода: POST /api/v1/validate/bulk для списка и POST /api/v1/validate/single для одного адреса. Отдельной настройки в кабинете нет, так что у каждой задачи может быть свой адрес.
Проверка одного адреса у нас тоже асинхронная. Ответ сразу содержит task_id, а сама проверка занимает от нескольких секунд до двух минут, смотря какой домен. Поэтому вебхук пригодится и для формы регистрации, не только для больших списков.
Когда задача завершилась, на адрес уходит POST с Content-Type: application/json. В теле пять полей:
task_id, номер задачи;status, одно из completed, failed или unknown;summary, сводка с полями total, good, bad и unknown;finished_at, время завершения в формате ISO 8601;error_text, причина, если задача упала, иначе null.
Самих адресов в теле нет, даже когда проверялся один. Вебхук только сообщает, что пора забирать, а результат берётся запросом GET /api/v1/tasks/{task_id}/results с вашим ключом. И одна тонкость: в сводке вебхука в bad входят и адреса с пометкой риска, а в аналитике задачи они идут в unknown. Такую разбивку отдаёт GET /api/v1/tasks/{task_id}/analytics.
Повторы и что должен отвечать ваш сервер
Доставка засчитывается, если сервер ответил кодом 2xx за 30 секунд; документация просит отвечать 200. Другой код, обрыв или таймаут запускают повтор через 30 секунд, потом через минуту, через 5 и через 15 минут. Всего пять попыток. Если ваш сервер лежит дольше двадцати минут с небольшим, уведомление не придёт, но задача и её результаты никуда не денутся, их можно забрать опросом.
Отсюда два правила для обработчика. Первое: отвечать 200 только после того, как данные записаны. Не удалась запись в базу, лучше вернуть 500 и дождаться повтора, чем подтвердить приём и потерять результат.
Второе: обработчик должен спокойно переживать один и тот же запрос дважды. Бывает, что вы всё обработали, а ответ не дошёл, например потому что обработка заняла больше 30 секунд. Сервис сочтёт попытку неудачной и пришлёт то же самое ещё раз. Номер задачи есть и в теле, и в заголовке X-Webhook-Task-Id; по нему проверяйте, не обработана ли задача уже. Номер попытки лежит в X-Webhook-Attempt.
Тяжёлую работу (скачать результаты, разложить их по CRM) удобнее делать после ответа: принять запрос, положить номер задачи в свою очередь, ответить 200.
Защита endpoint
Адрес вебхука открыт в интернет, и прислать на него POST может кто угодно. Чем это грозит, зависит от того, насколько обработчик доверяет телу запроса. Обычно используют такие способы защиты:
- HMAC-подпись. Сервис подписывает тело общим секретом и кладёт подпись в заголовок, вы вычисляете её сами и сравниваете. Так делает, например, GitHub (заголовок X-Hub-Signature-256), и его документация отдельно просит сравнивать подписи функцией с постоянным временем, а не обычным ==.
- Секрет в адресе. Случайная строка в пути, которую знаете только вы и сервис. Слабее подписи: адрес может осесть в логах прокси. Но лучше, чем ничего.
- Фильтр по IP. Держится, пока у сервиса не поменялись адреса, поэтому годится как дополнение к другим мерам.
- HTTPS. Это не аутентификация, но без шифрования запрос, а вместе с ним номер задачи, сводка и секретный токен из адреса, читается на любом узле по пути.
uChecker тело не подписывает. Поэтому рабочая схема складывается из секретного токена в webhook_url, HTTPS и правила не верить цифрам из тела. Получив уведомление, обработчик сам идёт в API со своим ключом и забирает статус и результаты. Поддельный запрос в худшем случае заставит лишний раз сходить за данными, а подменить их не сможет.
Адреса во внутренних сетях (localhost, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 и похожие) uChecker не вызывает. Обработчик для тестов придётся выставить наружу, хотя бы через туннель.
Три сценария
- Чистка базы перед рассылкой. Скрипт выгружает сегмент из CRM, отправляет на проверку и завершается. Вебхук запускает следующий шаг: забрать результаты, снять плохие адреса, написать в рабочий чат, что база готова.
- Проверка при регистрации. Аккаунт создаётся сразу со статусом «почта не подтверждена», адрес уходит на проверку в фоне. Пришёл плохой результат, человека просят указать другой адрес. Мгновенную реакцию в самой форме дают синтаксис и подсказки при опечатках. Подробнее о связке в статье про валидацию в формах.
- Поток лидов. Контакты из партнёрских форм и импорта копятся в очереди, каждая пачка уходит на проверку, и по вебхуку решается, куда она поедет дальше.
Вебхуки почтовых сервисов о доставке, отказах и открытиях устроены похоже, но это другая история, она разобрана в статье про webhook для email-событий.
Источники
Ключ API лежит в личном кабинете. Подключите uChecker, первые 100 проверок бесплатно.
Марк Аврилов · Автор материала
Опубликовано Обновлено
