deltachat-webhook: альтернатива Telegram-ботам через почту

У меня в инфраструктуре мониторинг уже несколько лет стоит на Telegram-ботах. Работало, работало - и перестало. Почему? Да кто ж его знает. Никогда такого не было, и вот опять. Боты молчат, сообщения приходят с задержкой или не приходят вообще, а ты сидишь и думаешь, что именно сломалось - связь или всё остальное. Мониторинг, который молчит именно тогда, когда что-то сломалось – это, строго говоря, не мониторинг.

Начал думать, как это фиксить.

Куда бедному крестьянину податься

Централизованные сервисы будут глушить - это теперь просто факт инфраструктуры, как погода. Значит, нужно что-то децентрализованное. Или хотя бы такое, что не представляет интереса как цель: мой мониторинг конкретно никому не нужен, и хорошо бы, чтобы он выглядел соответственно.

Смотрел на ntfy, Matrix, email напрямую. Везде своя проблема. Централизованные email сервисы шифрованный трафик не любят, да и с клиентами вечно что-то не так. Свой почтовый сервер - отдельная история: половина усилий уходит не на доставку, а на борьбу со спам-фильтрами.

Остановился на Delta Chat по трем причинам:

Первая - маскируется под email. Работает через обычный SMTP/IMAP. Для любого фильтра это просто почта. Заблокировать отдельно, не задев корпоративную переписку, практически невозможно.

Вторая - не требователен к ресурсам. Бот на VPS с 1GB RAM работает без проблем. Никакого отдельного брокера, никакой базы данных.

Третья - всё шифруется по умолчанию. Не то чтобы содержимое уведомлений сильно секретно, но приятно.

В общем чтобы заблокировать Delta Chat, нужно заблокировать email. Никто этого не делает - email нужен везде. В принципе заблокировать можно все, но некоторые вещи сложнее.

В догонку у Delta Chat есть официальный deltachat-rpc-server – JSON-RPC сервер, который даёт полный API к аккаунту. На этом и строится вся автоматизация - “дешево, надежно и практично”…

Архитектура deltachat-webhook

Репозиторий: github.com/lazarus-net/deltachat-notify

Три слоя:

[ваш сервис] 
POST /webhook  {"text": "..."}  Bearer <token> 
--> deltachat-webhook  (Go binary, HTTP server) 
--> deltachat-rpc-server (subprocess, JSON-RPC)  
--> chatmail relay server  (Postfix, Dovecot, filtermail)
--> email transport        (SMTP/IMAP) 
--> Delta Chat у получателя

Конфигурация

Настройки сервера – в settings/my_server/:

server_settings.mk      -- HOST_IP, SERVER_ID, feature flags
extended_settings.mk    -- SSH-ключ, домены
webhook_services.txt    -- список зарегистрированных сервисов
webhook_bot.age         -- учётные данные бота (age-encrypted)
webhook_tokens/NAME.age -- Bearer-токен сервиса (age-enrypted)
webhook_groups/NAME.group_id -- group_id сервиса

На сервере бот читает два файла из /opt/deltachat-webhook/:

  • bot.conf – адрес и пароль бота

  • services.conf – строки name token group_id

Эти файлы генерируются и деплоятся через make. Руками не редактируются. Слушает на 127.0.0.1:8095, за nginx.

Развёртывание

Всё управление – через make. Идемпотентно: запускать можно повторно, состояние не ломается.

Полное развёртывание (сборка бинарника, создание аккаунтов бота и админа, регистрация сервисов, деплой на сервер, запуск systemd-сервиса):

make settings=my_server deploy_webhook

Добавить новый сервис:

# 1. Добавить имя в список
echo "my-service" >> settings/my_server/webhook_services.txt
# 2. Зарегистрировать: создаёт токен + Delta Chat группу на сервере
make settings=my_server register_webhook_service SERVICE=my-service
# 3. Обновить конфиг на сервере и перезапустить
make settings=my_server update_webhook_conf
# 4. Пригласить пользователей: QR-код в терминале, сканировать из Delta Chat
make settings=my_server webhook_qr SERVICE=my-service
# 5. Получить Bearer-токен для вызывающего сервиса
make settings=my_server show_webhook_token SERVICE=my-service

Секреты (токены, учётные данные бота) хранятся age-encrypted в settings/my_server/ - безопасно коммитить в репозиторий.

Посмотреть все зарегистрированные сервисы:

make settings=my_server ls_webhook_services

На сервере бот работает как systemd-сервис. При добавлении нового сервиса register_webhook_service останавливает его на ~2 секунды (нужно освободить блокировку accounts dir), затем перезапускает. Это ожидаемое поведение.

Отправляем уведомление

curl:

curl -sf -X POST https://deltachat.example.org/webhook \  -H "Authorization: Bearer abc123def456" \  -H "Content-Type: application/json" \  -d '{"text": "Deploy завершён"}' \  && echo "ok"

bash-функция:

notify() {    curl -sf -X POST https://deltachat.example.org/webhook \        -H "Authorization: Bearer ${DC_TOKEN}" \        -H "Content-Type: application/json" \        -d "{\"text\": \"$1\"}" >/dev/null || true
}
notify "Бэкап завершён: $(date)"
notify "Диск > 90% на $(hostname)"

Python:

import httpx
WEBHOOK = "https://deltachat.example.org/webhook"
TOKEN = "abc123def456"
def notify(text: str) -> None:    httpx.post(        WEBHOOK,        headers={"Authorization": f"Bearer {TOKEN}"},        json={"text": text},        timeout=10.0,    )
notify(f"Воркер упал: {error}")

204 – доставлено. Всё остальное – ошибка, логировать и разбираться.

Email-бэкенд

Бот работает через chatmail-сервер – специализированный почтовый сервер для Delta Chat на базе upstream chatmail/relay (Postfix, Dovecot, filtermail, E2EE enforcement). Аккаунты создаются автоматически при первом подключении Delta Chat – никакой ручной провизии.

Развернуть chatmail-сервер:

make settings=my_server deploy_chatmail

Одна команда: клонирует chatmail/relay, настраивает DNS, ждёт propagation, запускает cmdeploy на сервере.

Публичные провайдеры VPS иногда ограничивают SMTP port 25. Проверьте перед тем как поднимать VPS.

Про надёжность

Delta Chat хранит переписку локально и синхронизируется через IMAP. Сервер хранит сообщения 30 дней по умолчанию, потом удаляет, так что диск не переполнится.

Итог

deltachat-webhook решает конкретную задачу: принять HTTP POST с текстом, доставить в Delta Chat группу. Тупо и деревянно.

Настройка и доработака AI-friendly.

Репозиторий