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 року. Того дня два листи з підтвердженням підписки не пішли: сайт не встиг за відведений час визначити адресу поштового сервера за його іменем. Журнал це чесно записав. Але про це нам не повідомило ніщо: сповіщення на провалений лист у нас немає, і ці два записи ми знайшли, коли самі відкрили журнал. Чи були це справжні підписники, чи тестові відправки, ми не знаємо.
Тобто урок першої частини вивчено наполовину. Тепер ми бачимо провали, якщо шукаємо їх. Наступний крок — щоб провал сам приходив повідомленням, як уже приходять тривоги про навантаження на сервер. Якщо вам потрібно, щоб хтось регулярно проходив ваші форми й дивився, чи доходять листи, це входить у супровід сайту; стан самого сервера й сайту закриває моніторинг доступності. Схожу історію про налаштування, яке «начебто працює», ми вже розбирали на прикладі стиснення сторінок.
Головне правило звідси коротке: підсистему, якої не видно на екрані, перевіряють відправкою, а не оглядом коду і не повідомленням «дякуємо».




