{
  "name": "Enterprise: Outlook & Slack Email Inbox Manager",
  "nodes": [
    {
      "parameters": {
        "event": "messageReceived",
        "folderId": "Inbox",
        "options": {}
      },
      "id": "outlook-trigger",
      "name": "Outlook Trigger (New Email)",
      "type": "n8n-nodes-base.microsoftOutlookTrigger",
      "typeVersion": 1,
      "position": [
        100,
        200
      ],
      "credentials": {
        "microsoftOutlookOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "notes": "\u26a1 Trigger khi nh\u1eadn email m\u1edbi trong Inbox. C\u1ea7n credentials Microsoft Graph API OAuth2. Thay OUTLOOK_CREDENTIAL_ID b\u1eb1ng ID credential th\u1ef1c trong n8n."
    },
    {
      "parameters": {
        "values": {
          "string": [
            {
              "name": "slackChannelId",
              "value": "YOUR_SLACK_CHANNEL_ID"
            }
          ]
        },
        "options": {}
      },
      "id": "config-vars",
      "name": "Config Vars",
      "type": "n8n-nodes-base.set",
      "typeVersion": 2,
      "position": [
        250,
        200
      ],
      "notes": "C\u1ea5u h\u00ecnh c\u00e1c bi\u1ebfn m\u00f4i tr\u01b0\u1eddng cho workflow (VD: Slack Channel ID)"
    },
    {
      "parameters": {
        "jsCode": "// Ph\u00e2n lo\u1ea1i email d\u1ef1a tr\u00ean VIP senders, keywords kh\u1ea9n c\u1ea5p v\u00e0 lo\u1ea1i tr\u1eeb qu\u1ea3ng c\u00e1o/newsletter\nconst email = $input.first().json;\n\n// Ch\u1ec9 x\u1eed l\u00fd email ch\u01b0a \u0111\u1ecdc\n// FIX: Th\u00eam console.log \u0111\u1ec3 d\u1ec5 debug khi email b\u1ecb b\u1ecf qua\nconst isRead = email.isRead === true;\nif (isRead) {\n  console.log(`[SKIP] Email \u0111\u00e3 \u0111\u1ecdc: id=${email.id} | subject=\"${email.subject}\" \u2014 b\u1ecf qua, kh\u00f4ng x\u1eed l\u00fd.`);\n  return [];\n}\n\nconst subject = (email.subject || '').toLowerCase();\nconst fromAddress = (email.from?.emailAddress?.address || '').toLowerCase();\nconst fromName = email.from?.emailAddress?.name || '';\nconst bodyPreview = email.bodyPreview || '';\nconst bodyContent = (email.body?.content || '').toLowerCase();\nconst fullText = `${subject} ${fromAddress} ${bodyContent}`;\n\n// Danh s\u00e1ch ng\u01b0\u1eddi g\u1eedi VIP c\u1ea7n ch\u00fa \u00fd ngay l\u1eadp t\u1ee9c\nconst vipSenders = [\n  'boss@company.com',\n  'director@company.com',\n  'important-client@corp.com',\n  'partner@company.com'\n];\n\n// T\u1eeb kh\u00f3a kh\u1ea9n c\u1ea5p c\u1ea7n h\u00e0nh \u0111\u1ed9ng ngay\nconst urgentKeywords = [\n  'urgent', 'kh\u1ea9n', 'g\u1ea5p', 'important', 'quan tr\u1ecdng', 'deadline', 'h\u1ea1n ch\u00f3t',\n  'payment', 'thanh to\u00e1n', 'overdue', 'qu\u00e1 h\u1ea1n', 'c\u1ea3nh b\u00e1o', 'warning', 'incident', 's\u1ef1 c\u1ed1'\n];\n\n// T\u1eeb kh\u00f3a b\u1ea3n tin ho\u1eb7c email t\u1ef1 \u0111\u1ed9ng kh\u00f4ng quan tr\u1ecdng\nconst newsletterKeywords = [\n  'unsubscribe', 'newsletter', 'digest', 'b\u1ea3n tin', 'h\u1ee7y \u0111\u0103ng k\u00fd',\n  'no-reply', 'noreply', 'do-not-reply', 'mailing list'\n];\n\n// T\u1eeb kh\u00f3a khuy\u1ebfn m\u00e3i ho\u1eb7c qu\u1ea3ng c\u00e1o\nconst promoKeywords = [\n  'sale', 'discount', 'gi\u1ea3m gi\u00e1', 'khuy\u1ebfn m\u00e3i', 'flash sale', '\u01b0u \u0111\u00e3i',\n  'coupon', 'voucher', '\u0111\u1eb7c bi\u1ec7t', 'qu\u00e0 t\u1eb7ng', 'offer', 'black friday'\n];\n\nconst isVip = vipSenders.some(sender => fromAddress.includes(sender));\nconst hasUrgent = urgentKeywords.some(kw => fullText.includes(kw));\nconst hasNewsletter = newsletterKeywords.some(kw => fullText.includes(kw));\nconst hasPromo = promoKeywords.some(kw => fullText.includes(kw));\n\nlet category = 'normal';\nlet action = 'notify_quiet';\nlet priority = 'medium';\n\nif (isVip || hasUrgent || email.importance === 'high') {\n  category = 'important';\n  action = 'notify_interactive';\n  priority = 'high';\n} else if (hasNewsletter || hasPromo) {\n  category = 'newsletter_promo';\n  action = 'auto_archive';\n  priority = 'low';\n} else {\n  category = 'normal';\n  action = 'notify_quiet';\n  priority = 'medium';\n}\n\nreturn [{\n  json: {\n    id: email.id,\n    subject: email.subject,\n    from: email.from,\n    bodyPreview: bodyPreview,\n    receivedDateTime: email.receivedDateTime,\n    importance: email.importance,\n    category: category,\n    action: action,\n    priority: priority,\n    classified_at: new Date().toISOString()\n  }\n}];"
      },
      "id": "classify-email",
      "name": "Classify Email",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        400,
        200
      ],
      "notes": "Ph\u00e2n lo\u1ea1i email th\u00e0nh: important (c\u1ea7n t\u01b0\u01a1ng t\u00e1c), newsletter_promo (t\u1ef1 \u0111\u1ed9ng l\u01b0u tr\u1eef), v\u00e0 normal (th\u00f4ng b\u00e1o th\u01b0\u1eddng). FIX: Email \u0111\u00e3 \u0111\u1ecdc \u2192 return [] d\u1eebng execution kh\u00f4ng l\u1ed7i, c\u00f3 ghi console.log \u0111\u1ec3 debug."
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": false,
                  "leftValue": "",
                  "typeValidation": "loose"
                },
                "conditions": [
                  {
                    "id": "notify-interactive-check",
                    "leftValue": "={{ $json.action }}",
                    "rightValue": "notify_interactive",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "notify_interactive"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": false,
                  "leftValue": "",
                  "typeValidation": "loose"
                },
                "conditions": [
                  {
                    "id": "auto-archive-check",
                    "leftValue": "={{ $json.action }}",
                    "rightValue": "auto_archive",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "auto_archive"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": false,
                  "leftValue": "",
                  "typeValidation": "loose"
                },
                "conditions": [
                  {
                    "id": "notify-quiet-check",
                    "leftValue": "={{ $json.action }}",
                    "rightValue": "notify_quiet",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "notify_quiet"
            }
          ]
        },
        "options": {}
      },
      "id": "switch-action",
      "name": "Switch Action",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [
        500,
        200
      ]
    },
    {
      "parameters": {
        "jsCode": "// Build Slack Block Kit payload \u0111\u1ec3 g\u1eedi interactive message\nconst d = $input.first().json;\nconst slackChannelId = $('Config Vars').first().json.slackChannelId;\n\nconst fromName = d.from?.emailAddress?.name || 'Kh\u00f4ng r\u00f5';\nconst fromAddr = d.from?.emailAddress?.address || '';\nconst subject  = d.subject || '(Kh\u00f4ng c\u00f3 ti\u00eau \u0111\u1ec1)';\nconst preview  = d.bodyPreview || 'Kh\u00f4ng c\u00f3 n\u1ed9i dung xem tr\u01b0\u1edbc.';\nconst priority = d.priority || 'medium';\nconst emailId  = d.id || '';\nconst receivedAt = d.receivedDateTime\n  ? new Date(d.receivedDateTime).toLocaleString('vi-VN', { timeZone: 'Asia/Ho_Chi_Minh' })\n  : 'Kh\u00f4ng r\u00f5';\n\nconst blocks = [\n  {\n    type: 'header',\n    text: { type: 'plain_text', text: '\ud83d\udce7 Outlook Inbox Manager', emoji: true }\n  },\n  {\n    type: 'section',\n    text: {\n      type: 'mrkdwn',\n      text: `*Email quan tr\u1ecdng m\u1edbi!* \ud83d\udd34\n\n*Ng\u01b0\u1eddi g\u1eedi:* ${fromName} <${fromAddr}>\n*Ch\u1ee7 \u0111\u1ec1:* ${subject}\n*Th\u1eddi gian:* ${receivedAt}\n\n*Xem tr\u01b0\u1edbc:*\n> ${preview.substring(0, 200)}`\n    }\n  },\n  {\n    type: 'actions',\n    elements: [\n      {\n        type: 'button',\n        text: { type: 'plain_text', text: 'L\u01b0u tr\u1eef \ud83d\udce6', emoji: true },\n        style: 'primary',\n        value: emailId,\n        action_id: 'archive'\n      },\n      {\n        type: 'button',\n        text: { type: 'plain_text', text: '\u0110\u00e1nh d\u1ea5u \u0111\u00e3 \u0111\u1ecdc \u2705', emoji: true },\n        value: emailId,\n        action_id: 'mark_read'\n      },\n      {\n        type: 'button',\n        text: { type: 'plain_text', text: 'G\u1eafn c\u1edd \u2b50\ufe0f', emoji: true },\n        value: emailId,\n        action_id: 'flag'\n      }\n    ]\n  }\n];\n\nreturn [{\n  json: {\n    channel: slackChannelId,\n    text: `\ud83d\udce7 Email quan tr\u1ecdng t\u1eeb ${fromName}: ${subject}`,\n    blocks: blocks,\n    // Pass through email data\n    _emailId: emailId,\n    _subject: subject\n  }\n}];"
      },
      "id": "code-build-slack-blocks",
      "name": "Code: Build Slack Blocks",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        720,
        100
      ],
      "notes": "Build Block Kit JSON ph\u00eda JavaScript \u0111\u1ec3 \u0111\u1ea3m b\u1ea3o blocks \u0111\u01b0\u1ee3c serialize \u0111\u00fang."
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://slack.com/api/chat.postMessage",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "contentType": "json",
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ channel: $json.channel, text: $json.text, blocks: $json.blocks }) }}",
        "options": {
          "timeout": 10000
        }
      },
      "id": "slack-interactive-alert",
      "name": "Slack: Interactive Alert",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.1,
      "position": [
        920,
        100
      ],
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "notes": "G\u1ecdi tr\u1ef1c ti\u1ebfp Slack chat.postMessage API v\u1edbi blocks JSON. Credential: HTTP Header Auth v\u1edbi Name='Authorization', Value='Bearer xoxb-YOUR-BOT-TOKEN'."
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "move",
        "messageId": "={{ $json.id }}",
        "destinationId": "archive"
      },
      "id": "outlook-auto-archive",
      "name": "Outlook: Auto Archive",
      "type": "n8n-nodes-base.microsoftOutlook",
      "typeVersion": 2,
      "position": [
        720,
        240
      ],
      "credentials": {
        "microsoftOutlookOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "notes": "T\u1ef1 \u0111\u1ed9ng di chuy\u1ec3n email qu\u1ea3ng c\u00e1o/newsletter v\u00e0o th\u01b0 m\u1ee5c Archive. FIX: D\u00f9ng destinationId='archive' (wellKnownFolderName h\u1ee3p l\u1ec7 theo Microsoft Graph API)."
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "update",
        "messageId": "={{ $json.id }}",
        "updateFields": {
          "isRead": true
        }
      },
      "id": "outlook-mark-read-auto",
      "name": "Outlook: Mark Read (Auto)",
      "type": "n8n-nodes-base.microsoftOutlook",
      "typeVersion": 2,
      "position": [
        920,
        240
      ],
      "credentials": {
        "microsoftOutlookOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "notes": "\u0110\u00e1nh d\u1ea5u email qu\u1ea3ng c\u00e1o/newsletter \u0111\u00e3 l\u01b0u tr\u1eef l\u00e0 \u0111\u00e3 \u0111\u1ecdc."
    },
    {
      "parameters": {
        "select": "channel",
        "channelId": "={{ $('Config Vars').first().json.slackChannelId }}",
        "sendAsText": true,
        "text": "=\ud83d\udce7 *Email th\u00f4ng th\u01b0\u1eddng:* \"{{ $json.subject || '(Kh\u00f4ng c\u00f3 ti\u00eau \u0111\u1ec1)' }}\" t\u1eeb *{{ $json.from?.emailAddress?.name || $json.from?.emailAddress?.address || 'Kh\u00f4ng r\u00f5' }}*",
        "otherOptions": {}
      },
      "id": "slack-quiet-alert",
      "name": "Slack: Quiet Alert",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.1,
      "position": [
        720,
        380
      ],
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "notes": "FIX: Th\u00eam '=' prefix \u0111\u1ec3 n8n evaluate expression trong text. G\u1eedi th\u00f4ng b\u00e1o text ng\u1eafn g\u1ecdn, kh\u00f4ng l\u00e0m \u1ed3n k\u00eanh."
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "slack-interactive-outlook",
        "responseMode": "onReceived",
        "options": {}
      },
      "id": "slack-webhook",
      "name": "Slack Interactivity Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        100,
        600
      ],
      "notes": "L\u1eafng nghe s\u1ef1 ki\u1ec7n ng\u01b0\u1eddi d\u00f9ng nh\u1ea5n n\u00fat tr\u00ean Slack. C\u1ea7n c\u1ea5u h\u00ecnh URL n\u00e0y trong Slack App \u2192 Interactive Components \u2192 Request URL: https://<n8n-host>/webhook/slack-interactive-outlook"
    },
    {
      "parameters": {
        "jsCode": "// FIX: Parse payload an to\u00e0n v\u1edbi error handling r\u00f5 r\u00e0ng\nconst body = $input.first().json.body;\n\nif (!body) {\n  throw new Error('Kh\u00f4ng t\u00ecm th\u1ea5y body t\u1eeb Slack webhook. Ki\u1ec3m tra l\u1ea1i c\u1ea5u h\u00ecnh Slack App Interactivity.');\n}\n\nif (!body.payload) {\n  throw new Error('Kh\u00f4ng t\u00ecm th\u1ea5y payload trong body. \u0110\u1ea3m b\u1ea3o Slack g\u1eedi \u0111\u00fang \u0111\u1ecbnh d\u1ea1ng application/x-www-form-urlencoded.');\n}\n\nlet payload;\ntry {\n  payload = JSON.parse(body.payload);\n} catch (e) {\n  throw new Error(`Kh\u00f4ng th\u1ec3 parse payload JSON t\u1eeb Slack: ${e.message}`);\n}\n\nif (!payload.actions || payload.actions.length === 0) {\n  throw new Error('Payload kh\u00f4ng ch\u1ee9a actions. C\u00f3 th\u1ec3 \u0111\u00e2y kh\u00f4ng ph\u1ea3i s\u1ef1 ki\u1ec7n n\u00fat b\u1ea5m.');\n}\n\nconst action = payload.actions[0];\nconst actionId = action.action_id; // 'archive', 'mark_read', 'flag'\nconst emailId = action.value;      // ID c\u1ee7a email Outlook\nconst responseUrl = payload.response_url;\nconst userName = payload.user?.username || payload.user?.name || 'unknown';\nconst channelId = payload.channel?.id;\nconst messageTs = payload.message?.ts;\nconst originalBlocks = payload.message?.blocks || [];\n\nreturn [{\n  json: {\n    action_id: actionId,\n    email_id: emailId,\n    response_url: responseUrl,\n    user_name: userName,\n    channel_id: channelId,\n    message_ts: messageTs,\n    original_blocks: originalBlocks\n  }\n}];"
      },
      "id": "parse-slack-payload",
      "name": "Parse Slack Payload",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        300,
        600
      ],
      "notes": "FIX: Th\u00eam error handling r\u00f5 r\u00e0ng cho t\u1eebng b\u01b0\u1edbc parse. Gi\u1ea3i m\u00e3 payload url-encoded c\u1ee7a Slack v\u00e0 tr\u1ea3 v\u1ec1 action_id, email_id, response_url."
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": false,
                  "leftValue": "",
                  "typeValidation": "loose"
                },
                "conditions": [
                  {
                    "id": "archive-check",
                    "leftValue": "={{ $json.action_id }}",
                    "rightValue": "archive",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "archive"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": false,
                  "leftValue": "",
                  "typeValidation": "loose"
                },
                "conditions": [
                  {
                    "id": "mark-read-check",
                    "leftValue": "={{ $json.action_id }}",
                    "rightValue": "mark_read",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "mark_read"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": false,
                  "leftValue": "",
                  "typeValidation": "loose"
                },
                "conditions": [
                  {
                    "id": "flag-check",
                    "leftValue": "={{ $json.action_id }}",
                    "rightValue": "flag",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "flag"
            }
          ]
        },
        "options": {}
      },
      "id": "switch-action-slack",
      "name": "Switch Action Slack",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [
        500,
        600
      ]
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "move",
        "messageId": "={{ $json.email_id }}",
        "destinationId": "archive"
      },
      "id": "outlook-action-archive",
      "name": "Outlook Action: Archive",
      "type": "n8n-nodes-base.microsoftOutlook",
      "typeVersion": 2,
      "position": [
        720,
        500
      ],
      "credentials": {
        "microsoftOutlookOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "notes": "FIX: D\u00f9ng destinationId thay folderId. 'archive' l\u00e0 wellKnownFolderName h\u1ee3p l\u1ec7 theo Microsoft Graph API."
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "update",
        "messageId": "={{ $json.email_id }}",
        "updateFields": {
          "isRead": true
        }
      },
      "id": "outlook-action-mark-read",
      "name": "Outlook Action: Mark Read",
      "type": "n8n-nodes-base.microsoftOutlook",
      "typeVersion": 2,
      "position": [
        720,
        620
      ],
      "credentials": {
        "microsoftOutlookOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "update",
        "messageId": "={{ $json.email_id }}",
        "updateFields": {
          "isRead": false,
          "categories": [
            "Important"
          ]
        }
      },
      "id": "outlook-action-flag",
      "name": "Outlook Action: Flag & Category",
      "type": "n8n-nodes-base.microsoftOutlook",
      "typeVersion": 2,
      "position": [
        720,
        740
      ],
      "credentials": {
        "microsoftOutlookOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "notes": "FIX: \u0110\u1eb7t isRead=false (gi\u1eef n\u1ed5i b\u1eadt) + g\u00e1n category 'Important'. \u26a0\ufe0f Category 'Important' ph\u1ea3i \u0111\u01b0\u1ee3c t\u1ea1o tr\u01b0\u1edbc trong Outlook: Settings \u2192 Categories \u2192 New. N\u1ebfu mu\u1ed1n d\u00f9ng flag thay category, c\u1ea7n HTTP Request node g\u1ecdi Graph API PATCH /messages/{id} v\u1edbi body {\"flag\":{\"flagStatus\":\"flagged\"}}."
    },
    {
      "parameters": {
        "jsCode": "// FIX: L\u1ea5y d\u1eef li\u1ec7u t\u1eeb Parse Slack Payload th\u00f4ng qua $() - an to\u00e0n trong c\u00f9ng m\u1ed9t execution\nconst slackData = $('Parse Slack Payload').first().json;\nconst originalBlocks = slackData.original_blocks || [];\nconst actionId = slackData.action_id;\nconst userName = slackData.user_name;\n\n// X\u00f3a b\u1ecf blocks ch\u1ee9a c\u00e1c n\u00fat b\u1ea5m (actions) \u0111\u1ec3 tr\u00e1nh click l\u1eb7p\nconst updatedBlocks = originalBlocks.filter(block => block.type !== 'actions');\n\nlet actionText = '';\nif (actionId === 'archive') {\n  actionText = '\ud83d\udce6 \u0110\u00e3 l\u01b0u tr\u1eef (Archived)';\n} else if (actionId === 'mark_read') {\n  actionText = '\u2705 \u0110\u00e3 \u0111\u00e1nh d\u1ea5u \u0111\u00e3 \u0111\u1ecdc (Marked Read)';\n} else if (actionId === 'flag') {\n  actionText = '\u2b50\ufe0f \u0110\u00e3 g\u1eafn nh\u00e3n quan tr\u1ecdng (Flagged)';\n} else {\n  actionText = `\u2753 H\u00e0nh \u0111\u1ed9ng kh\u00f4ng x\u00e1c \u0111\u1ecbnh: ${actionId}`;\n}\n\nconst processedAt = new Date().toLocaleTimeString('vi-VN', {\n  timeZone: 'Asia/Ho_Chi_Minh',\n  hour: '2-digit',\n  minute: '2-digit',\n  second: '2-digit'\n});\n\n// Th\u00eam context th\u00f4ng b\u00e1o tr\u1ea1ng th\u00e1i m\u1edbi b\u00ean d\u01b0\u1edbi tin nh\u1eafn g\u1ed1c\nupdatedBlocks.push({\n  \"type\": \"context\",\n  \"elements\": [\n    {\n      \"type\": \"mrkdwn\",\n      \"text\": `\ud83d\udfe2 *Tr\u1ea1ng th\u00e1i:* ${actionText} | Ng\u01b0\u1eddi x\u1eed l\u00fd: *@${userName}* l\u00fac ${processedAt}`\n    }\n  ]\n});\n\nreturn [{\n  json: {\n    response_url: slackData.response_url,\n    payload: {\n      blocks: updatedBlocks,\n      replace_original: true\n    }\n  }\n}];"
      },
      "id": "prepare-slack-update",
      "name": "Prepare Slack Update",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        980,
        620
      ],
      "notes": "C\u1eadp nh\u1eadt block kit g\u1ed1c: x\u00f3a n\u00fat b\u1ea5m, b\u1ed5 sung badge tr\u1ea1ng th\u00e1i. D\u00f9ng $('Parse Slack Payload') \u0111\u1ec3 truy c\u1eadp d\u1eef li\u1ec7u t\u1eeb node upstream trong c\u00f9ng execution."
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $json.response_url }}",
        "sendBody": true,
        "contentType": "json",
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify($json.payload) }}",
        "options": {
          "timeout": 5000
        }
      },
      "id": "update-slack-message",
      "name": "Update Slack Message",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.1,
      "position": [
        1200,
        620
      ],
      "notes": "FIX: S\u1eeda c\u1ea5u tr\u00fac body params \u2014 specifyBody v\u00e0 jsonBody ph\u1ea3i n\u1eb1m \u1edf top-level parameters, kh\u00f4ng l\u1ed3ng trong bodyParameters. D\u00f9ng JSON.stringify($json.payload) \u0111\u1ec3 serialize \u0111\u00fang c\u00e1ch."
    }
  ],
  "connections": {
    "Outlook Trigger (New Email)": {
      "main": [
        [
          {
            "node": "Config Vars",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Config Vars": {
      "main": [
        [
          {
            "node": "Classify Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Classify Email": {
      "main": [
        [
          {
            "node": "Switch Action",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch Action": {
      "main": [
        [
          {
            "node": "Code: Build Slack Blocks",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Outlook: Auto Archive",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Slack: Quiet Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code: Build Slack Blocks": {
      "main": [
        [
          {
            "node": "Slack: Interactive Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Outlook: Auto Archive": {
      "main": [
        [
          {
            "node": "Outlook: Mark Read (Auto)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack Interactivity Webhook": {
      "main": [
        [
          {
            "node": "Parse Slack Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Slack Payload": {
      "main": [
        [
          {
            "node": "Switch Action Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch Action Slack": {
      "main": [
        [
          {
            "node": "Outlook Action: Archive",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Outlook Action: Mark Read",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Outlook Action: Flag & Category",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Outlook Action: Archive": {
      "main": [
        [
          {
            "node": "Prepare Slack Update",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Outlook Action: Mark Read": {
      "main": [
        [
          {
            "node": "Prepare Slack Update",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Outlook Action: Flag & Category": {
      "main": [
        [
          {
            "node": "Prepare Slack Update",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Slack Update": {
      "main": [
        [
          {
            "node": "Update Slack Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "saveManualExecutions": true,
    "timezone": "Asia/Ho_Chi_Minh"
  },
  "staticData": null,
  "tags": [
    "enterprise",
    "email",
    "outlook",
    "slack",
    "automation",
    "vietnamese"
  ],
  "triggerCount": 2,
  "versionId": "1.1.0",
  "meta": {
    "templateCredsSetupCompleted": false,
    "usage": "H\u1ec7 th\u1ed1ng qu\u1ea3n l\u00fd h\u1ed9p th\u01b0 Outlook chuy\u00ean nghi\u1ec7p qua Slack, cho ph\u00e9p x\u1eed l\u00fd email nhanh (L\u01b0u tr\u1eef, \u0110\u00e1nh d\u1ea5u \u0111\u1ecdc, G\u1eafn c\u1edd) ngay tr\u00ean giao di\u1ec7n Slack.",
    "version": "1.1.0",
    "changelog": "v1.1.0: Fix Block Kit expressions (= prefix), fix HTTP body params, fix folderId\u2192destinationId, fix categories+isRead, add credentials, add error handling in Parse Slack Payload, add console.log for skipped emails."
  }
}