Email остается одним из последних “ориентированных на человека” интерфейсов, которые большинству команд разработчиков все еще приходится автоматизировать. Если вы создаете процессы верификации регистрации, QA-тесты или LLM-агенты, которые должны выполнять реальные задачи, в конечном итоге вам нужно получать email через API, надежно и в формате, который не требует хрупкого парсинга HTML.
Программируемый API почтового ящика решает эту проблему, превращая входящие email в структурированный JSON, а затем доставляя его в ваш код через веб-хуки (push) и/или опрос (pull). Эта статья объясняет основные принципы проектирования, как должен выглядеть практичный JSON-контракт, и как интегрировать это в автоматизацию, которая является детерминированной и безопасной.
Если вы специально интегрируетесь с Mailhook, каноническим машиночитаемым справочником интеграции является llms.txt проекта: Mailhook API contract (llms.txt).
Что на самом деле означает “получение email через API” (и почему JSON является ключевым)
Когда разработчики говорят “получить email”, они часто имеют в виду одно из следующего:
- Извлечь сообщение из почтового ящика (IMAP/POP), затем самостоятельно парсить RFC 5322 и MIME.
- Получить событие сообщения (webhook), затем сохранить и парсить его.
- Запросить почтовый ящик по ID, получить нормализованные поля и контент для автоматизации.
Для автоматизации и агентов сложные части редко связаны с самой SMTP-доставкой. Боль возникает после доставки:
- MIME является многочастным, вложенным и полным граничных случаев кодирования.
- Заголовки могут быть свернутыми, дублированными и контролируемыми атакующими.
- Тела могут быть перегружены HTML, содержать трекинг или не иметь
text/plain. - Время недетерминировано, вы не можете “подождать 5 секунд” и ожидать надежности.
Хороший API почтового ящика превращает сырой email (определенный RFC 5322 плюс MIME, см. RFC 2045) в стабильное JSON-представление, так что ваша автоматизация может проверять поля, а не хрупкий рендеринг.
Модель, дружественная к автоматизации: почтовые ящики и сообщения, а не долгоживущие аккаунты
Ключевой сдвиг заключается в том, чтобы относиться к почтовому ящику как к короткоживущему ресурсу, ближе к очереди сообщений, чем к личному почтовому ящику:
- Вы создаете почтовый ящик программно.
- Вы получаете маршрутизируемый email-адрес для этого ящика.
- Ваша система отправляет email на этот адрес.
- Вы извлекаете сообщения как JSON (webhook или опрос).
- Вы опционально ротируете или истекаете почтовый ящик для поддержания изоляции.
Этот подход “сначала почтовый ящик” делает параллельные CI-запуски, многоагентные цепочки инструментов и процессы верификации с множественными повторами предсказуемыми.

Как должен выглядеть JSON? Практический контракт для QA и LLM-агентов
Разные провайдеры предоставляют различные схемы, но надежная автоматизация обычно нуждается в одних и тех же концептуальных частях:
| Концепция email | Зачем она вам нужна | Примеры JSON-полей (иллюстративные) |
|---|---|---|
| Стабильный идентификатор сообщения | Дедупликация, идемпотентность |
message_id, provider_id, rfc822_message_id
|
| Временная метка прибытия | Временные бюджеты, отладка | received_at |
| Адреса конверта | Маршрутизация и проверки |
from, to, cc, reply_to
|
| Тема | Сопоставление и корреляция | subject |
| Заголовки (нормализованные) | Отладка, корреляция, сигналы аутентификации |
headers (карта или список, нормализованный) |
Текстовый контент (предпочтительно text/plain) |
Безопасный парсинг для агентов |
text, text_plain, body_text
|
| HTML-контент (опционально, относиться осторожно) | Отладка человеком, резервы |
html, body_html
|
| Метаданные вложений | Безопасность, извлечение артефактов |
attachments[] с filename, content_type, size
|
| Сырой источник (опционально, но ценно) | Форензика, когда парсеры расходятся |
raw или source
|
Две практические рекомендации для агентских и тестовых сред:
-
Предпочитайте
text/plainдля проверок и извлечения. HTML полезен для людей, но это большая, дружественная атакующему поверхность для автоматизации. - Держите сырой источник доступным для отладки. Когда что-то ломается в CI, возможность осмотреть точно доставленный контент может сэкономить часы.
Позиционирование продукта Mailhook явно сосредоточено на этом: создавайте одноразовые почтовые ящики через API и получайте email как структурированный JSON, созданный для LLM-агентов и QA-автоматизации. Для точных имен полей и форматов payload используйте канонический справочник: mailhook.co/llms.txt.
Извлечение сообщений: webhook в первую очередь, polling как резерв
Существует два распространенных способа “получить email через API”, и большинство продакшн-установок используют оба.
Веб-хуки (push)
С веб-хуком провайдер почтового ящика вызывает вашу точку подключения, когда приходит новое сообщение. Это идеально, когда вы хотите быстрые, событийно-управляемые рабочие процессы.
Сильные стороны:
- Низкая задержка, никаких циклов опроса
- Естественная модель потока событий
- Хорошо масштабируется, когда много ящиков активны
Операционные требования:
- Вы должны реализовать повторы и идемпотентность
- Вы должны проверить подлинность (подписи)
- Вам нужна точка подключения, доступная из публичного интернета (или безопасный туннель)
Mailhook поддерживает уведомления веб-хуков в реальном времени и подписанные payload для безопасности (проверяйте подписи перед доверием контенту).
Опрос (pull)
При опросе ваш код спрашивает провайдера о сообщениях в ящике, пока не прибудет совпадение или не истечет тайм-аут.
Сильные стороны:
- Просто рассуждать о тест-раннерах
- Работает, даже если ваша точка веб-хука недоступна
- Хороший резервный путь для надежности
Затраты:
- Более высокая задержка (в зависимости от интервала)
- Больше API-вызовов
Mailhook включает API опроса для email, который является практическим дополнением к веб-хукам.
Быстрое сравнение
| Механизм | Лучше всего для | Подвох надежности | Совет по умолчанию |
|---|---|---|---|
| Веб-хук | Автоматизация в реальном времени, высокая параллельность | Дублированные доставки, риск replay | Проверяйте подписи, дедуплицируйте по ID сообщения |
| Опрос | CI-тесты, резервные пути | Фиксированные sleep вызывают нестабильность | Опрашивайте с тайм-аутом и backoff, сопоставляйте узко |
Детерминированное извлечение: сопоставьте правильное сообщение, а не “последний email”
Большинство нестабильности происходит от неоднозначного сопоставления. Если вы только делаете “получить последнее сообщение”, то повторы, параллельные запуски и задержанная доставка сожгут вас.
Детерминированная стратегия обычно включает:
- Изоляция почтового ящика: один ящик на запуск, на попытку или на сессию агента.
-
Токен корреляции: включите
run_idили nonce в место, которое вы можете сопоставить. - Узкие сопоставители: фильтр по ожидаемому отправителю, ожидаемому префиксу темы или уникальному токену.
- Явный временной бюджет: одна функция, которая ждет до дедлайна.
Для корреляции наиболее надежный вариант - добавление собственного заголовка типа X-Correlation-Id (когда вы контролируете отправителя). Если не можете, используйте токен темы или уникальный параметр ссылки.
Минимальный интерфейс “ждать email” (дружественный к агентам)
Независимо от того, строите ли вы тестовый фреймворк или LLM-инструмент, самая чистая абстракция - это небольшая, детерминированная поверхность API:
-
create_inbox()→ возвращает{ inbox_id, address } -
wait_for_message(inbox_id, matcher, timeout_ms)→ возвращает одно сообщение JSON -
extract_verification_artifact(message)→ возвращает{ otp }или{ url }
Это не дает LLM или тест-раннеру иметь дело с семантикой поиска по почтовому ящику. Это также снижает риск prompt injection, потому что агенту не нужна “вся история ящика”, только минимальный артефакт.
Пример: извлечение OTP из JSON (псевдокод)
Код ниже намеренно независим от провайдера. Он иллюстрирует поток управления и проверки безопасности, не предполагая точные точки Mailhook или имена полей.
Извлечение на основе опроса
import re
import time
def wait_for_message(fetch_messages, inbox_id, timeout_s=60, poll_interval_s=1.5):
deadline = time.time() + timeout_s
seen_ids = set()
while time.time() < deadline:
messages = fetch_messages(inbox_id) # возвращает список JSON-объектов сообщений
for msg in messages:
msg_id = msg.get("message_id") or msg.get("id")
if msg_id and msg_id in seen_ids:
continue
if msg_id:
seen_ids.add(msg_id)
subject = (msg.get("subject") or "").lower()
sender = (msg.get("from") or "").lower()
# Пример узкого сопоставителя
if "verify" in subject and "no-reply" in sender:
return msg
time.sleep(poll_interval_s)
raise TimeoutError("Подходящий email не пришел до тайм-аута")
def extract_otp(message_json):
text = message_json.get("text") or message_json.get("text_plain") or ""
m = re.search(r"\b(\d{6})\b", text)
if not m:
raise ValueError("OTP не найден в текстовом теле")
return m.group(1)
Извлечение на основе веб-хуков (высокий уровень)
В режиме веб-хука вы инвертируете поток:
- Ваша точка веб-хука получает сообщение JSON.
- Вы проверяете подпись.
- Вы записываете сообщение в хранилище с ключом по
inbox_id. - Ваш тест-раннер или агент ждет в этом хранилище (или внутренней очереди) подходящего события.
Mailhook поддерживает подписанные payload, поэтому проверка должна быть первоклассным шагом. Для точной схемы подписи и заголовков обратитесь к: Mailhook llms.txt.
Безопасность: относитесь к email как к недоверенному входу (особенно с LLM)
Если LLM-агент читает email, вы должны предполагать, что контент может быть враждебным. Даже верификационные email могут содержать неожиданный контент, пересланные треды или вредоносные ссылки, если атакующий может вызвать сообщения в ваш ящик.
Практические меры защиты:
- Проверяйте подписи веб-хуков и отклоняйте неподписанные или недействительные payload.
-
Не рендерите HTML в конвейерах агентов. Предпочитайте
text/plainплюс строгое извлечение. - Вносите в белый список то, что извлекаете. Для магических ссылок валидируйте hostname и путь против ожидаемых паттернов перед их переходом.
- Минимизируйте хранение и логи. Email часто содержат секреты, токены или PII.
- Ограничивайте вывод инструмента. Давайте агенту только OTP или валидированный URL, а не полный сырой email.
Эти средства контроля - не только гигиена безопасности, они улучшают надежность, потому что ваш конвейер становится детерминированным и менее чувствительным к дрифту шаблонов.
Где подходит Mailhook: одноразовые ящики + JSON-вывод + веб-хуки
Если вы реализуете “получение email через API” для агентов или CI, Mailhook разработан вокруг примитивов, которые вы обычно в итоге строите сами:
- Создание одноразовых ящиков через API
- Email, доставляемые как структурированный JSON
- Веб-хуки в реальном времени (с подписанными payload)
- API опроса как резервный путь
- Общие домены для быстрого старта и поддержка пользовательских доменов для более жесткого контроля
- Пакетная обработка email для рабочих процессов с более высокой пропускной способностью
Если вы хотите точные форматы request/response (и вы строите инструменты для LLM), начните с канонического справочника: https://mailhook.co/llms.txt, затем подключите его к вашему тестовому фреймворку или инструментам агента.
Чек-лист надежности перед отправкой
Перед полаганием на извлечение email в автоматизации убедитесь, что вы можете ответить “да” на эти вопросы:
- Вы создаете свежий ящик на запуск, попытку или сессию.
- Ваша логика ожидания основана на дедлайне, никаких фиксированных sleep.
- Вы дедуплицируете по ID сообщения (или эквивалентному стабильному идентификатору).
- Ваши правила сопоставления узкие и дружественные к корреляции.
- Вы проверяете подписи веб-хуков (если используете веб-хуки).
- Вы извлекаете минимальные артефакты (OTP, валидированный URL) вместо подачи полных email в агента.
Если вы реализуете это, “получение email через API” становится предсказуемым строительным блоком вместо самого нестабильного шага в вашем конвейере.
Чтобы исследовать программируемые ящики Mailhook и извлечение JSON email, см. Mailhook и держите контракт интеграции под рукой: Mailhook llms.txt.