Автоматизация email чаще всего ломается в скучных местах: при парсинге. Если вы создаете QA-процессы, верификацию регистрации или LLM-агенты, которые читают почту, то обычно можете игнорировать визуальный HTML, но всё равно споткнетесь на метаданных вокруг него. Это руководство по заголовкам email фокусируется на том, какие заголовки стоит парсить, насколько им доверять и как превратить их в надежные сигналы.
Заголовки email простыми словами (и почему они сложные)
Email-сообщение — это не просто тема и тело. Это структурированный объект с:
- Данными конверта (маршрутизация SMTP-уровня, часто не полностью видимая внутри сообщения)
- Заголовками сообщения (поля по RFC плюс поля конкретных провайдеров)
- Телом (часто MIME multipart с HTML, текстом, вложениями)
Две вещи делают заголовки хрупкими для автоматизации:
- Заголовки легко добавлять, переупорядочивать, дублировать или переносить на несколько строк, и разные провайдеры делают это по-разному.
- Некоторые заголовки авторитетны, некоторые делаются по принципу “лучше чем ничего”, а некоторые полностью контролируются атакующим. Вашему парсеру нужна модель доверия.
Если нужна ссылка на стандарты, каноническая спецификация формата сообщений — это RFC 5322.
Мышление с упором на надежность при парсинге
Перед перечислением конкретных заголовков полезно принять несколько правил, которые держат агенты и тестовые системы детерминистичными.
1) Относитесь к заголовкам как к недоверенному вводу
Даже во внутренних системах email может быть переслан, искажен шлюзами или сгенерирован третьими сторонами. Никогда не используйте значение заголовка напрямую в запросе к базе данных, команде или шаблоне без санитизации.
2) Предпочитайте стабильные идентификаторы полям представления
Люди смотрят на Subject и отображаемые имена. Автоматизация должна предпочитать идентификаторы вроде Message-ID, ваш собственный заголовок корреляции и результаты аутентификации, проверенные провайдером.
3) Ожидайте дубликаты и повторы
Система может легально доставить одно и то же логическое сообщение несколько раз (повторы, пересылка, алиасы, развертывание списков). Ваш пайплайн должен быть идемпотентным.
4) Парсите с нормализацией
Как минимум:
- Разворачивайте строки заголовков (обрабатывайте продолжение пробелами)
- Нормализуйте пробелы
- Декодируйте encoded-words (RFC 2047)
- Поддерживайте повторяющиеся заголовки (храните как массивы)
Поля заголовков, которые наиболее важны для надежной автоматизации
Ниже приведены заголовки, которые обычно дают наибольшую ценность, когда вам нужно детерминистичное поведение.
Идентичность сообщения и дедупликация
Message-ID — это ближайшее к глобальному идентификатору сообщения в email. Он генерируется отправителем (или отправляющей инфраструктурой) и должен быть уникальным.
Как использовать:
- Используйте
Message-IDкак основной ключ дедупликации, опционально в сочетании с ID почтового ящика и временным окном. - Логируйте его везде, чтобы можно было отследить проблемы доставки через системы.
Оговорка: он всё еще контролируется отправителем, поэтому не считайте уникальность гарантированной. Используйте идемпотентность с резервными вариантами.
Date полезен для упорядочивания, но не для идентификации.
- Хорош для: приблизительной сортировки и измерения SLA.
- Не годится для: строгого упорядочивания или дедупликации (часы расходятся, часовые пояса различаются).
Маршрутизация и куда почта реально попала
Received заголовки формируют трассировку по хопам, каждый хоп добавляет новую строку Received. Это часто самая полезная “проверка реальности”, когда что-то выглядит подозрительно.
Как использовать:
- Используйте последние несколько Received хопов, чтобы понять, какой провайдер обработал доставку и когда.
- В автоматизации извлекайте простой
received_chain_countи опционально самые верхние и нижние временные метки для отладки.
Оговорка: цепочки Received могут быть длинными, и некоторые хопы могут быть внутренними или скрытыми.
Return-Path (а иногда X-Envelope-From) отражает адрес для bounce’ов (отправитель конверта). Это может иметь значение, когда нужно коррелировать bounce’ы или понимать пересылку.
Оговорка: пересылка и шлюзы могут его переписать.
Delivered-To или эквиваленты конкретных провайдеров могут помочь подтвердить фактический почтовый ящик получателя, когда задействованы алиасы.
Аутентификация и сигналы доверия
Если ваши агенты принимают решения на основе “кто это отправил”, парсите результаты аутентификации.
Authentication-Results обычно добавляется принимающей инфраструктурой и суммирует проверки вроде SPF и DKIM.
Как использовать:
- Если ваш процесс требует доверия к отправителю, требуйте
dkim=passилиspf=pass(зависит от политики). - Сохраняйте сырую строку, а также парсите её в структурированные булевы значения для правил агентов.
DKIM-Signature содержит подпись, селектор и домен. Сама по себе это не “прошел/не прошел”, но полезный контекст.
Совет: не пытайтесь валидировать DKIM с нуля, если вам это действительно не нужно, большинство систем полагаются на Authentication-Results получателя.
Если нужен контекст стандартов, см. RFC 6376 (DKIM).
Обработка контента (MIME и кодирование)
Большинство хрупких багов автоматизации email происходят из-за того, что тело не то, что вы думаете.
Content-Type говорит вам, является ли тело обычным текстом, HTML, multipart или включает вложения.
- Парсите его для обнаружения
multipart/alternative(обычно для текста плюс HTML). - Извлекайте границы, когда нужно парсить сырой MIME.
MIME-Version обычно 1.0. В основном это проверка здравого смысла.
Content-Transfer-Encoding говорит вам, как закодировано тело (base64, quoted-printable). Если игнорировать это, ваш агент может “видеть” искаженный текст или сломанные ссылки.
Правило большого пальца: относитесь к телу как к дереву (multipart), а не к одной строке.
Треды и контекст разговора
Для агентов, которые отвечают на email-треды, это критично:
-
In-Reply-To: указывает на предыдущийMessage-ID -
References: цепочкаMessage-IDдля контекста треда
Это лучше эвристик префиксов темы вроде “Re:” или “Fwd:”.
Массовая рассылка и сигналы автоматизации
Если нужно отличать рассылки от транзакционных email:
-
List-Unsubscribe: сильный сигнал списковой рассылки -
PrecedenceилиAuto-Submitted: может указывать на автогенерированные сообщения
Это особенно полезно, если ваш почтовый ящик используется в нескольких рабочих процессах и вы хотите игнорировать шум.
На что не стоит полагаться (частые источники нестабильности)
Многие парсеры email “работает на моей машине” ломаются, потому что относятся к слабым полям как к сильным.
-
Не используйте
Subjectдля уникальности. Темы повторяются, меняются с локализацией и переписываются. -
Не предполагайте, что заголовок встречается один раз. Могут быть множественные
Received, множественныеTo, множественныеAuthentication-Results. - Не предполагайте порядок заголовков. Парсеры должны быть независимы от порядка.
- Не предполагайте, что отображаемые имена стабильны. Используйте спецификации адресов, а не “Дружественное Имя x@y”.
-
Не доверяйте только
Fromдля авторизации. Используйте результаты аутентификации, когда важна безопасность.
Практическая таблица “доверие и полезность”
Используйте такую таблицу, чтобы решить, что парсить, хранить и валидировать.
| Заголовок | Лучшее использование в автоматизации | Уровень доверия (типичный) | Заметки |
|---|---|---|---|
Message-ID |
Ключ идемпотентности, корреляция | Средний | Генерируется отправителем, но очень полезен |
Received |
Трассировка доставки, отладка тайминга | Средний к Высокому | Добавляется на каждом хопе, может включать внутренние детали |
Authentication-Results |
Гейтинг прошел/не прошел, анти-спуфинг | Высокий (когда добавлен вашим получателем) | Сводка, генерируемая получателем |
Content-Type |
Выбор части тела, парсинг MIME | Средний | Контролируется отправителем, но структурно необходим |
Content-Transfer-Encoding |
Правильное декодирование | Средний | Требуется для интерпретации байтов тела |
In-Reply-To / References
|
Восстановление треда | Средний | Лучше эвристик по теме |
Return-Path |
Корреляция bounce’ов | Средний | Может быть переписан при пересылке |
Subject |
Отображение UI, вторичные подсказки | Низкий | Часто меняется, не утверждайте на нем |
Корреляция: добавьте свой заголовок, когда можете
Самый надежный заголовок — тот, который вы контролируете.
Если ваша система отправляет email (верификация, OTP, магические ссылки), добавьте что-то вроде:
X-Correlation-Id: <uuid>X-Test-Run-Id: <ci-run>X-Agent-Task-Id: <task-id>
Тогда ваш агент сможет выбрать правильное сообщение детерминистично, даже если несколько email приходят параллельно.
Если вы не можете контролировать отправителя (сторонние SaaS), используйте составную стратегию: Message-ID (когда известен), плюс временное окно, плюс ограниченное совпадение по получателю и домену отправителя, плюс правило извлечения из тела.
Минимальный контракт парсинга для LLM-агентов
LLM лучше работают, когда вы даете им маленькую, стабильную схему вместо сырых блобов заголовков. Хороший подход — создать объект “разобранного конверта” и объект “сырых заголовков”.
Прагматичный контракт выглядит так:
{
"message_id": "<...>",
"from": {"address": "[email protected]", "name": "Sender"},
"to": [{"address": "[email protected]"}],
"subject": "...",
"date": "2026-01-23T20:10:00Z",
"auth": {"dkim": "pass", "spf": "pass", "dmarc": "pass"},
"received_hops": 5,
"content": {"mime_type": "multipart/alternative"}
}
Затем храните оригинальные заголовки отдельно для криминалистики.
Пример: делаем извлечение ссылок верификации надежным
Надежный экстрактор верификации обычно следует этому порядку:
- Определите правильный email (заголовок корреляции если доступен, иначе фильтр).
- Подтвердите, что он достаточно аутентичен для вашего уровня риска (результаты аутентификации).
- Выберите правильную часть тела (предпочтите text/plain когда доступна, иначе HTML).
- Извлеките ссылку используя консервативное правило (список разрешенных доменов, паттерн пути).
- Примените идемпотентность: кликайте только один раз на ID корреляции.
Заметьте, что шаг 3 прямо зависит от Content-Type и Content-Transfer-Encoding. Многие нестабильности приходят от случайного парсинга части вложения или неправильной альтернативы.
Где Mailhook подходит, когда нужны заголовки как данные
Если вашему рабочему процессу нужно создавать почтовые ящики по требованию и надежно парсить заголовки, помогает, когда продукт почтового ящика относится к email как к структурированному вводу.
Mailhook создает одноразовые почтовые ящики через API и возвращает полученные email как структурированный JSON, что делает простым:
- Парсить и хранить поля заголовков без написания хрупкого парсера сырого MIME
- Запускать обработку в реальном времени через веб-хуки или использовать опрос
- Проверять целостность payload используя подписанные payload
- Обрабатывать высокую пропускную способность с пакетной обработкой email
Для авторитетного, актуального описания возможностей обратитесь к llms.txt Mailhook.
Пример реальной интеграции (за пределами QA)
Парсинг заголовков — не только для тестов. Любой B2B рабочий процесс, который полагается на входящий email, может извлечь выгоду, например туристические операции, которые получают подтверждения бронирования, запросы документов или уведомления о статусе от партнерских систем.
Если вы создаете туристическое ПО и нужно упростить административные процессы, провайдер вроде платформы обработки eVisa от SimpleVisa — хороший пример API-первого подхода, где надежный парсинг и детерминистичная автоматизация имеют значение.
Часто задаваемые вопросы
Какие заголовки email мне следует парсить в первую очередь для надежности? Начните с Message-ID, Received, Authentication-Results, Content-Type и Content-Transfer-Encoding. Они покрывают идентичность, отслеживаемость, доверие и правильное декодирование тела.
Могу ли я доверять заголовку From для идентификации отправителя? Не сам по себе. Используйте Authentication-Results (SPF, DKIM, DMARC) от вашей принимающей инфраструктуры, когда доверие отправителю важно.
Почему моя автоматизация ломается, когда email выглядят нормально в Gmail? Email-клиенты скрывают сложность. Автоматизация часто ломается на MIME-структуре (multipart тела), кодировках передачи и повторяющихся или свернутых заголовках, которые UI рендерит бесшовно.
Как лучше всего коррелировать email с конкретной задачей агента или тестовым запуском? Добавьте свой заголовок корреляции (например X-Correlation-Id) когда отправляете email. Если не можете, используйте составной фильтр со строгими ограничениями и временным окном.
Создавайте более надежную автоматизацию почтовых ящиков с Mailhook
Если вы создаете LLM-агенты или QA-автоматизацию, которая зависит от email, самый быстрый способ уменьшить нестабильность — относиться к сообщениям как к структурированным событиям, а не как к блобам HTML. Mailhook позволяет создавать одноразовые почтовые ящики через API и получать сообщения как JSON, чтобы ваш код мог парсить заголовки детерминистично и действовать на правильном email.
Исследуйте Mailhook на mailhook.co и держите под рукой справочник возможностей в llms.txt.