Настройка электронной почты
Hermes умеет принимать письма и отвечать на них по обычным протоколам IMAP и SMTP. Отправьте письмо на адрес агента — он ответит прямо в той же ветке. Никакого особого клиента или bot API не нужно. Подойдёт Gmail, Outlook, Yahoo, Fastmail и любой провайдер с поддержкой IMAP/SMTP.
Эта страница про почтовый адаптер шлюза. Он работает на встроенных модулях Python imaplib, smtplib и email. Для такого способа подключения не нужны ни дополнительные пакеты, ни внешние сервисы.
Не путайте с встроенным навыком Himalaya для почты: тот даёт агенту управлять почтой через команды в терминале и требует внешнего CLI himalaya плюс конфиг-файл Himalaya.
| Задача | Что настраивать | Внешняя зависимость |
|---|---|---|
| Дать людям писать агенту Hermes и получать ответы | Почтовый адаптер шлюза с этой страницы | Только аккаунт IMAP/SMTP, больше ничего |
| Дать агенту просматривать, составлять, перемещать и разбирать письма через терминальные инструменты | Навык Himalaya для почты | CLI himalaya и ~/.config/himalaya/config.toml |
Что понадобится заранее
- Отдельный почтовый аккаунт под вашего агента Hermes (личную почту не используйте)
- Включённый IMAP на этом аккаунте
- Пароль приложения, если у вас Gmail или другой провайдер с двухфакторной аутентификацией
Настройка Gmail
- Включите двухфакторную аутентификацию в Google-аккаунте
- Откройте App Passwords
- Создайте новый пароль приложения (выберите «Mail» или «Other»)
- Скопируйте 16-символьный пароль — его и используйте вместо обычного
Outlook / Microsoft 365
- Зайдите в настройки безопасности
- Включите 2FA, если ещё не включена
- Создайте пароль приложения в разделе «Additional security options»
- IMAP-хост:
outlook.office365.com, SMTP-хост:smtp.office365.com
Другие провайдеры
IMAP/SMTP поддерживает большинство почтовых сервисов. Загляните в документацию своего провайдера и уточните:
- IMAP-хост и порт (обычно порт 993 с SSL)
- SMTP-хост и порт (обычно порт 587 с STARTTLS)
- нужны ли пароли приложений
Proton Mail Bridge и локальные релеи
Proton Mail Bridge (и похожие локальные релеи вроде самостоятельно поднятого MTA)
слушают на loopback со STARTTLS и самоподписанным сертификатом, поэтому
умолчания (неявный TLS на IMAP 993 и проверка сертификатов) подключиться не дадут.
Переопределите транспорт в ~/.hermes/config.yaml:
platforms:
email:
enabled: true
extra:
imap_host: 127.0.0.1
imap_security: starttls # tls (по умолчанию) | starttls | plain
imap_tls_verify: false # у Bridge самоподписанный сертификат
smtp_host: 127.0.0.1
smtp_security: starttls # по умолчанию: tls на порту 465, иначе starttls
smtp_tls_verify: false
и пропишите EMAIL_IMAP_PORT=1143 и EMAIL_SMTP_PORT=1025 рядом с учётными
данными Bridge в ~/.hermes/.env. Неизвестные значения *_security выдают
предупреждение и откатываются к безопасному умолчанию. Отключать *_tls_verify
стоит только для loopback-хостов — для любого другого хоста Hermes напишет в лог
предупреждение о снятой проверке.
Шаг 1: Настройте Hermes
Самый простой путь:
hermes gateway setup
В меню платформ выберите Email. Мастер спросит ваш почтовый адрес, пароль, хосты IMAP/SMTP и список разрешённых отправителей.
Настройка вручную
Добавьте в ~/.hermes/.env:
# Обязательно
EMAIL_ADDRESS=hermes@gmail.com
EMAIL_PASSWORD=abcd efgh ijkl mnop # Пароль приложения (не обычный пароль)
EMAIL_IMAP_HOST=imap.gmail.com
EMAIL_SMTP_HOST=smtp.gmail.com
# Безопасность (рекомендуется)
EMAIL_ALLOWED_USERS=your@email.com,colleague@work.com
# Обязательно: точный authserv-id в самом верхнем заголовке Authentication-Results
# вашего принимающего сервера (Gmail: mx.google.com).
# Этот сервер должен вырезать входящие заголовки с таким id, прежде чем добавить свой.
EMAIL_AUTHSERV_ID=mx.google.com
# Опционально
EMAIL_IMAP_PORT=993 # По умолчанию: 993 (IMAP SSL)
EMAIL_SMTP_PORT=587 # По умолчанию: 587 (SMTP STARTTLS)
EMAIL_POLL_INTERVAL=15 # Секунд между проверками входящих (по умолчанию: 15)
EMAIL_HOME_ADDRESS=your@email.com # Адрес доставки по умолчанию для cron-задач
Шаг 2: Запустите шлюз
hermes gateway # Run in foreground
hermes gateway install # Install as a user service
sudo hermes gateway install --system # Linux only: boot-time system service
При старте адаптер:
- Проверяет соединения по IMAP и SMTP
- Помечает все письма во входящих как «прочитанные» (обрабатываются только новые)
- Начинает опрашивать ящик на предмет новых сообщений
Как это работает
Приём сообщений
Адаптер опрашивает IMAP-ящик на непрочитанные письма (UNSEEN) с заданным интервалом (по умолчанию — каждые 15 секунд). С каждым новым письмом происходит следующее:
- Тема письма добавляется в контекст (например,
[Subject: Deploy to production]) - Ответные письма (тема начинается с
Re:) идут без префикса темы — ветка уже задана - Вложения кешируются локально:
- Картинки (JPEG, PNG, GIF, WebP) → доступны инструменту зрения
- Документы (PDF, ZIP и т. д.) → доступны для работы с файлами
- Письма только в HTML очищаются от тегов, чтобы извлечь обычный текст
- Письма от самого агента отфильтровываются, чтобы не возникало петли ответов
- Автоматические отправители и noreply молча игнорируются —
noreply@,mailer-daemon@,bounce@,no-reply@, а также письма с заголовкамиAuto-Submitted,Precedence: bulkилиList-Unsubscribe
Отправка ответов
Ответы уходят по SMTP с корректной привязкой к ветке:
- Заголовки In-Reply-To и References держат письма в одной цепочке
- Тема сохраняется с префиксом
Re:(без двойногоRe: Re:) - Message-ID генерируется с доменом агента
- Ответ уходит обычным текстом (UTF-8)
Прикреплённые файлы
Агент может прикладывать файлы к ответам. Укажите в ответе MEDIA:/path/to/file, и файл прикрепится к исходящему письму.
Пропуск вложений
Чтобы игнорировать все входящие вложения (ради защиты от вредоносов или экономии трафика), добавьте в config.yaml:
platforms:
email:
skip_attachments: true
С этой настройкой вложения и встроенные части пропускаются ещё до декодирования содержимого. Текст письма при этом обрабатывается как обычно.
Контроль доступа
По умолчанию доступ к почте строже, чем на чат-платформах:
EMAIL_ALLOWED_USERSзадан → обрабатываются письма только с этих адресов (а также отGATEWAY_ALLOWED_USERSили одобренных через сопряжение)- Список разрешений не задан → незнакомые отправители молча игнорируются
EMAIL_ALLOW_ALL_USERS=true→ принимается любой отправитель (осторожно с этим)platforms.email.unauthorized_dm_behavior: pair→ незнакомый отправитель получает код для сопряженияplatforms.email.unauthorized_dm_behavior: decline→ незнакомый отправитель получает один вежливый отказ, а потом 24 часа — ничего
Записи списка разрешённых сверяются с адресом целиком. Голая запись вроде alice (скажем, имя пользователя чата в GATEWAY_ALLOWED_USERS) никогда не пропустит alice@ ни на каком домене, а письмо с такого адреса отбрасывается, без сопряжения и без отказа.
Hermes реагирует на письмо, только когда заголовок Authentication-Results, проставленный вашим принимающим сервером, подтверждает домен из From: (DMARC или выровненные SPF/DKIM). Это верно и при открытом доступе (EMAIL_ALLOW_ALL_USERS / GATEWAY_ALLOW_ALL_USERS): открытый доступ пускает любого отправителя, но каждый разговор и каждый ответ привязаны к From:, так что поддельный From: отправил бы текст злоумышленника в сессию этого адреса, а Hermes разослал бы его по почте. Коды сопряжения и отказы тоже требуют подтверждённого From:, поэтому ни то ни другое не уходит на поддельный адрес. Если ваш почтовый сервер такой заголовок не ставит, задайте platforms.email.require_authenticated_sender: false (или EMAIL_TRUST_FROM_HEADER=true) и примите этот риск. Иначе письмо допущенного отправителя без такого заголовка отбрасывается, а в журнале шлюза появляется предупреждение Dropping sender with unauthenticated From. Такое же предупреждение, но со ссылкой на platforms.email.authserv_id (EMAIL_AUTHSERV_ID), срабатывает, когда самый верхний заголовок Authentication-Results (тот, что добавляет ваш сервер; нижние никогда не учитываются) называет не в точности закреплённый authserv_id. Значение authserv_id должно в точности совпадать с authserv-id, который ваш сервер пишет перед первой ; этого заголовка. Письмо с адреса из EMAIL_ALLOWED_USERS / GATEWAY_ALLOWED_USERS, не прошедшее проверку по другой причине (например, у отправителя сломана DKIM или пересылка нарушает выравнивание), отбрасывается с тем же предупреждением и вердиктом, но без подсказки, как отказаться от проверки. Неудачные письма прочих отправителей, скажем с поддельным From: при открытом доступе, отбрасываются молча: только запись на уровне debug.
Закрепление authserv_id обязательно, пока включена проверка отправителя. Без platforms.email.authserv_id (EMAIL_AUTHSERV_ID) Hermes не отличит заголовок Authentication-Results вашего сервера от написанного самим отправителем (собственный MTA, который своего заголовка не добавляет, оставляет сверху заголовок отправителя), поэтому не доверяет ни одному: отбрасывается каждое письмо, которому нужен подтверждённый From:, а журнал шлюза один раз сообщает об этом и подсказывает исправление. Чтобы найти значение, откройте письмо, доставленное вашим сервером («показать оригинал» / исходный текст), и скопируйте токен перед первой ; в самом верхнем заголовке Authentication-Results, например mx.google.com для Gmail. Если этот токен меняется от письма к письму, перед вами имя хоста отдельного ретранслятора, а не authserv-id: RFC 8601 определяет authserv-id как стабильное имя административного домена, поэтому настройте свой MTA так, чтобы он ставил такое имя (например, AuthservID в OpenDKIM / OpenDMARC), и закрепите его. Совпадение id — это закрепление, а не доказательство происхождения: убедитесь, что ваш MTA вырезает входящие заголовки Authentication-Results с его id, прежде чем добавить свой. Если стабильный id закрепить нельзя, откажитесь от проверки явно через platforms.email.require_authenticated_sender: false (или EMAIL_TRUST_FROM_HEADER=true) и примите, что From: тогда принимается на веру как написан.
Для обычной работы используйте отдельный почтовый ящик и настройте EMAIL_ALLOWED_USERS. Сопряжение по почте отключено по умолчанию: в общих ящиках часто скапливаются посторонние непрочитанные письма, и Hermes не должен отвечать этим отправителям автоматически.
Решение проблем
| Проблема | Решение |
|---|---|
| «IMAP connection failed» при старте | Проверьте EMAIL_IMAP_HOST и EMAIL_IMAP_PORT. Убедитесь, что IMAP включён на аккаунте. Для Gmail включите его в Settings → Forwarding and POP/IMAP. |
| «SMTP connection failed» при старте | Проверьте EMAIL_SMTP_HOST и EMAIL_SMTP_PORT. Убедитесь, что пароль верный (для Gmail — пароль приложения). |
| Сообщения не приходят | Проверьте, что адрес отправителя есть в EMAIL_ALLOWED_USERS. Если в журнале шлюза написано authserv-id is not configured, задайте EMAIL_AUTHSERV_ID — точный id из самого верхнего заголовка Authentication-Results, который пишет ваш сервер. Загляните в спам — некоторые провайдеры помечают автоматические ответы. |
| «Authentication failed» | Для Gmail нужен именно пароль приложения, а не обычный. Сначала включите 2FA. |
| Дублирующиеся ответы | Убедитесь, что запущен лишь один экземпляр шлюза. Проверьте hermes gateway status. |
| Медленный ответ | Интервал опроса по умолчанию — 15 секунд. Уменьшите через EMAIL_POLL_INTERVAL=5 ради скорости (но IMAP-соединений будет больше). |
| Ответы не складываются в ветку | Адаптер использует заголовки In-Reply-To. Некоторые клиенты (особенно веб) могут неправильно группировать автоматические письма. |
Безопасность
Заведите отдельный почтовый аккаунт. Личную почту не подключайте — агент хранит пароль в .env и через IMAP получает полный доступ к ящику.
- Пользуйтесь паролями приложений вместо основного пароля (для Gmail с 2FA это обязательно)
- Задайте
EMAIL_ALLOWED_USERS, чтобы ограничить круг тех, кто может общаться с агентом - Задайте
EMAIL_AUTHSERV_ID— точный id из самой верхней отметкиAuthentication-Resultsпринимающего MTA — и убедитесь, что этот MTA вырезает входящие заголовки с таким id - Пароль лежит в
~/.hermes/.env— защитите этот файл (chmod 600) - По умолчанию IMAP идёт через SSL (порт 993), а SMTP — через STARTTLS (порт 587), так что соединения зашифрованы
Справочник переменных окружения
| Переменная | Обязательна | По умолчанию | Описание |
|---|---|---|---|
EMAIL_ADDRESS | Да | — | Почтовый адрес агента |
EMAIL_PASSWORD | Да | — | Пароль почты или пароль приложения |
EMAIL_IMAP_HOST | Да | — | Хост IMAP-сервера (например, imap.gmail.com) |
EMAIL_SMTP_HOST | Да | — | Хост SMTP-сервера (например, smtp.gmail.com) |
EMAIL_IMAP_PORT | Нет | 993 | Порт IMAP-сервера |
EMAIL_SMTP_PORT | Нет | 587 | Порт SMTP-сервера |
EMAIL_POLL_INTERVAL | Нет | 15 | Секунд между проверками входящих |
EMAIL_ALLOWED_USERS | Нет | — | Разрешённые адреса отправителей через запятую |
EMAIL_AUTHSERV_ID | Да, если проверка отправителя не отключена | — | Точный authserv-id в самом верхнем заголовке Authentication-Results вашего принимающего сервера; без него отбрасывается каждое письмо, которому нужен подтверждённый From: |
EMAIL_HOME_ADDRESS | Нет | — | Адрес доставки по умолчанию для cron-задач |
EMAIL_ALLOW_ALL_USERS | Нет | false | Принимать всех отправителей (не рекомендуется) |