17 августа 2026 года мы прошли все формы на собственном сайте так, как их проходит клиент: заполнили, отправили, а потом пошли смотреть, что случилось дальше. Не в код и не на экран с благодарностью, а туда, куда заявка должна была попасть: в почтовый ящик, в журнал писем, в логи сервера.
Нашлись две подсистемы, которые не работали. Исходящие вебхуки падали на каждой заявке. Письмо-подтверждение клиенту не уходило. И никаких признаков поломки снаружи не было: форма говорила «спасибо», заявка сохранялась в базе, админка выглядела исправной.
Эта статья о том, почему так бывает и как за 15 минут проверить свою форму, не читая код.
Что именно было сломано
Вебхуки. Это уведомления, которые сайт шлёт в другую систему, когда что-то произошло: новая заявка, новый бриф, новая подписка. В нашем коде список событий был записан с одними ключами, а все вызовы обращались к нему с другими. Ключа, к которому обращались, не существовало, поэтому вместо названия события в запрос к базе уходило пустое значение, и запрос падал. Таких мест в коде было 16: формы заявок, всплывающие окна, подписка и все шесть событий брифа. Файл со списком событий в таком виде лежал в репозитории с 20 января 2026 года до исправления 17 августа.
Почта. В проекте было два почтовых модуля: старый, который умел слать письма только через один сторонний сервис, и новый, который берёт настройки из админки, шлёт через наш почтовый сервер и ведёт журнал. Путь импорта в коде был одинаковым для обоих, и среда выполнения выбирала старый файл, а не папку с новым модулем. Новый модуль был написан, но ни одно письмо до него не доходило. Ключа к стороннему сервису в рабочей среде на момент проверки не было, поэтому на каждую заявку в логе появлялась строка о том, что ключ не настроен, а клиент оставался без письма. Кнопка «отправить тестовое письмо» в админке падала по той же причине.
В тот же день, продолжая разбор, мы нашли ещё две вещи. Письма о коммерческих предложениях не отправлялись ни разу: код брал из старого модуля три функции, которых там никогда не было. А ещё четыре места слали почту в обход настроек: приветственное письмо подписчику, рассылка кампании, лид-магнит и еженедельный отчёт.
Почему этого никто не видел
Причин три, и каждая по отдельности привычна.
Первая: ошибки перехватывались и молча проглатывались. Отправку письма и вебхука обернули в перехват ошибок, чтобы сбой почты не срывал сохранение заявки. Само решение правильное: заявка важнее письма. Но после перехвата ошибку лишь писали в лог, который никто не читал.
Вторая: журнал писем сам не работал. Модуль, который должен был записывать каждую отправку, передавал в базу значение, которое она не принимала, и эта ошибка тоже проглатывалась. Поэтому в журнале писем в админке не было ни одной записи. Пустой журнал легко прочитать как «писем пока не было», а не как «журнал сломан». В базе первая запись датирована 18 августа 2026 года, то есть следующим днём после исправления.
Третья: проверка типов видела часть этих дефектов с самого начала, но сборка её игнорирует. Отсутствующие функции для писем о предложениях были в отчёте проверки типов ещё до наших правок. В начале той сессии проверка типов выдавала 374 ошибки, после двух исправлений 318. Когда ошибок сотни, ещё три строки среди них не замечает никто.
Ни одна из этих причин не о небрежности конкретного человека. Это свойство любой подсистемы, которую не видно на экране: она может не работать месяцами, и сайт при этом будет выглядеть вполне исправным.
Кто на самом деле пострадал
Здесь важно не преувеличить. Таблица подписок на вебхуки в нашей базе пуста: ни одна внешняя система на них не была подписана, так что события фактически никто не потерял. Массовых рассылок, по данным того же разбора, никто не запускал. А вот письмо-подтверждение на момент проверки не уходило ни одному клиенту, а письма о предложениях не могли уйти вообще. Сколько писем потерялось за всё время, мы уже не установим: журнал, который должен был это показать, тоже не работал.
Как проверить свою форму за 15 минут
Не нужно читать код. Нужно отправить заявку и пройти её путь до конца.
- Отправьте заявку с меткой. В поле имени или комментария впишите что-то уникальное, например
ТЕСТ-1609-форма-контакты. Указывайте свою реальную почту, а не адрес, который вы не открываете. Сделайте это для каждой формы отдельно: контакты, обратный звонок, всплывающее окно, оформление заказа, подписка.
- Проверьте обе стороны. Письмо-подтверждение должно было прийти вам как клиенту. Уведомление о заявке должно было прийти менеджеру. Ищите метку и во «Входящих», и в «Спаме», и в «Промоакциях».
- Посмотрите, откуда пришло письмо. В Gmail это «Показать оригинал». Строка
Authentication-Results должна содержать spf=pass и dkim=pass. Если там fail или ничего, письмо сегодня дошло, но в следующий раз может оказаться в спаме.
- Найдите следы на сервере. Если у вашей системы есть журнал писем, метка должна быть в нём. Если журнала нет, поищите в логах:
grep -iE "mail|smtp|email" /путь/к/error.log | tail -50
Строки вроде «not configured», «timeout», «connection refused» рядом со временем вашей заявки означают, что письмо не ушло, хотя форма и поблагодарила.
- Посчитайте пути отправки. Для технических читателей это самый полезный шаг. Поищите в коде все места, которые шлют почту:
grep -rnE "sendMail|mail\(|emails\.send|wp_mail|->send\(" --include=*.php --include=*.ts --include=*.js . | grep -v node_modules
Если мест больше одного и они пользуются разными настройками, у вас та же ситуация, что была у нас: почините одну форму, а другая так и будет молчать.
- Проверьте, не пуст ли журнал. Если в админке есть журнал писем и он пуст на живом сайте с заявками, сначала подозревайте журнал, а не отсутствие писем.
Что мы изменили и чего это не решило
Мы сделали один путь отправки для всех писем: тот, который берёт настройки из админки и записывает каждую попытку в журнал. Старый клиент стороннего сервиса убрали совсем, чтобы вторым путём никто не воспользовался снова. Ключи событий вебхуков привели к тому виду, в котором их вызывает код. Ошибки журнала исправили, и с 18 августа 2026 года он пишет каждую отправку.
Чего это не решило, показал день 8 сентября 2026 года. В тот день два письма с подтверждением подписки не ушли: сайт не успел за отведённое время определить адрес почтового сервера по его имени. Журнал это честно записал. Но об этом нам не сообщило ничто: уведомления о проваленном письме у нас нет, и эти две записи мы нашли, когда сами открыли журнал. Были ли это настоящие подписчики или тестовые отправки, мы не знаем.
То есть урок первой части усвоен наполовину. Теперь мы видим провалы, если ищем их. Следующий шаг — чтобы провал сам приходил уведомлением, как уже приходят тревоги о нагрузке на сервер. Если вам нужно, чтобы кто-то регулярно проходил ваши формы и смотрел, доходят ли письма, это входит в сопровождение сайта; состояние самого сервера и сайта закрывает мониторинг доступности. Похожую историю о настройке, которая «вроде бы работает», мы уже разбирали на примере сжатия страниц.
Главное правило отсюда короткое: подсистему, которую не видно на экране, проверяют отправкой, а не осмотром кода и не сообщением «спасибо».