У вас одне завдання: пояснити, чому лист не дійшов. Не «ймовірно, він потрапив у спам». Не «Microsoft/Gmail ненадійні». Потрібно вказати на хоп, де повідомлення перестало поводитись як повідомлення і почало поводитись як чутка.
Найшвидший шлях — ланцюжок заголовків Received. Це найближче, що є в пошті до «чорної скриньки» — безладне, непослідовне й іноді підроблене. Але якщо читати його так, як SRE читає розподілений трейс, зазвичай можна визначити область збою за кілька хвилин.
Ментальна модель: що насправді означає заголовок Received
Пошта передається хоп за хопом. Кожен SMTP-сервер, який приймає повідомлення і передає його далі, має проставити новий заголовок Received зверху. Отже ви отримуєте стек: найновіший хоп — зверху, найстаріший — унизу.
Уявіть кожен хоп як невеликий контракт: «Я, сервер X, отримав це повідомлення від Y у час T використовуючи протокол P і передаю його далі». Контракт пише X, а не Y. Оце ключ. Саме хоп, що написав рядок, ви можете перевірити в логах і метриках.
Якщо ви звикли до трасування в розподілених системах, це — по суті список спенів без ідентифікаторів. Немає глобального trace ID. Немає канонічної схеми. Багато креативної пунктуації. Проте, якщо читати з правильною долею скептицизму, цього зазвичай достатньо.
Дві правило, які врятують вас від пустих зустрічей:
- Рядки Received — це доказ лише в межах межі довіри. Усе, що нижче вашого першого довіреного входу, може бути підроблене.
- Більшість випадків «відсутнього листа» насправді є «затриманим листом». Ваше завдання — визначити, де була введена затримка і чи це очікувано (повторна спроба) або патологічно (провал черги, політична блокування, неправильна маршрутизація).
Цікаві факти й історичний контекст (коротко, конкретно)
- SMTP передує більшості сучасних механізмів автентифікації. Ядро протоколу стандартизовано на початку 1980-х; додатки для автентифікації з’явилися десятиліттями пізніше.
- Заголовки Received старіші за спам. Вони були створені для трасування й налагодження маршруту пошти, а не для роботи в ворожому середовищі.
- Формат заголовків «структурований ніби», але не суворий. Сервери заохочуються додавати деталі, тому ви бачите вендор-специфічні фрази й креативні пробіли.
- Часові пояси — постійне джерело проблем. Хопи можуть показувати «рух часу назад», якщо годинник сервера неправильний або він використовує дивний зсув.
- Message-ID не гарантовано унікальний. Більшість MTA генерують нормальні ID, але зламані клієнти або деякі пристрої повторно використовують або спотворюють їх.
- Greylisting став популярним як маловитратний антиспам. Він навмисно затримує перші спроби доставки; у Received заголовках часто видно розриви між спробами.
- SPF перевіряє конвертний відправник, а не видимий From. Люди й досі плутають це, у тому числі ті, у кого в титулі є «Директор».
- DKIM підписує заголовки й тіло, але не всю «істину». Він не перевіряє ланцюжок Received; він перевіряє цілісність контенту від підписувача.
- Великі провайдери використовують кілька шарів обробки пошти. Ви можете бачити внутрішні хопи, які не відповідають 1:1 вашим уявленням про «поштовий сервер».
Анатомія рядка Received: поля, що важливі, і поля, які брешуть
Типовий заголовок Received може виглядати так (не прив’язуйтесь; реальність гірша):
cr0x@server:~$ sed -n '1,8p' message.headers
Received: from mail-out.example.net (mail-out.example.net [203.0.113.10])
by mx.google.com with ESMTPS id x12-20020a17090a000000b003e000000000si1234567pja.12.2026.01.04.10.11.12
for <user@example.com>
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
Sun, 04 Jan 2026 10:11:12 -0800 (PST)
Received: from app01.corp.example (app01.corp.example [10.20.30.40])
by mail-out.example.net (Postfix) with ESMTPA id 4A1B2C3D4E
for <user@example.com>; Sun, 04 Jan 2026 18:11:10 +0000 (UTC)
Що важливо:
- «by»: сервер, що додав цей рядок. Це ваш анкер у логах. Якщо ви не маєте доступу до логів на «by», ваші опції зменшуються.
- «from»: хто підключився до «by». Може бути ім’я хоста + IP. Ім’я хоста часто — зворотний DNS або те, що заявив пір. IP підробити складніше на рівні TCP (але NAT і проксі ускладнюють ситуацію).
- Клаузула протоколу (
with ESMTP,with ESMTPS,with LMTP): каже, чи використовувалось TLS і чи була автентифікація (ESMTPAзазвичай означає автентифіковану відправку). - Мітка часу: критична для аналізу затримок. Ставтесь до неї як до будь-якого розподіленого таймстемпу: довіряйте лише якщо годинники адекватні.
- ID черги: Postfix, Exchange та інші часто ставлять внутрішній ID. Це золото, бо корелюється безпосередньо з логами.
Що часто брешуть або вводять в оману:
- Імена, які надає клієнт. Деякі MTA включають те, що клієнт сказав у HELO/EHLO. Це не ідентичність; це рядок.
- Недостовірні нижчі хопи. Усе, що додано сервером поза вашою зоною довіри, може бути сфабриковане спамером або похибкою ретранслятора.
- Надмірна впевненість у форматуванні. Деякі сервери дивно згортають рядки; деякі опускають поля; деякі вміщують усе в один рядок, ніби їм платять за символи.
Жарт №1: Заголовки пошти схожі на хроніки інцидентів: кожен додає рядок, і тим не менш це не відповідає на питання «хто останнім чіпав продакшн?»
Правила порядку: знизу вгору, з гострими краями
Найстаріший хоп — внизу. Найновіший хоп — зверху. Отже, ви читаєте заголовки Received знизу вгору, щоб простежити шлях повідомлення вперед у часі.
Гострі краї:
- Зсув годинника може змусити час виглядати так, ніби він рухається назад. Якщо один сервер відстає на п’ять хвилин, ви побачите негативні часи транзиту. Не панікуйте; перевірте NTP.
- Локальна доставка може не додавати рядок Received. Іноді фінальна передача — у поштовий скриньку або на фільтр — не супроводжується новим заголовком.
- Шлюзи можуть згортати хопи. Шлюз безпеки може прийняти вхідну пошту і потім заново ввести її в мережу, додаючи рядки на кшталт «from gateway by internal-mx», але ви не побачите upstream-складність.
- Розсилки та форвардери можуть створювати «нові» повідомлення з новими Message-ID і зміненими заголовками, водночас візуально виглядаючи як той самий контент для користувача.
Межі довіри: яким Received рядкам можна вірити
Єдині Received заголовки, яким слід довіряти — ті, що додані системами, яким ви довіряєте: ваші MX, ваш вхідний шлюз, внутрішні ретранслятори, сервіс подачі (submission).
Усе, що перед першим довіреним хопом, — «доказ, наданий користувачем». Корисно, але не прийнятно як доказ. Це не параноя; це вівторок.
Практичний підхід:
- Визначте перший хоп, під вашим контролем. Це зазвичай ваш MX, вхідний шлюз або вхід хостингу провайдера.
- Позначте все, що нижче, як недовірений ланцюг.
- Скорелюйте довірений хоп з логами, використовуючи queue ID, Message-ID і мітку часу.
Якщо ви управляєте системою, яка приймає пошту з інтернету безпосередньо, дотримуйтеся практик, що роблять ваші власні Received рядки корисними: включайте IP підключення, вказуйте інформацію про TLS, коли вона є, додавайте queue ID і тримайте годинники синхронізованими.
Затримки: як помітити черги, повторні спроби, greylisting і зворотний тиск
«Збої» в доставці часто насправді є очікуванням доставки. Ваше завдання — класифікувати це очікування:
1) Затримка в черзі на боці відправника
Симптом: великий часовий розрив між найнижчим «клієнт → MTA відправника» Received і наступним хопом «MTA відправника → ваш MX».
Інтерпретація: відправник прийняв повідомлення, але не доставив його оперативно. Причини: завантаження вихідної черги, проблеми DNS, обмеження швидкості, політичні блокування або відправник обмежується одержувачами.
2) Greylisting / тимчасові відмови
Симптом: повторні спроби відображені в логах (не завжди в заголовках), з розривом у хвилини до остаточного прийняття. У заголовках ви можете побачити лише остаточну спробу з міткою часу значно пізнішою за заявлений користувачем час відправлення.
Інтерпретація: одержувач відповів 4xx на ранні спроби. Відправник повторив спробу. Це в певних екосистемах нормальна практика, але фактично це бізнес-рішення, замасковане під SMTP.
3) Черги на вході в вашому шлюзі або MX
Симптом: повідомлення прийнято вашим периметром, але воно пізно з’являється в скриньці. У заголовках видно швидку передачу до шлюзу, а потім внутрішні «by» хопи з мітками часу, що повільно просуваються вперед.
Інтерпретація: внутрішній фільтр, сканування контенту, зворотний тиск від зберігання скриньок або внутрішня маршрутизація. Тут важливі ваші дашборди.
4) Політичні затримки й карантин
Симптом: заголовки показують прийняття, але користувач ніколи не бачить повідомлення. Логи показують його перенаправлення в карантин, модерацію або утримання для ручного перегляду.
Інтерпретація: це не «злам доставки». Це політичне рішення. Трактуйте його як таке: знайдіть правило політики, обґрунтуйте й відкоригуйте за потреби.
5) Тихе відкидання (рідко, але трапляється)
Справжні тихі відкидання рідше, ніж люди думають, бо SMTP транзакційний. Але вони трапляються в екосистемах: фільтри можуть відкинути, скриньки відкинути, а деякі неправильно налаштовані системи приймають, а потім втрачають. Ви шукаєте, де відбулась остання довірена реєстрація отримання, і що система робила після цього.
Сигнали безпеки навколо Received: SPF, DKIM, DMARC, ARC і чому це важливо для збоїв доставки
Received заголовки показують шлях. Результати автентифікації показують, наскільки історія ідентичності повідомлення відповідає реальності — принаймні настільки, щоб провайдери прийняли його.
Authentication-Results — ваш друг
Багато систем додають заголовок Authentication-Results. Він може містити оцінки SPF, DKIM, DMARC. Його пише приймач, тож у межах довіри він цінний.
Що з ним робити:
- Якщо SPF не пройшов, перевірте SPF-запис домену відправника і вирівнювання IP, що відправляв.
- Якщо DKIM не пройшов, перевірте домен підпису, селектор, питання канонізації і чи не модифікував посередник тіло/заголовки.
- Якщо DMARC не пройшов, перевірте вирівнювання між доменом у From і доменами SPF/DKIM; також перевірте політику (reject/quarantine/none).
ARC може пояснити «форвардинг зламав DMARC»
Форвардери й розсилки часто ламають DKIM (через модифікації) і SPF (через повторну відправку з їхніх IP). ARC (Authenticated Received Chain) дозволяє посередникам зберегти результати автентифікації upstream. При діагностиці проблем, пов’язаних із пересиланням, наявність ARC і його валідація можуть перетворити «таємницю» на «очевидне».
Використовуйте сигнали автентифікації, щоб вирішити, чи злам стався через транспорт або політику. Якщо транспорт в порядку, але DMARC провалюється зі строгою політикою, ви не налагоджуєте мережу. Ви налагоджуєте ідентичність і вирівнювання.
Швидкий план діагностики
Потрібна швидкість? Не читайте весь роман заголовків. Зробіть так:
Перше: знайдіть останній довірений «by» хоп
- Знайдіть верхній Received рядок, написаний отримуючою системою, якій ви довіряєте (ваш MX / шлюз / провайдерський інгрeс).
- Витягніть: мітку часу, queue ID (якщо є), IP підключення і «for <одержувач>».
- Рішення: якщо у вас немає довіреного хопа, у вас немає доказів. Попросіть відправника надати повні заголовки з їхнього надісланого елементу або журнали від адміністратора відправника.
Друге: класифікуйте домен збою
- Не прийнято вашим периметром: немає довіреного Received рядка → проблема на боці відправника або в Інтернеті (DNS, маршрутизація, репутація).
- Прийнято периметром, але не доставлено: довірений Received є → внутрішній пайплайн (фільтрація, скринька, маршрутизація, карантин).
- Доставлено, але «відсутнє»: заголовки показують фінальну доставку, але користувач не може знайти — клієнтські правила, пошук у поштові, теки або архівація.
Третє: вимірюйте затримки між хопами
- Читайте Received заголовки знизу вгору у межах довіреного сегмента.
- Обчисліть дельти часу між суміжними хопами.
- Рішення: хоп з найбільшою дельтою — там шукайте черги, обмеження або утримання.
Четверте: корелюйте з логами за допомогою ID
Queue ID, Message-ID і адреса отримувача — ваші ключі для приєднання. Візьміть два; використайте три, якщо можете.
П’яте: вирішіть, що ви повідомите людям
Не кажіть «пошта затримується». Скажіть «прийнято нашим шлюзом о 10:11:12 PST, утримувалося в контент-скануванні протягом 34 хв через чергу sandobox, потім доставлено». Люди більше ненавидять невизначеність, ніж погані новини.
Практичні завдання (з командами, тлумаченням виводу і рішеннями)
Нижче — реальні завдання, які можна виконати на поширених Linux-MTA й інструментаріях. Кожне включає: команду, приклад виводу, що це означає і яке рішення прийняти.
Завдання 1: витягти і переглянути лише ланцюжок Received (швидка перевірка)
cr0x@server:~$ awk 'BEGIN{RS="";FS="\n"} {for(i=1;i<=NF;i++) if($i ~ /^Received:/) print $i}' message.eml
Received: from app01.corp.example (app01.corp.example [10.20.30.40]) by mail-out.example.net (Postfix) with ESMTPA id 4A1B2C3D4E for <user@example.com>; Sun, 04 Jan 2026 18:11:10 +0000 (UTC)
Received: from mail-out.example.net (mail-out.example.net [203.0.113.10]) by mx.google.com with ESMTPS id x12-... for <user@example.com> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 04 Jan 2026 10:11:12 -0800 (PST)
Що це означає: У вас короткий ланцюжок; ймовірно записано лише два хопи у зразку. У реальній пошті буде більше.
Рішення: Якщо ланцюжок несподівано короткий, підозрюйте, що повідомлення було створене всередині провайдера або заголовки обрізано шлюзом чи клієнтом. Попросіть «повні оригінальні заголовки» з інтерфейсу скриньки, а не переслану копію.
Завдання 2: визначити перший довірений хоп (збіг шаблону з MX/шлюзом)
cr0x@server:~$ grep -n '^Received:' -n message.eml | head
12:Received: from mail-out.example.net (mail-out.example.net [203.0.113.10]) by mx-inbound.corp.example with ESMTPS id 9F3A2B1C for <user@corp.example>; Sun, 04 Jan 2026 18:11:12 +0000 (UTC)
18:Received: from unknown (HELO sender.example) (198.51.100.23) by mail-out.example.net with SMTP; Sun, 04 Jan 2026 18:11:10 +0000 (UTC)
Що це означає: Рядок «by mx-inbound.corp.example» — ваш довірений інгрeс. Все нижче може бути реальним або фальшивим.
Рішення: Починайте кореляцію з цього queue ID (9F3A2B1C) і мітки часу. Ігноруйте upstream «unknown (HELO …)» для рішення про вину, поки не з’являться інші докази.
Завдання 3: розпарсити мітки часу і обчислити затримки між хопами (дешевий «розподілений трейс»)
cr0x@server:~$ grep '^Received:' -n message.eml
12:Received: ...; Sun, 04 Jan 2026 18:11:12 +0000 (UTC)
18:Received: ...; Sun, 04 Jan 2026 18:11:10 +0000 (UTC)
Що це означає: Дві секунди від реле відправника до вашого MX. Це нормально.
Рішення: Якщо між суміжними довіреними хопами хвилини або години — це ваш вузький місце. Йдіть до MTA/шлюзу, відповідального за пізніший хоп, і перевіряйте черги та відмови.
Завдання 4: у Postfix шукати логи за queue ID
cr0x@mailgw01:~$ sudo grep '9F3A2B1C' /var/log/mail.log | tail -n 5
Jan 4 18:11:12 mailgw01 postfix/smtpd[22110]: 9F3A2B1C: client=mail-out.example.net[203.0.113.10], sasl_method=PLAIN, sasl_username=
Jan 4 18:11:13 mailgw01 postfix/cleanup[22122]: 9F3A2B1C: message-id=<CAO9z9kGx12345@mail-out.example.net>
Jan 4 18:11:14 mailgw01 postfix/qmgr[1211]: 9F3A2B1C: from=<noreply@example.net>, size=48212, nrcpt=1 (queue active)
Jan 4 18:47:02 mailgw01 postfix/smtp[23110]: 9F3A2B1C: to=<user@corp.example>, relay=mbx01.corp.example[10.0.10.25]:25, delay=2149, delays=0.2/0.1/2130/18, dsn=2.0.0, status=sent (250 2.0.0 Ok: queued as 7C8D9E0F)
Jan 4 18:47:02 mailgw01 postfix/qmgr[1211]: 9F3A2B1C: removed
Що це означає: Повідомлення переважно сиділо в черзі перед доставкою до mbx01. Розбивка delays=0.2/0.1/2130/18 вказує на час у різних фазах; величезне третє число — наочний доказ.
Рішення: Припиніть звинувачувати відправника. Дослідіть, чому ваш шлюз утримував повідомлення ≈35 хвилин: інтеграція фільтра контенту, обмеження швидкості, повільні відповіді поштового сховища або політика утримання.
Завдання 5: перевірити чергу Postfix на наявність накопичення
cr0x@mailgw01:~$ mailq | head -n 20
-Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
9F3A2B1C 48212 Sun Jan 4 18:11:12 noreply@example.net
user@corp.example
A1B2C3D4 1200 Sun Jan 4 18:12:01 alerts@vendor.example
oncall@corp.example
Що це означає: Є активна черга. Наявність кількох повідомлень навколо одного часу натякає на системну затримку, а не поодинокий випадок.
Рішення: Якщо черга росте і вік повідомлень збільшується, класифікуйте як інцидент: перевірте доступність downstream, затримки фільтрації контенту, розв’язання DNS і обмеження швидкості.
Завдання 6: розподіл віку черги Postfix (це «старі листи»?)
cr0x@mailgw01:~$ sudo postqueue -p | awk 'BEGIN{count=0} /^[A-F0-9]/ {id=$1} /[0-9][0-9]:[0-9][0-9]:[0-9][0-9]/ {count++} END{print "queue_entries="count}'
queue_entries=42
Що це означає: Швидка і недосконала підрахунок записів у черзі. Не ідеально, але тригер.
Рішення: Якщо кількість записів різко зростає у порівнянні з базовою лінією, перевірте, чому пошта не обробляється: таймаути relay=, відмови TLS handshake або повільність сервісу фільтрації.
Завдання 7: перевірити DNS для MX отримувача і зворотний DNS відправника (основи репутації)
cr0x@server:~$ dig +short MX corp.example
10 mx-inbound.corp.example.
cr0x@server:~$ dig +short A mx-inbound.corp.example
192.0.2.55
cr0x@server:~$ dig +short -x 203.0.113.10
mail-out.example.net.
Що це означає: MX резольвиться; у відправника є PTR. Відсутність PTR або невідповідність імен може викликати суворішу обробку приймаючими серверами і призвести до тимчасових відмов або розміщення в спамі.
Рішення: Якщо резолюція MX нестабільна або PTR відсутній — виправте DNS. Якщо ви не можете змінити PTR відправника, очікуйте непередбачуваної доставки і використовуйте автентифіковані шляхи подачі.
Завдання 8: перевірити вирівнювання SPF для домену конвертного відправника
cr0x@server:~$ dig +short TXT example.net | sed -n '1,3p'
"v=spf1 ip4:203.0.113.0/24 include:_spf.provider.example -all"
Що це означає: Домен вказує, які IP можуть відправляти. Якщо у Received видно інший IP, SPF на приймальній стороні провалиться при enforcement.
Рішення: Якщо SPF не включає реальні вихідні IP, оновіть SPF. Якщо відправник використовує третю сторону, переконайтесь, що її адреси включені і не перевищується ліміт DNS-запитів.
Завдання 9: переглянути Authentication-Results з боку отримувача
cr0x@server:~$ grep -i '^Authentication-Results:' -n message.eml | head -n 2
25:Authentication-Results: mx-inbound.corp.example; spf=pass smtp.mailfrom=noreply@example.net; dkim=pass header.d=example.net; dmarc=pass header.from=example.net
Що це означає: Транспорт може все ще відмовлятися, але перевірки ідентичності пройшли. Це відсуває фокус від відмов DMARC і на маршрутизацію, черги або фільтрацію контенту.
Рішення: Якщо DMARC провалюється і політика сувора, не витрачайте години на мережеві трасування. Виправляйте вирівнювання або змініть політику для легітимних відправників.
Завдання 10: у Exchange (або схожі логи), шукати трасування повідомлення (приклад збирача логів на Linux)
cr0x@loghost:~$ grep -R "CAO9z9kGx12345@mail-out.example.net" /var/log/exchange-message-tracking.log | tail -n 3
2026-01-04T18:11:12Z,RECEIVE,SMTP,MBX01,user@corp.example,CAO9z9kGx12345@mail-out.example.net,192.0.2.55
2026-01-04T18:45:50Z,AGENTINFO,TRANSPORT,MBX01,user@corp.example,CAO9z9kGx12345@mail-out.example.net,ContentFilter=SandboxWait
2026-01-04T18:47:02Z,DELIVER,STOREDRIVER,MBX01,user@corp.example,CAO9z9kGx12345@mail-out.example.net,Inbox
Що це означає: Повідомлення прийнято оперативно, потім чекало на вердикт sandbox. Це внутрішня затримка обробки.
Рішення: Масштабуйте або налаштуйте sandbox/AV етап, або звільніть низькоризикові потоки, якщо бізнес це дозволяє. Не просіть відправника «переслати» як стратегію.
Завдання 11: підтвердити збої TLS, коли хоп показує ESMTPS але доставка зупинилась
cr0x@mailgw01:~$ sudo grep -E "TLS|handshake|SSL" /var/log/mail.log | tail -n 5
Jan 4 18:20:11 mailgw01 postfix/smtp[24001]: warning: TLS library problem: error:0A000126:SSL routines::unexpected eof while reading
Jan 4 18:20:11 mailgw01 postfix/smtp[24001]: warning: TLS policy lookup failed
Jan 4 18:20:11 mailgw01 postfix/smtp[24001]: warning: TLS handshake failed for mbx01.corp.example[10.0.10.25]:25: unexpected EOF
Jan 4 18:20:12 mailgw01 postfix/smtp[24001]: 9F3A2B1C: to=<user@corp.example>, relay=mbx01.corp.example[10.0.10.25]:25, delay=540, delays=0.2/0.1/520/20, dsn=4.4.2, status=deferred (lost connection with mbx01.corp.example[10.0.10.25] while sending end of data -- message may be sent more than once)
Jan 4 18:20:12 mailgw01 postfix/qmgr[1211]: 9F3A2B1C: deferred: lost connection with mbx01.corp.example[10.0.10.25] while sending end of data
Що це означає: Ваш шлюз не може завершити TLS або з’єднання з нижестоячим вузлом. Це призведе до відтермінувань і довгих черг, які користувачі сприймуть як «лист зник».
Рішення: Виправте невідповідність TLS політик, проблеми з сертифікатом або скидання балансувальника. За потреби тимчасово послабте TLS вимоги всередині мережі під час усунення проблеми (акуратно, з компенсуючими контролями).
Завдання 12: перевірити системний час і NTP (припиніть відлагодження «подорожі в часі»)
cr0x@mailgw01:~$ timedatectl
Local time: Sun 2026-01-04 18:52:10 UTC
Universal time: Sun 2026-01-04 18:52:10 UTC
RTC time: Sun 2026-01-04 18:52:10
Time zone: UTC (UTC, +0000)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
Що це означає: Годинник у нормі. Якби ні — мітки часу в Received стають ненадійними, і ви будете ганятися за помилковими підказками.
Рішення: Якщо годинник не синхронізовано — виправте NTP спочатку. Потім повторно оцініть таймлайн заголовків.
Завдання 13: підтвердити, чи повідомлення в карантині (приклад: локальна база/лог карантину шлюзу)
cr0x@mailgw01:~$ sudo grep -R "CAO9z9kGx12345@mail-out.example.net" /var/log/mailgw/quarantine.log | tail -n 2
2026-01-04T18:12:02Z action=quarantine reason="AttachmentSandboxPending" queue_id=9F3A2B1C msgid=CAO9z9kGx12345@mail-out.example.net
2026-01-04T18:46:55Z action=release reason="SandboxVerdictClean" queue_id=9F3A2B1C msgid=CAO9z9kGx12345@mail-out.example.net
Що це означає: Повідомлення не «зло», його утримували. Тепер у вас є чітке пояснення і ручка налаштування.
Рішення: Якщо карантин занадто повільний для бізнес-потреб, масштабируйте sandbox або відрегулюйте політику для відомих надійних відправників і типів файлів.
Завдання 14: відстежити повідомлення за Message-ID по декількох хостах (grep + ssh)
cr0x@ops:~$ for h in mailgw01 mailgw02 mbx01; do echo "== $h =="; ssh $h "sudo grep -R \"CAO9z9kGx12345@mail-out.example.net\" /var/log/mail.log | tail -n 2"; done
== mailgw01 ==
Jan 4 18:11:13 mailgw01 postfix/cleanup[22122]: 9F3A2B1C: message-id=<CAO9z9kGx12345@mail-out.example.net>
Jan 4 18:47:02 mailgw01 postfix/smtp[23110]: 9F3A2B1C: to=<user@corp.example>, relay=mbx01.corp.example[10.0.10.25]:25, dsn=2.0.0, status=sent (250 2.0.0 Ok: queued as 7C8D9E0F)
== mailgw02 ==
== mbx01 ==
Jan 4 18:47:02 mbx01 postfix/smtpd[18001]: 7C8D9E0F: client=mailgw01.corp.example[10.0.10.5]
Jan 4 18:47:03 mbx01 postfix/local[18012]: 7C8D9E0F: to=<user>, orig_to=<user@corp.example>, relay=local, status=sent (delivered to mailbox)
Що це означає: Кінцевий трас Across вашого господарства. Відсутність записів на mailgw02 натякає, що маршрутизація через нього не проходила.
Рішення: Якщо Message-ID є на інгрeсі, але немає на скриньці — фокус на етапі ретелей. Якщо є на скриньці, але користувач не знаходить — переключайтесь на правила клієнта, фолдери і індексацію пошуку.
Завдання 15: перевірити затримку фільтра контенту (приклад: amavis/milter статистика)
cr0x@mailgw01:~$ sudo grep -E "milter|amavis|scan time" /var/log/mail.log | tail -n 5
Jan 4 18:12:05 mailgw01 amavis[3101]: (03101-02) Passed CLEAN, [203.0.113.10] [203.0.113.10] <noreply@example.net> -> <user@corp.example>, Queue-ID: 9F3A2B1C, Message-ID: <CAO9z9kGx12345@mail-out.example.net>, Hits: -, size: 48212, queued_as: 9F3A2B1C, 92 ms
Jan 4 18:45:49 mailgw01 milter-sandbox[4021]: queue_id=9F3A2B1C verdict=pending wait=2010s
Jan 4 18:46:55 mailgw01 milter-sandbox[4021]: queue_id=9F3A2B1C verdict=clean wait=2066s
Що це означає: AV-сканування швидке; sandbox — вузьке місце і це явно видно.
Рішення: Налаштуйте паралелізм sandbox, змініть, що підлягає sandbox-скануванню, або впровадьте асинхронні шаблони доставки, якщо шлюз це підтримує (доставити і потім виправляти, якщо політика дозволяє).
Завдання 16: перевірити, чи правила скриньки не «з’їли» лист (аудит правил на сервері)
cr0x@mbx01:~$ sudo grep -R "user@corp.example" /var/log/mailbox-rules.log | tail -n 5
2026-01-04T18:47:05Z user=user@corp.example rule="Move vendor mail" match="From contains example.net" action="move" folder="Vendors"
2026-01-04T18:47:05Z user=user@corp.example msgid=CAO9z9kGx12345@mail-out.example.net result="moved" folder="Vendors"
Що це означає: Доставка відбулася; видимість — ні. Повідомлення в іншій теці.
Рішення: Не розглядати це як інцидент MTA. Допоможіть користувачу виправити правила або відрегулюйте корпоративні налаштування.
Три корпоративні історії з практики
Міні-історія 1: інцидент через неправильне припущення
У тікеті писали: «Лист від нашого платіжного провайдера не приходить. Мусить бути їхній збій». Це надійшло від фінансів, отже справа мала пріоритет, неоднозначність і вкладення з календарем.
Молодший адміністратор зробив те, що молодші роблять, коли в кімнаті голосно: подивився на верхній Received рядок в повідомленні, яке платіжник переслав як доказ. Там було ім’я хоста платіжного провайдера і нічого, що виглядало б як наша інфраструктура. Висновок був: «Ми його не отримали. Проблема платіжника». Вони були напівправі і повністю неправі в найважливішому.
Ми попросили заголовки від повідомлення, яке дійшло раніше того ж дня, і порівняли ланцюжки. Відсутній лист не був відсутній; він потрапив на наш периметр і був поміщений у карантин без видимого для користувача повідомлення через новий тип вкладення. Наш шлюз мав правило утримання, яке не генерувало сповіщень зовнішнім відправникам, бо колись хтось скаржився на «забагато листів з карантину». Той хтось тепер працював в іншому відділі, звісно.
Неправильне припущення було в тому, що «якщо в Inbox немає — ми не отримали». Ланцюжок Received з нашого довіреного шлюзу довів, що ми отримали. Логи показали queue ID, дію карантину і те, що реліз не відбувся, бо sandbox був неактивний. Останнє і було реальним збоям — і це була наша помилка.
Ми запустили sandbox, випустили карантиновані повідомлення і ухвалили рішення, що закріпилось: карантин без повідомлень користувачам — це операційний борг. Іноді це необхідно, але тоді ви винні собі дашборди й алерти, бо користувачі прийдуть з вилами, і ви їх заслужите.
Міні-історія 2: оптимізація, яка відкотилась
Велика компанія хотіла «оптимізувати затримки безпеки пошти». План звучав розумно: перейти від синхронного sandbox-сканування вкладень (утримувати лист до вердикту) до швидшого пайплайна, збільшивши паралелізм і посиливши TLS-політики. Швидше і безпечніше. Що могло піти не так?
Зміна впала в п’ятницю, звісно. Паралелізм зріс, що збільшило навантаження на CPU шлюзу. TLS-політики посилились, що збільшило відмови握 handshake з внутрішнім relay, який мав стару конфігурацію шифрів. Шлюз почав відкладати доставку, але все ще приймав вхідні листи, нагромаджуючи їх у черзі як тарілки на шведському столі.
Received заголовки говорили самі за себе: мітки часу прийому були нормальними, але внутрішня передача до поштових серверів відставала на 20–60 хв. Користувачі звинувачували зовнішніх відправників, ті звинувачували нашу репутацію, а керівництво звинуватило «електронну пошту» як таку. Тим часом черга росла, і диск шлюзу заповнився, бо черги — це сховище, хочете ви того чи ні.
Ми відкотили жорсткість TLS для внутрішніх ретлей, зменшили паралелізм sandbox до відповідності фактичної CPU-можливості і додали жорсткий моніторинг розміру черги з прив’язкою до пейджингу. Болісний урок: тюнінг продуктивності в поштових системах — як тюнінг бази даних. Ви можете перемістити вузьке місце, але також створити абсолютно новий режим відмови з красивим маркетингом.
Міні-історія 3: нудна, але правильна практика, яка врятувала день
Інша компанія, інший настрій: у них був runbook «mail trace», про який ніхто не вихвалявся. Це була сторінка з кроками: витягнути ланцюжок Received, знайти перший довірений хоп, скорелювати queue ID, перевірити карантин, підтвердити доставку в теку. Це не було захопливо. Це було правильно.
Одного дня VIP поскаржився, що угода «ніколи не надійшла» і пригрозив ескалацією. На виклику on-call дотримався runbook. Через п’ять хвилин у них був queue ID шлюзу, точна мітка часу прийняття і внутрішній relay ID, що підтверджував фінальну доставку в поштове сховище.
Потім вони перевірили журнали правил скриньки: повідомлення було переміщено в папку «Legal» і відмічене як прочитане мобільним клієнтом. Це не була проблема MTA. Це був робочий процес користувача. On-call дав чітке пояснення: «Доставлено о 14:03 UTC, переміщено правилом X у папку Y». Ескалація зникла.
Практика, що врятувала день, не була якимось модним інструментом. Це був регулярний логінг, годинники, що не обманюють, і звичка корелювати ID замість здогадок. Надійність часто — це просто відсутність драм завдяки хорошій гігієні.
Типові помилки: симптом → корінь проблеми → виправлення
-
Симптом: «Received заголовки показують доставку, але користувач каже, що нічого не отримував.»
Корінь проблеми: Відображення для користувача: правила, фокусований inbox, папка спаму, серверне переміщення, архівація.
Виправлення: Скорелюйте фінальний довірений хоп + логи доставки в скриньку; перевірте дії правил; підтвердіть шлях папки і поведінку клієнта; відключіть проблемні правила. -
Симптом: Мітки часу йдуть назад між хопами.
Корінь проблеми: Зсув годинника або неправильна конфігурація часової зони на сервері; іноді — помилкове зчитування через згортання заголовків інструментами.
Виправлення: Перевірте NTP (timedatectl); виправте часову зону; перевірте в raw заголовках. -
Симптом: Немає довіреного Received рядка від вашого периметра.
Корінь проблеми: Ви ніколи не приймали повідомлення; відправник не дійшов до вас; MX у DNS неправильний; upstream політика блокує; відправлено на помилковий домен.
Виправлення: Перевірте записи MX; підтвердіть адресу отримувача; попросіть відправника надати SMTP логи/коди bounce; перевірте логи периметра на спроби підключень. -
Симптом: Велика затримка між прийняттям у вашому MX і доставкою в скриньку.
Корінь проблеми: Беклог у вхідному пайплайні: фільтр контенту, sandbox, AV, DLP, повільне сховище скриньок, відмови TLS внутрішнього ретлей.
Виправлення: Визначте, який внутрішній хоп додав затримку; перевірте глибину черги; масштабуйте вузьке місце; виправте TLS/cipher невідповідність; додайте алерти на вік черги. -
Симптом: Відправник стверджує «ми отримали 250 OK», але ви не можете знайти повідомлення.
Корінь проблеми: 250 був від проміжного ретлея (не від вас), або ви прийняли, а потім помістили в карантин/переписали, або логи відсутні через ротацію.
Виправлення: Зіставте сервер, що видав 250, з «by» хопом у Received; попросіть їхні логи; зберігайте логи достатньо довго для бізнес-потреб. -
Симптом: Деякі зовнішні домени постійно відмовляють або затримуються, інші ні.
Корінь проблеми: Репутація/тротлінг, невідповідність TLS-політик, DMARC примушення або помилкові спрацьовування фільтра для конкретних відправників.
Виправлення: Перевірте Authentication-Results; перевірте TLS логи; координуйте allowlist грамотно (надавайте перевагу DKIM); відрегулюйте правила фільтра з доказами. -
Симптом: Переслані листи з особистої пошти не доходять, але прямі — доходять.
Корінь проблеми: SPF провалюється і DKIM ламається при пересиланні; DMARC політика reject/quarantine спрацьовує у приймача.
Виправлення: Заохочуйте прямі відправлення; впровадьте ARC-aware обробку; для внутрішніх форвардерів використовуйте SRS і зберігайте DKIM, де можливо. -
Симптом: Кілька дублікатів приходять через години.
Корінь проблеми: Відправник повторює після невизначеної доставки (з’єднання загубилось після DATA), або шлюз повторно інжектував при таймауті.
Виправлення: Перевірте логи на «message may be sent more than once»; виправте стабільність downstream-з’єднань; забезпечте идемпотентність фільтрів, де можливо.
Контрольні списки / покроковий план
Покроково: простежити одне відсутнє повідомлення
- Отримати правильний артефакт: повні оригінальні заголовки повідомлення з інтерфейсу скриньки отримувача (не переслате повідомлення). Якщо можливо — сирцевий raw.
- Витягти рядки Received і читати знизу вгору.
- Визначити перший довірений «by» хоп (ваш MX/шлюз/провайдерський інгрeс). Усе нижче — недовірений контекст.
- Зафіксувати ключі для кореляції: queue ID(и), Message-ID, адреса отримувача, мітки часу.
- Перевірити логи периметра на прийняття, відмови або відтермінування близько до мітки часу.
- Перевірити стан черги (глибина + вік). Визначити, чи це системна проблема.
- Перевірити pipeline контенту (AV/sandbox/DLP) на утримання й затримки.
- Перевірити внутрішній handoff ретлея на відмови TLS, таймаути або зворотний тиск.
- Перевірити логи доставки в скриньку і фінальне розміщення (папки/правила/карантин).
- Написати пояснення для людей: «Прийнято о X, затримано у Y через Z, доставлено о T.» Вказати часи й системи.
Покроково: вирішити, де проблема — на боці відправника чи отримувача
- Якщо у вас немає довіреного Received рядка з вашої інфраструктури: вважайте проблему на боці відправника або в Інтернет-маршруті. Попросіть коди відмов або їхні MTA логи.
- Якщо у вас є довірене прийняття, але немає доставки в скриньку: обробка на боці отримувача. Режим інциденту.
- Якщо у вас є доставка в скриньку, але користувач не знаходить — питання видимості/правил. Не викликайте команду MTA за UI-проблему.
Операційний чекліст: зробіть Received заголовки корисними у вашому середовищі
- Підтримуйте NTP здоровим на всіх системах, що торкаються пошти.
- Переконайтеся, що ваші MTA логують queue ID і Message-ID і зберігають логи достатньо довго для бізнес-розслідувань.
- Експортуйте як метрики глибину черги і вік найстарішого повідомлення з порогами для пейджингу.
- Інструментуйте фільтри контенту метриками латентності і вердиктів.
- Документуйте межі довіри: які хопи ваші, які — вендорські, які — публічний інтернет.
Жарт №2: Найшвидший спосіб знайти вузьке місце в доставці — призначити на це зустріч; пошта з’явиться під час наради, просто щоб насолити вам.
Питання й відповіді
1) Чому Received заголовки здаються «в зворотному порядку»?
Тому що кожен сервер додає свій Received рядок зверху. Шлях повідомлення вперед у часі читається знизу вгору.
2) Чи можна підробити Received заголовки?
Усе поза межами вашої зони довіри може бути підроблене, бо відправник може додати довільні заголовки. Received рядок, доданий вашим першим довіреним MX/шлюзом — це анкeр, на який треба опиратися.
3) У чому різниця між «from» і «by» у Received заголовку?
by — сервер, що написав рядок. from — пір, що з’єднався з ним. При налагодженні дивіться на «by» для логів.
4) Який ідентифікатор кращий для кореляції логів: Message-ID чи queue ID?
Queue ID кращий в межах одного MTA, бо це локальний і гарантовано зіставляється з логами. Message-ID кращий між системами, але може відсутній або дублюватись. Використовуйте обидва, коли можливо.
5) Я бачу ESMTPA в Received. Що це означає?
Часто це означає автентифіковану подачу (клієнт увійшов). Це звужує пошук до логів хоста подачі, а також означає, що пошта зайшла через submission сервіс, а не через відкритий ретлей.
6) Відправник каже, що отримав «250 OK». Хіба це не доводить доставку?
Це доводить прийняття деяким SMTP-сервером, але не обов’язково фінальну доставку в скриньку отримувача. Потрібно зіставити сервер, що видав 250, з «by» хопом у Received і простежити далі.
7) Як зрозуміти, що затримка — це greylisting?
Самі заголовки часто не показують повторних спроб; треба дивитись логи. Шукайте 4xx відмови в логах отримувача або логах відправника, за якими йде пізніше успішне прийняття. Час відправлення у відправника може бути значно раніше, ніж час прийняття у вас.
8) Чому іноді багато внутрішніх хопів у великих провайдерів?
Великі провайдери обробляють пошту через кілька сервісів: edge MTA, фільтрація спаму, політичні рушії, доставка в скриньку. Кожен шар може додати Received рядок і кожен може бути джерелом затримки.
9) Що робити, якщо немає Received заголовків взагалі?
Це незвично для Інтернет-пошти. Можливо, ви бачите фрагмент повідомлення, копію/вставку або переслане повідомлення, де клієнт замінив заголовки. Отримайте raw source через «view original» у скриньці.
10) Як SPF/DKIM/DMARC пов’язані з тим, де «зламалась доставка»?
Якщо DMARC провалюється з жорсткою політикою, злам — це застосування політики на приймаючій стороні, а не транспорт. Received заголовки покажуть шлях, але сигнали автентифікації пояснять, чому хоп відмовив, помістив у карантин або поклав у папку спаму.
Висновок: наступні кроки, які можна зробити цього тижня
Налагодження доставки пошти стає значно менш містичним, якщо ставитись до Received заголовків як до трейсів хопів, а до логів — як до ground truth. Заякорюйтесь на першому довіреному хопі, вимірюйте затримки між хопами і корелюйте за допомогою queue ID та Message-ID. Потім говоріть у часових позначках і системах, а не в відчуттях.
Практичні наступні кроки:
- Напишіть (або запозичте) односторінковий runbook, що відповідає Швидкому плану діагностики й покроковому плану вище.
- Додайте дві метрики до моніторингу: глибину черги і вік найстарішого повідомлення на кожному поштовому хопі, який ви контролюєте.
- Аудитуйте карантин/утримання: якщо ви утримуєте пошту, потрібна видимість і сповіщення, інакше ви створюєте майбутні інциденти.
- Перевірте синхронізацію часу між MTAs, шлюзами і поштовими серверами. Дріф часу перетворює аналіз заголовків у перформанс-арт.
«Надія — не стратегія.»
— перефразована ідея, поширена в операціях і колах надійності