Каждый бизнес работает на электронной почте, и большая её часть — рутина: подтверждения, запросы статусов, пересылка нужному человеку, беглый просмотр рассылок в поисках одного важного абзаца. Интеграция ИИ-агента с электронной почтой на базе IMAP и SMTP берёт эту работу на себя прямо на вашей инфраструктуре — без сторонних SaaS-прослоек, без оплаты за каждого пользователя, без утечки данных с ваших серверов.
В этом гайде мы разберём весь стек: подключение к почтовому ящику, чтение и классификация сообщений, генерация черновиков ответов и отправка исходящей почты — всё с помощью саморазмещённого агента, который вы контролируете.
Почему IMAP + SMTP (а не вендорный API)
Когда речь заходит об «автоматизации почты», многие сразу тянутся к SaaS-коннекторам — Zapier, Make или API Gmail/Outlook. Они работают, но с оговорками: проверка OAuth-приложения, плата за каждого пользователя, лимиты частоты запросов, которые вы не контролируете, и данные, проходящие через чужие серверы.
IMAP (Internet Message Access Protocol) — стандартный протокол для чтения электронной почты с почтового сервера. SMTP (Simple Mail Transfer Protocol) — стандарт для отправки. Оба протокола независимы от вендора, универсально поддерживаются и не требуют никаких API-ключей от посредника.
Подход через IMAP/SMTP имеет конкретные преимущества:
- Универсальность. Работает с Google Workspace, Microsoft 365, ProtonMail Bridge, саморазмещёнными Postfix/Dovecot, Fastmail, Zoho — любым провайдером, предоставляющим стандартный доступ к почтовому ящику.
- Нет привязки к вендору. Смените почтового провайдера, не переписав ни строки кода агента.
- Данные остаются вашими. Учётные данные и содержимое сообщений не попадают на сторонние SaaS-платформы.
- Нет помесячной оплаты за автоматизацию. Вы платите почтовому провайдеру (уже оплачено) и за токены LLM. Никакого тарификации «задач в месяц».
Обратная сторона — вам придётся заниматься инфраструктурой самостоятельно. Но, как мы увидим, это хорошо изученная и не самая сложная задача.
Настройка IMAP-доступа для ИИ-агента
Предварительные требования
Перед написанием кода вам понадобятся три вещи:
1. Почтовый ящик — выделенный адрес вроде agent@yourcompany.com или общий ящик, например support@yourcompany.com. 2. Учётные данные приложения — не ваш личный пароль. Google, Microsoft и большинство провайдеров позволяют сгенерировать пароль приложения с доступом только к IMAP/SMTP. 3. Параметры IMAP-сервера — обычно imap.yourprovider.com на порту 993 (TLS) и smtp.yourprovider.com на порту 587 (STARTTLS).
Подключение на Python (imaplib)
Стандартная библиотека Python включает imaplib. Вот минимальное, пригодное для продакшена подключение, которое читает непрочитанные сообщения из почтового ящика:
import imaplib
import email
from email.header import decode_header
IMAP_HOST = "imap.yourcompany.com"
IMAP_PORT = 993
EMAIL = "agent@yourcompany.com"
APP_PASSWORD = "your-app-password"
def fetch_unread(limit=20):
mail = imaplib.IMAP4_SSL(IMAP_HOST, IMAP_PORT)
mail.login(EMAIL, APP_PASSWORD)
mail.select("INBOX")
status, data = mail.search(None, "UNSEEN")
msg_ids = data[0].split()
messages = []
for uid in msg_ids[-limit:]: # last N unread
_, msg_data = mail.fetch(uid, "(RFC822)")
raw = msg_data[0][1]
msg = email.message_from_bytes(raw)
subject = decode_header(msg["Subject"])
subject = subject[0][0]
if isinstance(subject, bytes):
subject = subject.decode()
body = _extract_text(msg)
messages.append({
"uid": uid.decode(),
"from": msg["From"],
"to": msg["To"],
"subject": subject,
"body": body,
"date": msg["Date"],
"message_id": msg["Message-ID"],
})
mail.logout()
return messages
def _extract_text(msg):
if msg.is_multipart():
for part in msg.walk():
if part.get_content_type() == "text/plain":
payload = part.get_payload(decode=True)
charset = part.get_content_charset() or "utf-8"
return payload.decode(charset, errors="replace")
else:
payload = msg.get_payload(decode=True)
charset = msg.get_content_charset() or "utf-8"
return payload.decode(charset, errors="replace")
return ""
Несколько важных нюансов на практике:
UNSEENvsALL: ИспользуйтеUNSEEN, чтобы избежать повторной обработки. Помечайте сообщения как прочитанные (mail.store(uid, '+FLAGS', '\\Seen')) только после успешной обработки — тогда при сбое работа не потеряется.- Message-ID: Сохраняйте его — он понадобится для ответов в цепочке (заголовки
In-Reply-ToиReferencesзависят от него). - Письма только в HTML: Некоторые отправители не включают
text/plain. Добавьте запасной вариант, который убирает HTML-теги или использует библиотеку вродеbeautifulsoup4/html2textдля извлечения читаемого текста. - Вложения: Обходите части multipart-сообщений, проверяйте
Content-Dispositionи решайте, нужно ли агенту их обрабатывать (например, извлекать текст из PDF-счётов).
IMAP IDLE для доставки почти в реальном времени
Опрос раз в 30 секунд подходит для большинства задач сортировки, но если нужна реакция за доли секунды (например, мониторинг срочной очереди поддержки), используйте IMAP IDLE — сервер отправляет уведомления при поступлении новой почты.
import imaplib
def idle_loop(callback):
mail = imaplib.IMAP4_SSL(IMAP_HOST, IMAP_PORT)
mail.login(EMAIL, APP_PASSWORD)
mail.select("INBOX")
while True:
mail.send(b"A01 IDLE\r\n")
response = mail.readline() # waits for server push
if b"EXISTS" in response:
mail.send(b"DONE\r\n")
new_msgs = fetch_unread(limit=5)
for msg in new_msgs:
callback(msg)
mail.send(b"A01 IDLE\r\n")
На практике IDLE требует поддержания постоянного TCP-соединения. Используйте менеджер соединений с автоматическим переподключением (соединения обрываются примерно через 29 минут на большинстве серверов, поэтому периодически отправляйте NOOP для поддержания активности).
Отправка почты через SMTP: черновики и автоответы
Чтение почты — лишь половина работы. Агенту нужно и отправлять: пересылать сводки, создавать черновики ответов для проверки человеком или — при наличии защитных механизмов — отвечать напрямую.
import smtplib
from email.mime.text import MIMEText
SMTP_HOST = "smtp.yourcompany.com"
SMTP_PORT = 587
def send_email(to, subject, body, in_reply_to=None, references=None):
msg = MIMEText(body, "plain", "utf-8")
msg["From"] = EMAIL
msg["To"] = to
msg["Subject"] = subject
if in_reply_to:
msg["In-Reply-To"] = in_reply_to
msg["References"] = references or in_reply_to
with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as server:
server.starttls()
server.login(EMAIL, APP_PASSWORD)
server.send_message(msg)
Тредирование критически важно: без заголовков In-Reply-To и References ваш ответ отобразится как новая переписка, а не продолжение цепочки. Всегда сохраняйте оригинальный Message-ID.
Защитные механизмы для автоответов
Никогда не позволяйте LLM отправлять почту полностью автономно. Безопасный паттерн:
1. Порог уверенности. LLM классифицирует письмо и возвращает оценку уверенности (0–1). Автоответ только при значении выше 0.9. 2. Белые списки. Автоответ только на известные внутренние адреса или заранее одобренные домены отправителей. 3. Режим «сначала черновик». Для внешних отправителей генерируйте черновик и ставьте в очередь на одобрение человеком, а не отправляйте сразу. 4. Лимиты частоты. Ограничьте исходящие автоответы до N в час, чтобы предотвратить петли (кто-то включает автоответ «не в офисе», ваш агент отвечает, их автоответ срабатывает снова…).
Сортировка входящих: классификация, маршрутизация, приоритизация
Здесь LLM показывает свою ценность. Сортировка почтового ящика — это классификация каждого входящего сообщения и принятие решения, что с ним делать.
Схема классификации
Задайте фиксированный набор категорий, из которых LLM должен выбирать:
TRIAGE_SCHEMA = {
"categories": [
"urgent_customer_issue",
"internal_question",
"invoice_or_payment",
"newsletter_or_promo",
"meeting_request",
"spam_or_phishing",
"needs_human_review"
]
}
Передайте каждое письмо LLM с системным промптом:
You are an email triage agent. Classify the following email into exactly one
category from the list. Also extract: sender_name, urgency (low/medium/high),
and a one-sentence summary. Return valid JSON only.
Categories: urgent_customer_issue, internal_question, invoice_or_payment,
newsletter_or_promo, meeting_request, spam_or_phishing, needs_human_review
LLM возвращает структурированный JSON:
{
"category": "urgent_customer_issue",
"sender_name": "Maria Chen",
"urgency": "high",
"summary": "Customer reports production API returning 500 errors since 9am."
}
Маршрутизация действий
Каждая категория соответствует определённому действию:
| Категория | Действие |
|---|---|
urgent_customer_issue | Переслать в канал #support в Slack + отправить подтверждение отправителю |
internal_question | Направить соответствующему сотруднику по ключевым словам |
invoice_or_payment | Извлечь сумму и срок оплаты, записать в таблицу бухгалтерии |
newsletter_or_promo | Архивировать + извлечь ключевой вывод в еженедельный дайджест |
meeting_request | Распарсить дату и время, проверить календарь, отправить предварительное подтверждение |
spam_or_phishing | Переместить в спам, пометить домен отправителя |
needs_human_review | Поставить в очередь в панели проверки для ручной обработки |
Снижение затрат на LLM
Для каждого письма не нужен GPT-4. Грамотный маршрутизирующий слой экономит бюджет:
1. Предварительная фильтрация по правилам. Если отправитель есть в вашей базе контактов, а тема соответствует [INVOICE], пропускайте LLM полностью — маршрутизируйте напрямую в бухгалтерию. 2. Дешёвая модель для классификации. Используйте маленькую быструю модель (GPT-4o-mini, Claude Haiku или локальную модель на 7B) для шага классификации. Дорогую модель берегите для составления ответов. 3. Пакетная обработка. Накапливайте 5–10 писем и классифицируйте их в одном вызове LLM с несколькими входными данными — это снижает накладные расходы на сообщение. 4. Локальные модели для извлечения. Извлечение сущностей (даты, суммы, имена) можно запускать на небольшой локальной модели без затрат на API.
Архитектура: цикл опроса, конечный автомат и идемпотентность
Для продакшен-почтового агента нужен не просто скрипт, а архитектура, устойчивая к сбоям.
Цикл опроса
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Fetch IMAP │────▶│ Classify │────▶│ Route/Act │
│ (UNSEEN) │ │ (LLM) │ │ (send/fwd/ │
│ │ │ │ │ archive) │
└──────────────┘ └──────────────┘ └──────────────┘
│ │
└──────── Mark SEEN on success ◀──────────┘
Идемпотентность — обязательное требование. Если агент упадёт между классификацией и действием, при перезапуске он не должен повторно классифицировать или повторно отправлять. Решения:
- Храните обработанные UID в лёгкой базе данных (SQLite подойдёт).
- Помечайте IMAP-сообщения как
\Seenтолько после успешного прохождения всего конвейера. - Используйте
Message-IDкак ключ дедупликации, а не IMAP UID (UID могут меняться на некоторых серверах после компактификации).
Хранение состояния
Простая схема SQLite отслеживает всё:
CREATE TABLE processed_emails (
message_id TEXT PRIMARY KEY,
uid TEXT,
from_addr TEXT,
subject TEXT,
category TEXT,
urgency TEXT,
summary TEXT,
action_taken TEXT,
processed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Это также даёт вам аудиторский журнал с поиском по каждому решению агента — бесценный инструмент для отладки и комплаенса.
Безопасность и управление учётными данными
ИИ-агент с доступом к почте — мощный и опасный инструмент. Обезопасьте его:
- Пароли приложений с доступом только к IMAP+SMTP (без календаря, контактов и прав администратора).
- Выделенный почтовый ящик, а не чей-то личный аккаунт. Если агента скомпрометируют, зона поражения будет ограничена.
- Секреты в переменных окружения, никогда в коде. Используйте Docker Secrets или файл
.env, исключённый из контроля версий. - TLS везде. IMAP на порту 993 (неявный TLS), SMTP на порту 587 (STARTTLS). Никогда в открытом виде.
- Белый список IP. Если почтовый провайдер поддерживает, ограничьте доступ к IMAP/SMTP IP-адресом вашего VPS.
- Режим «только чтение» для мониторинга. Если агенту нужна только сортировка (без ответов), используйте разрешение IMAP «только чтение».
Обработка крайних случаев, которые вас настигнут
Реальная почта — хаос. Будьте готовы к следующему:
- Хаос с кодировками. Отправители используют ISO-8859-1, Windows-1252, UTF-8 и иногда битые кодировки. Всегда декодируйте с
errors="replace". - Вложенные multipart MIME. Некоторые письма имеют 5+ уровней вложенности (пересланные письма, содержащие пересланные письма). Обходите рекурсивно и аккуратно.
- Петли автоответов. Ваш агент отправляет ответ, автоответ получателя «не в офисе» срабатывает, ваш агент отвечает снова. Защитите себя проверкой заголовков (
X-Auto-Response-Suppress,Auto-Submitted) и лимитами частоты на отправителя. - Большие вложения. Вложение на 50 Мб может заблокировать конвейер обработки. Установите ограничение по размеру и пропускайте (или откладывайте) сообщения сверх порога.
- Приглашения в календарь (.ics). Это multipart-сообщения с частью
text/calendar. Парсите их отдельно. - Фишинг в почтовом ящике агента. Если агент обрабатывает фишинговые письма, он может переходить по вредоносным ссылкам в теле. Никогда не позволяйте агенту переходить по ссылкам или скачивать вложения без явных белых списков.
Если вам нужна готовая ИИ-команда, которая берёт сортировку почты из коробки — читает входящие письма на вашем домене, составляет черновики ответов, маршрутизирует нужному человеку — саморазмещённая ИИ-команда вроде OfficeForge поставляется с агентом-секретарём, который делает именно это, работая полностью на вашем VPS. Никакой подписки за каждого пользователя, никаких утечек данных за пределы вашей инфраструктуры, и вы используете собственный ключ модели, поэтому платите провайдеру LLM напрямую по базовому тарифу.
Купить — 15 400 ₽Мониторинг и наблюдаемость
Почтовый агент, работающий молча, — это агент, которому нельзя доверять. Встраивайте наблюдаемость с первого дня:
- Структурированное логирование. Логируйте каждый IMAP-запрос (количество, ошибки), каждую классификацию LLM (категория, уверенность) и каждое исходящее действие. Используйте JSON-логи для удобного поиска и фильтрации.
- Метрики. Отслеживайте количество обработанных писем в час, распределение по категориям (круговая диаграмма), долю автоответов, долю ручных корректировок.
- Оповещения. Если агент не может подключиться к IMAP в течение 10 минут или если очередь
needs_human_reviewпревышает N элементов, отправляйте оповещение в Slack/PagerDuty/Discord. - Еженедельный дайджест. Пусть агент сам резюмирует свою работу: «На этой неделе я обработал 342 письма, автоматически ответил на 47, переслал 89 команде и архивировал 206 рассылок.»
Сборка воедино: минимально жизнеспособный агент
Самая простая полезная версия этой системы — примерно 200 строк Python:
1. Опрашивайте IMAP каждые 30 секунд на предмет UNSEEN. 2. Предварительно фильтруйте по правилам отправителя/темы — пропускайте известный шум. 3. Классифицируйте оставшиеся сообщения с помощью дешёвой LLM. 4. Маршрутизируйте: архивируйте рассылки, пересылайте срочные проблемы, ставьте черновики в очередь на ручную проверку. 5. Логируйте всё в SQLite. 6. Оповещайте через webhook, если требуется немедленное вмешательство человека.
Вы можете запустить это в виде одного Docker-контейнера рядом с существующей инфраструктурой. Никаких SaaS-подписок, никаких утечек данных из вашей сети и полный контроль над тем, что агент делает, а чего нет.
Дальше расширяйте: добавляйте обработку вложений, интеграцию с инструментом управления проектами (создание тикета при поступлении срочной проблемы), подключение к календарю для встреч, постройте панель ручной проверки. Основа остаётся прежней — IMAP для чтения, LLM для принятия решений, SMTP для действий — и каждый компонент работает на оборудовании, которое принадлежит вам.
Электронная почта никуда не денется. Интеграция ИИ-агента с почтой на открытых протоколах означает, что ваша автоматизация работает сегодня, будет работать при смене провайдера в следующем году и не потребует отчислений кому-либо за каждое обработанное сообщение.
FAQ
Может ли ИИ-агент читать и отправлять электронную почту без стороннего почтового API?
Да. Стандартный IMAP позволяет читать почтовые ящики, а SMTP — отправлять письма. Оба протокола открыты и поддерживаются любым почтовым сервером. Никаких SDK от поставщика не требуется.
Как защитить учётные данные, когда ИИ-агент обращается к почте?
Используйте пароли приложений с минимальными правами, ограничьте агента отдельным почтовым ящиком или подадресом, ротируйте учётные данные ежеквартально и разворачивайте агента на инфраструктуре, которую вы контролируете.
Какая архитектура лучше — опрос или доставка писем в ИИ-агент в реальном времени?
IMAP IDLE обеспечивает уведомления о новых письмах почти в реальном времени; опрос каждые 30–60 секунд проще и работает везде. Для большинства задач сортировки опрос раз в 30 секунд достаточен и устойчивее.
Можно ли подключить ИИ-агента к почте Google Workspace или Microsoft 365?
Обе платформы поддерживают IMAP/SMTP с паролями приложений или OAuth2. Google требует включения «Небезопасных приложений» или использования OAuth2; Microsoft использует OAuth2 или IMAP с современной аутентификацией. Оба варианта отлично работают с саморазмещённым агентом.
Как ИИ-агент решает, на какие письма отвечать автоматически?
Вы задаёте правила сортировки: белые списки отправителей, шаблоны совпадения по теме, пороги уверенности от классификатора на базе LLM и пути эскалации для неоднозначных случаев. Никогда не отправляйте автоматически без защитных механизмов.
Дешевле ли саморазмещать почтового ИИ-агента, чем платить за SaaS-инструмент для работы с входящими?
Саморазмещение исключает плату за каждого пользователя. Вы платите только за вычислительные ресурсы (часто это уже имеющийся VPS) и токены LLM по стоимости провайдера — как правило, на 80–95% дешевле для команды любого размера.
