Интеграция Outlook и n8n: triage писем, задачи и draft-ответы без дублей ¶
Обновлено: 2026-05-30
Импортируйте JSON в n8n, замените credentials, IDs, правила доступа и production-политики под вашу инфраструктуру.
Проблема: корпоративная почта в Outlook быстро превращается в очередь без владельца: важные письма теряются, вложения копируются вручную, а повторный запуск workflow создаёт дубли задач.
Решение: интеграция Outlook и n8n должна читать письма по контролируемому триггеру, нормализовать thread/message identifiers, ставить категорию, создавать задачу или draft-ответ и сохранять audit trail. Такой подход закрывает не демонстрационный happy path, а реальную production-боль: повторы, права доступа, пустые поля, API-ошибки и ручной контроль там, где автоматизация может навредить.
Проблема: почему простая связка ломает процесс ¶
Интеграция нужна не ради факта подключения сервиса к n8n. Пользователь ищет конкретный ответ: как настроить сценарий так, чтобы данные не дублировались, права не были избыточными, а результат можно было проверить без ручного расследования execution logs.
Для этой страницы основной объект — Outlook message. Входной контракт должен явно фиксировать message_id, internetMessageId, conversationId, sender, subject, attachments. Если эти поля приходят нестабильно, автоматизация начинает угадывать, а угадывание в production почти всегда превращается в дубли, потерю данных или лишние уведомления.
Поэтому workflow строится вокруг детерминированных проверок: сначала validation и idempotency, потом запрос к API, потом запись результата и только после этого уведомление человека или downstream-системы.
Архитектура workflow для n8n ¶
| Блок | Задача | Production-проверка |
|---|---|---|
| Outlook Trigger | получает новое письмо или событие папки | mailbox/folder ограничены allowlist |
| Normalize message | готовит identifiers, sender, subject, preview | есть internetMessageId/messageId |
| Dedupe storage | не создаёт задачу дважды | unique key по message id |
| Classify and route | выбирает category, owner и SLA | AI не принимает write-решение без guard |
| Create task or draft | создаёт задачу, draft или комментарий в CRM | draft-first для внешних ответов |
| Audit + archive | ставит category/folder и пишет лог | можно восстановить цепочку действий |
Такой workflow удобно сопровождать: каждая нода отвечает за один слой ответственности, а не смешивает mapping, API-запрос, retry и уведомления в одном Code Node.
Контракт входных данных ¶
{
"mailbox": "support@example.com",
"message_id": "AAMkAG...",
"internet_message_id": "<ticket-1942@example.com>",
"conversation_id": "AAQkAD...",
"from": "client@example.com",
"subject": "Нужна помощь с оплатой",
"body_preview": "Оплата прошла, но доступ не появился",
"has_attachments": true,
"received_at": "2026-05-30T09:15:00Z"
}Payload можно расширять, но нельзя делать обязательные поля “по настроению”. Если источник не передал внешний ID, timezone, владельца или другой ключевой атрибут, workflow должен остановиться с понятной ошибкой до записи во внешний сервис.
Code Node: нормализация, mapping и guard-условия ¶
const msg = $json.body ?? $json;
const internetId = String(msg.internet_message_id ?? msg.internetMessageId ?? '').trim();
const messageId = String(msg.message_id ?? msg.id ?? '').trim();
const conversationId = String(msg.conversation_id ?? msg.conversationId ?? '').trim();
if (!internetId && !messageId) throw new Error('No stable Outlook message identifier');
const sender = String(msg.from ?? msg.sender?.emailAddress?.address ?? '').toLowerCase();
const subject = String(msg.subject ?? '').trim();
const dedupeKey = `outlook:${internetId || messageId}`;
const isAuto = /no-?reply|mailer-daemon|postmaster/.test(sender) || /auto-submitted/i.test(String(msg.headers ?? ''));
return [{
json: {
action: isAuto ? 'ignore_auto_message' : 'triage_message',
idempotency_key: dedupeKey,
message_id: messageId,
internet_message_id: internetId,
conversation_id: conversationId,
sender,
subject,
category: subject.match(/оплат|invoice|payment/i) ? 'billing' : 'support',
requires_human_approval: true,
safe_body_preview: String(msg.body_preview ?? '').slice(0, 500),
has_attachments: Boolean(msg.has_attachments)
}
}];Этот скрипт n8n не заменяет бизнес-логику внешнего сервиса. Его задача — привести данные к стабильному контракту, сформировать idempotency key и не пропустить опасный payload дальше по цепочке.
Готовый workflow JSON: скачать и импортировать ¶
В архиве страницы есть импортируемый workflow JSON и тестовый payload. После импорта замените credentials, URL, IDs, папки, владельцев, лимиты и правила доступа. Не запускайте сценарий на production-данных, пока не проверены повторы, пустые значения и ошибки API.
{
"name": "Nodbot - Outlook mail triage with dedupe and draft approval",
"nodes": [
{
"name": "Outlook Trigger",
"type": "n8n-node",
"purpose": "получает новое письмо или событие папки"
},
{
"name": "Normalize message",
"type": "n8n-node",
"purpose": "готовит identifiers, sender, subject, preview"
},
{
"name": "Dedupe storage",
"type": "n8n-node",
"purpose": "не создаёт задачу дважды"
},
{
"name": "Classify and route",
"type": "n8n-node",
"purpose": "выбирает category, owner и SLA"
},
{
"name": "Create task or draft",
"type": "n8n-node",
"purpose": "создаёт задачу, draft или комментарий в CRM"
},
{
"name": "Audit + archive",
"type": "n8n-node",
"purpose": "ставит category/folder и пишет лог"
}
],
"connections": "Outlook Trigger → Normalize message → Dedupe storage → Classify and route → Create task or draft → Audit + archive"
}Пошаговая настройка связки ¶
- Создайте отдельный mailbox или папку для автоматизации, чтобы workflow не читал всю корпоративную почту.
- Подключите Microsoft Outlook credential в n8n и проверьте scopes для чтения писем, drafts и категорий.
- Добавьте dedupe storage по internetMessageId или message id до создания задач.
- Настройте routing: billing, support, legal, sales и правила human approval.
- Для вложений сохраняйте файл в OneDrive/SharePoint или S3, а в задачу пишите ссылку и checksum.
Что проверить после импорта workflow
Откройте каждую ноду, замените credentials и IDs, включите dry-run там, где доступно, затем выполните сценарий на тестовом объекте. Для write-действий добавьте отдельный флаг approval или manual step.
Тесты перед production ¶
Минимальный smoke test:
curl -X POST "https://YOUR-N8N-DOMAIN/webhook/outlook-mail-triage-n8n" -H "Content-Type: application/json" --data @integration-outlook-n8n-mail-triage-payload.json- одно письмо обработано повторно
- письмо от noreply
- ответ в существующем thread
- письмо с большим вложением
- OAuth token expired или permission denied
Отдельно проверьте, что retry n8n не создаёт второй объект во внешнем сервисе. Для критичных действий используйте durable storage: Postgres, CRM custom field, Google Sheet mapping или другой слой с уникальным ключом.
Production-риски ¶
- Workflow читает весь mailbox вместо отдельной папки.
- Дубль определяется по subject, а не по message identifier.
- AI автоматически отправляет внешний ответ без approval.
- Вложения уходят во внешний LLM без redaction.
- Shared mailbox требует отдельной модели прав tenant.
Полезные ссылки и смежные материалы ¶
Внутренняя перелинковка помогает быстро перейти от общего integration-гайда к готовым workflow, а внешние ссылки ведут на официальную документацию API и n8n-нод.
Критерии готовности ¶
- Повторное письмо не создаёт вторую задачу.
- Есть allowlist mailbox/folder/actions.
- Draft-ответы требуют human approval.
- Вложения имеют storage policy и не теряются.
- Ошибки Microsoft Graph, OAuth и rate limit уходят в alert.