Если ваша CMS или CRM умеет отправлять email-копию о новом заказе на произвольный адрес — этот гайд для вас. InSales, RetailCRM, МойСклад, WooCommerce, Битрикс, самописная система — без разницы. Инфраструктура одна и та же. Ссылка на гитхаб с полный мануалом по установке на русском в конце статьи.
Поводом написать стало то, что неделю назад приложение InSales было удалено из App Store и пуши о заказах пропали сразу. Таким образом мы пропустили несколько заказов, но благо они не сорвались полностью, хотя небольшой неприятный осадок остался.
Первая мысль при поиске решения — n8n или Make. Но зарубежные no‑code платформы сейчас работают в России нестабильно из‑за замедлений и блокировок трафика. Строить критическую бизнес‑инфраструктуру на том, что может лечь в любой момент — плохая идея.
Задача: автономная система, работающая внутри РФ, без постоянного сервера, с доставкой уведомлений в Telegram за секунды. Решение — Yandex Cloud Serverless: он не боится блокировок, имеет очень щедрые лимиты, благодаря чему функция работает полностью бесплатно. К тому же, сервис очень гибок в настройке и улучшении.
Расскажу, что получилось, и дам полный гайд по настройке.
Архитектура: как это работает
Ключевой инсайт: InSales (и большинство других CMS/CRM) умеет отправлять email-копию о каждом новом заказе на указанный адрес. Этот email и стал источником данных. Ищите в настройках своей платформы что‑то вроде «отправлять копию заказа на email».
У Yandex Cloud есть Email Trigger — сервис, который создаёт технический почтовый адрес вида xxxx@serverless.yandexcloud.net. Когда на него приходит письмо, автоматически запускается Cloud Function с телом письма в payload.
Дальше всё просто:
InSales ↓ email-уведомление о заказеYandex Cloud Email Trigger ↓Cloud Function (Node.js) ↓Telegram Bot API
Уведомление приходит в Telegram через 5–10 секунд после оформления заказа.
Две версии: Lite и Pro
Я сделал два варианта под разные сценарии.
Lite — для тех, кто работает в одиночку или просто хочет видеть заказы без лишних усложнений:
InSales email → Email Trigger → Cloud Function → Telegram
Никаких баз данных, никаких очередей. Настраивается за 20–40 минут.
Pro — скорее для команды менеджеров, где важно контролировать, кто и когда взял заказ в работу. Если заказ никто не взял в течение 10 минут (можно настроить время), то придёт повторное напоминание.
InSales email ↓Email Trigger ↓Cloud Function ├─ отправляет заказ в Telegram (с кнопкой «Принять заказ») ├─ сохраняет заказ в YDB (статус: pending) └─ кладёт request_id в YMQ с задержкой 10 минут ↓ если заказ не принят - отправляет напоминание в Telegram
Почему YDB + YMQ
Можно было обойтись простым setTimeout или внешним cron — но оба варианта ненадёжны в serverless‑среде, где функция живёт ровно столько, сколько нужно для выполнения запроса.
YDB Serverless хранит статус каждого заказа (pending / accepted). При нажатии кнопки статус меняется — и когда YMQ через 10 минут снова вызывает функцию, она проверяет базу и молчит, если заказ уже принят.
YMQ (Yandex Message Queue) — это совместимый с AWS SQS брокер очередей. Он позволяет положить сообщение с задержкой (DelaySeconds: 600) и гарантировать его доставку. Функция не висит в памяти, а просто просыпается, когда пришло время.
Это классическая Event‑Driven Architecture: одна Cloud Function обрабатывает три типа событий, определяя источник по структуре входящего event:
|
Что пришло в event |
Что делает функция |
|---|---|
|
|
Парсит заказ, пишет в YDB, отправляет в Telegram, кладёт в YMQ |
|
|
Меняет статус в YDB, редактирует кнопку в Telegram |
|
|
Проверяет статус в YDB, при необходимости шлёт напоминание |
Ни одного постоянно работающего сервера. Платим только за фактические вызовы.
Сравнительная таблица версий
|
Возможность |
Lite |
Pro |
|---|---|---|
|
Уведомление о заказе в Telegram |
✅ |
✅ |
|
Парсинг email-письма InSales |
✅ |
✅ |
|
Кнопка «Принять заказ» |
❌ |
✅ |
|
Статус заказа в YDB |
❌ |
✅ |
|
Кто принял заказ |
❌ |
✅ |
|
Напоминание, если заказ не принят |
❌ |
✅ |
|
Время настройки |
20-40 мин |
60-120 мин |
Экономика: почему это почти бесплатно
Проект работает полностью на serverless, отдельный сервер не нужен. Оплата идёт только за фактическое использование.
На момент написания статьи Yandex Cloud даёт каждый месяц бесплатно:
-
Cloud Functions: 1 000 000 вызовов + 10 GB×hour выполнения
-
Yandex Message Queue: 100 000 запросов
-
YDB Serverless: 1 000 000 Request Units + 1 ГБ хранения
Триггеры (Email Trigger, YMQ Trigger) тарифицируются отдельно по числу вызовов функции, то есть дополнительных расходов за сами триггеры нет.
Посчитаем реальную нагрузку для Pro-версии. Один заказ создаёт примерно 2–3 вызова функции:
1. Email Trigger → функция получает заказ, пишет в YDB, шлёт в Telegram, кладёт в YMQ2. Менеджер нажимает кнопку → webhook → функция обновляет YDB и Telegram3. YMQ Trigger → функция проверяет статус (и молчит, если уже принят)
|
Заказов в день |
В месяц |
Вызовов функции в месяц |
Укладываемся в бесплатный лимит? |
|---|---|---|---|
|
10 |
~300 |
~600–900 |
✅ с запасом |
|
100 |
~3 000 |
~6 000–9 000 |
✅ всё ещё с запасом |
|
500 |
~15 000 |
~30 000–45 000 |
✅ |
|
1 000 |
~30 000 |
~60 000–90 000 |
✅ |
Для магазина с тысячей заказов в день нагрузка — это примерно 9% от бесплатного лимита вызовов Cloud Functions. YDB и YMQ тоже остаются в пределах бесплатной квоты.
Расчёт приблизительный. Точную стоимость лучше проверять в калькуляторе Yandex Cloud — тарифы, регион и объём логов влияют на итоговую сумму.
Пошаговый гайд по развёртыванию
Шаг 0. Создаём Telegram-бота и чат
Создаём бота:
Открываем @BotFather в Telegram, отправляем /newbot, задаём имя и username (должен заканчиваться на bot). BotFather выдаст токен — сохраняем:
TELEGRAM_BOT_TOKEN=1234567890:AAHxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Создаём чат и добавляем бота:
Создаём отдельную группу или канал для уведомлений о заказах. Добавляем бота как участника (в группу) или администратора (в канал). Для Pro-версии бот должен уметь редактировать сообщения.
Получаем chat_id:
Проще всего через @UserInfoBot — запускаем, выбираем нужный чат, копируем ID. Сохраняем:
TELEGRAM_CHAT_ID=-1001234567890
Проверяем, что всё работает:
https://api.telegram.org/bot<TOKEN>/sendMessage?chat\_id=<CHAT\_ID>&text=Проверка
Шаг 1. Подготавливаем Yandex Cloud
Заходим на console.yandex.cloud, создаём аккаунт и привязываем платёжный аккаунт (нужен для активации сервисов, даже если будем укладываться в бесплатный лимит).
Создаём сервисный аккаунт:
IAM → Сервисные аккаунты → Создать
Имя: order-alerts-functions-sa
Для Lite достаточно роли serverless.functions.invoker. Для Pro добавляем ещё:
ydb.editorymq.writerymq.readerserverless.functions.invoker
Для Pro — создаём статический ключ доступа:
Сервисный аккаунт → Создать новый ключ → Статический ключ доступа
⚠️
Secret access keyпоказывается только один раз. Сохраните сразу.
AWS_ACCESS_KEY_ID=AWS_SECRET_ACCESS_KEY=
Шаг 2. Создаём YDB и YMQ (только для Pro)
YDB:
YDB → Создать базу данных → Serverless
Из строки подключения формата grpcs://.../?database=/ru-central1/xxxx/yyyy выделяем два значения:
YDB_ENDPOINT=grpcs://ydb.serverless.yandexcloud.net:2135YDB_DATABASE=/ru-central1/xxxx/yyyy
Создаём таблицу в Query editor:
CREATE TABLE `insales_order_alerts` ( request_id Utf8 NOT NULL, status Utf8, order_number Utf8, phone Utf8, name Utf8, customer_email Utf8, products_text Utf8, total_price Utf8, comment Utf8, delivery_text Utf8, payment_text Utf8, payment_status Utf8, order_url Utf8, message_id Utf8, created_at Utf8, accepted_by Utf8, accepted_at Utf8, raw_subject Utf8, raw_email_text Utf8, PRIMARY KEY (request_id));
YMQ:
Message Queue → Создать очередь → Standard
Название: insales-order-reminders. Задержку доставки оставляем 0 задержка будет задаваться в коде (DelaySeconds: 600). После создания копируем URL очереди:
YMQ_QUEUE_URL=https://message-queue.api.cloud.yandex.net/xxxx/yyyy/insales-order-reminders
Шаг 3. Создаём Cloud Function
Cloud Functions → Создать функцию
Имя: order-mail-to-telegram. Runtime: Node.js. Точка входа: index.handler. Сервисный аккаунт: order-alerts-functions-sa.
Загружаем код:
Берём lite/index.js или pro/index.js из репозитория. Добавляем package.json:
Для Lite:
{ "dependencies": { "html-to-text": "^9.0.5" }}
Для Pro:
{ "dependencies": { "ydb-sdk": "^5.11.1", "@yandex-cloud/nodejs-sdk": "latest", "@aws-sdk/client-sqs": "^3.600.0", "html-to-text": "^9.0.5" }}
Переменные окружения для Pro:
TELEGRAM_BOT_TOKEN=TELEGRAM_CHAT_ID=YDB_ENDPOINT=grpcs://ydb.serverless.yandexcloud.net:2135YDB_DATABASE=ORDERS_TABLE=insales_order_alertsYMQ_QUEUE_URL=AWS_ACCESS_KEY_ID=AWS_SECRET_ACCESS_KEY=AWS_REGION=ru-central1REMINDER_DELAY_SECONDS=600
После деплоя у функции появится URL — сохраняем его, он понадобится для webhook.
Для Pro делаем функцию публичной (Telegram будет стучаться в неё при нажатии кнопки).
Шаг 4. Подключаем Email Trigger
Cloud Functions → Триггеры → Создать триггер → Почта
Привязываем к нашей функции, выбираем сервисный аккаунт, размер группы = 1, количество попыток = 1 на старте.
Если при сохранении триггера появляется ошибка прав — временно выдайте сервисному аккаунту роль
editor, создайте триггер, затем отзовите обратно.
После создания триггер выдаст технический email-адрес:
xxxxxxxxxxxxxxxxxxxx@serverless.yandexcloud.net
Добавляем его в InSales:
Настройки → Карточка магазина → Email для уведомлений
Шаг 5. Настраиваем Telegram Webhook (только для Pro)
Устанавливаем webhook. Делается одним GET-запросом в браузере:
https://api.telegram.org/bot<TOKEN>/setWebhook?url=<FUNCTION\_URL>&allowed\_updates=%5B%22message%22%2C%22callback\_query%22%5D
Проверяем:
https://api.telegram.org/bot<TOKEN>/getWebhookInfo
В ответе должны быть:
-
url— URL нашей Cloud Function -
allowed_updates— содержитcallback_query
Без
callback_queryкнопка «Принять заказ» работать не будет.
Шаг 6. Создаём YMQ Trigger (только для Pro)
Cloud Functions → Триггеры → Создать триггер → Message Queue
Выбираем очередь insales-order-reminders, привязываем к той же функции. Размер группы = 1.
На этом настройка завершена. Создаём тестовый заказ и через 5–10 секунд в Telegram придёт уведомление.
Как это работает под капотом
Самое интересное — как один handler разбирается с тремя совершенно разными типами входящих событий.
module.exports.handler = async function (event) { try { console.log('Incoming event keys:', Object.keys(event || {})); // 1. Telegram webhook: менеджер нажал кнопку «Принять заказ» const callback = getTelegramCallback(event); if (callback) { console.log('Route: telegram callback'); return await handleTelegramCallback(callback); } // 2. YMQ Trigger: пришло отложенное напоминание из очереди const requestIds = extractRequestIdsFromQueueEvent(event); if (requestIds.length > 0) { console.log('Route: reminder queue', requestIds); return await handleReminderEvent(requestIds); } // 3. Email Trigger: новый заказ из InSales if (event.httpMethod && event.httpMethod !== 'POST') { return jsonResponse(405, { ok: false, error: 'Method not allowed' }); } console.log('Route: email order'); return await handleEmailOrder(event); } catch (error) { console.error('insales-order-handler failed:', error); return jsonResponse(500, { ok: false, error: 'Internal server error', message: error.message }); }};
Логика роутинга проста:
-
Если в
eventестьcallback_query— это Telegram webhook. Достаёмrequest_idизcallback_data, находим заказ в YDB, меняем статус наaccepted, редактируем кнопку и уведомляем чат. -
Если в
event.messages[]есть JSON сrequest_id— это сообщение из YMQ. Смотрим статус заказа в YDB: еслиpending— шлём напоминание, еслиaccepted— молчим. -
Всё остальное Email Trigger с письмом о заказе. Парсим, пишем в YDB, шлём в Telegram, кладём
request_idв YMQ.
Парсер письма
Это самая хрупкая часть. Письма от разных магазинов приходят в разном формате, поэтому парсер построен на массиве регулярных выражений с приоритетом — matchFirst берёт первое совпадение:
const orderNumber = matchFirst(sourceText, [ /Поступил заказ\s*№\s*([^\s\n]+)/i, /заказ\s*№\s*([^\s\n!]+)/i, /Благодарим Вас за заказ\s*№\s*([^\s\n!]+)/i, /Новый заказ\s*№\s*([^\s\n]+)/i,]);
Аналогично работает извлечение телефона, email, состава заказа, доставки и ссылки на админку. HTML из письма преобразуется в текст через html-to-text, после чего regex-ами вырезаются нужные блоки.
Ссылка на заказ в админке вытаскивается отдельно InSales часто оборачивает её в tracking URL. Функция extractRealUrlFromInsalesTracker декодирует base64url-параметр url, чтобы получить реальный адрес:
function extractRealUrlFromInsalesTracker(url) { const parsed = new URL(rawUrl); const encodedTarget = parsed.searchParams.get('url'); const decodedTarget = decodeBase64Url(encodedTarget); return decodedTarget || rawUrl;}
Как выглядит уведомление
Обычное уведомление о заказе:
🛒 Новый заказ!Заказ: №6004Клиент: ИванТелефон: 8(999)123-45-67E-mail: client@example.comСостав заказа:Массажный пистолет Booster M2Комплектация: Набор для домаСумма: 9 990 ₽Оплата: Оплата при полученииОткрыть заказ в админке [кнопка][✅ Принять заказ]
Напоминание через 10 минут (если заказ не взяли):
🚨 Заказ не принят 10 минутЗаказ: №6004Клиент: ИванТелефон: 8(999)123-45-67Открыть заказ в админке
Адаптация под другие системы
К InSales привязан только парсер письма, и то его легко переписать. Сама инфраструктура (Email Trigger → Cloud Function → YDB/YMQ → Telegram) работает с любой системой, которая умеет слать email-копию о заказе.
Единственное условие: в настройках вашей платформы должна быть возможность добавить дополнительный email-адрес для уведомлений о заказах. В большинстве CMS и CRM это есть.
Очевидно совместимо:
-
RetailCRM — есть настройка уведомлений на email
-
МойСклад — есть триггеры по событиям с email-уведомлением
-
Любая самописная CRM — если умеет слать письма
-
Другие CMS — Битрикс, OpenCart, WooCommerce
Для адаптации под другой формат письма достаточно поправить регулярки в parseOrderEmail, extractProductsText и extractDeliveryText. Подробный разбор каждой функции — в docs/code-overview.md в репозитории.
Итог
Система работает, менеджеры не пропускают заказы. Весь функционал обходится абсолютно бесплатно. В будущем можно расширяться — добавить полезные кнопки, разнообразить статусы заказа.
Что получилось:
-
Serverless — нет постоянного сервера, платить не за что
-
Работает внутри РФ — никаких зависимостей от зарубежных сервисов, максимальная скорость
-
Event‑Driven — одна функция обрабатывает email, webhook и очередь
-
Open source — можно форкнуть и адаптировать под свой стек
Сервис для отправки заказов из email-уведомлений интернет-магазина в Telegram через Yandex Cloud. Есть Lite-версия для простых уведомлений и Pro-версия с кнопкой принятия, статусом заказа и напоминанием, если заказ не принят в течение некоторого времени. Функционал бесплатный или совсем дешёвый при огромных объёмах, не боится блокировок.
Код в репозитории DmitriiDmallSick/order-mail-to-telegram: полная документация с пошаговыми скриншотами, два варианта кода (Lite и Pro), примеры .env файлов и разбор каждой функции в docs/code-overview.md.
ссылка на оригинал статьи https://habr.com/ru/articles/1040472/