{
  "id": "XvgV8qqLUG9Vayj2",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Professional Email Automation Framework",
  "tags": [],
  "nodes": [
    {
      "id": "f702a564-b299-4bc4-b5c4-19a38a127cfa",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        0,
        0
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 30
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "5ba2106f-fa48-4a8f-9243-f5ab93d6fe5a",
      "name": "Limit - Max emails per run",
      "type": "n8n-nodes-base.limit",
      "position": [
        624,
        -96
      ],
      "parameters": {
        "maxItems": 5
      },
      "typeVersion": 1
    },
    {
      "id": "48e377b6-bbf4-4a6d-b873-bee34c7619fd",
      "name": "Gmail - Get message details",
      "type": "n8n-nodes-base.gmail",
      "position": [
        832,
        -96
      ],
      "parameters": {
        "messageId": "={{ $json.id }}",
        "operation": "get"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "d180af7a-0a91-4d3d-b7b9-740cea82a9eb",
      "name": "Search unreplied emails",
      "type": "n8n-nodes-base.gmail",
      "position": [
        208,
        0
      ],
      "parameters": {
        "limit": 10,
        "filters": {
          "q": "=in:inbox is:unread"
        },
        "operation": "getAll"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "f071cd47-4c2e-4e73-86fd-db6d1d9e0a52",
      "name": "Check if new emails exist",
      "type": "n8n-nodes-base.if",
      "position": [
        416,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "fee64c80-a6e5-42cb-aaec-5a1a73f01018",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{$items().length}}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "856ba060-691f-4779-9c16-5d5acf13d6d5",
      "name": "Extract email body for AI",
      "type": "n8n-nodes-base.code",
      "position": [
        1040,
        -96
      ],
      "parameters": {
        "jsCode": "// Safely extract the email body text from the Gmail payload\n\nfunction decodeBase64(str) {\n  return Buffer.from(str, 'base64').toString('utf-8');\n}\n\nconst payload = $json.payload;\n\nlet body = '';\n\n// Case 1: Simple text/plain email body\nif (payload.body && payload.body.data) {\n  body = decodeBase64(payload.body.data);\n}\n\n// Case 2: Multipart email (e.g. text/plain + text/html)\nif (!body && payload.parts) {\n  for (const part of payload.parts) {\n    if (part.mimeType === 'text/plain' && part.body?.data) {\n      body = decodeBase64(part.body.data);\n      break;\n    }\n  }\n}\n\n// Fallback to snippet if full body is not available\nif (!body) {\n  body = $json.snippet || '';\n}\n\nreturn {\n  emailText: body.trim(),\n  subject: $json.snippet,\n  threadId: $json.threadId,\n  receivedAt: new Date(Number($json.internalDate)).toISOString()\n};\n"
      },
      "typeVersion": 2
    },
    {
      "id": "23239b95-5337-4285-bd74-4e9d132ce29b",
      "name": "AI - Draft professional email reply",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        1248,
        -96
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini",
          "cachedResultName": "GPT-4.1-MINI"
        },
        "options": {},
        "responses": {
          "values": [
            {
              "role": "system",
              "content": "You are a professional assistant who writes polite Japanese business emails.\nIf there are any points where the facts are unclear, do not make assumptions and instead confirm them by asking questions."
            },
            {
              "content": "=Please draft a polite and short reply to the email you received below.\n\nConditions: \n- Greetings at the beginning\n- Thanking the recipient\n- Answering the purpose of the email (don't guess, ask questions to confirm anything unclear)\n- Proposing next actions (potential dates/necessary information, etc.)\n- Closing greetings\n- Do not include a signature \n Body of the received email:\n{{ $json.emailText }}\n"
            }
          ]
        },
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "59cdfe8b-7527-428a-bcf1-7dfd345e55ae",
      "name": "Notify draft reply in Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        1600,
        -96
      ],
      "parameters": {
        "text": "=\ud83d\udce9 There is an email that needs to be replied to\n\n[AI reply draft]\n{{ $node[\"AI - Draft professional email reply\"].json.output[0].content[0].text }}\n\n\u2015\u2015\u2015\u2015\u2015\u2015\u2015\u2015\u2015\u2015\n(This message is automatically generated.)\n",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0A3FM8HDU3",
          "cachedResultName": "all-kota"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    },
    {
      "id": "4c787cfc-8bc0-4f5c-815e-d8432be82017",
      "name": "Mark email as AUTO_REPLIED",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1040,
        128
      ],
      "parameters": {
        "labelIds": [
          "Label_5043339914715829876"
        ],
        "messageId": "={{ $json.id }}",
        "operation": "addLabels"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "9f39256e-b781-4109-a2dc-b897607dd9e7",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "disabled": true,
      "position": [
        992,
        -224
      ],
      "parameters": {
        "color": 7,
        "width": 544,
        "height": 304,
        "content": "## AI Draft Generation\nCreates a professional email reply draft using AI.\nHuman review required."
      },
      "typeVersion": 1
    },
    {
      "id": "f2204ee0-b63b-44ec-86d2-bb8224319766",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        992,
        112
      ],
      "parameters": {
        "color": 7,
        "width": 368,
        "height": 320,
        "content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## \ud83d\udcec Notification & State Control\n \n\u2022 Sends AI-generated draft to Slack\n\u2022 Marks email as AUTO_REPLIED\n\u2022 Prevents duplicate processing\n"
      },
      "typeVersion": 1
    },
    {
      "id": "95899fba-a7c8-4cfb-8829-b78bff651dba",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1584,
        -224
      ],
      "parameters": {
        "color": 7,
        "width": 368,
        "height": 304,
        "content": "## \ud83d\udcec Notification & State Control\n \n\u2022 Sends AI-generated draft to Slack\n\u2022 Marks email as AUTO_REPLIED\n\u2022 Prevents duplicate processing\n"
      },
      "typeVersion": 1
    },
    {
      "id": "5ab4f131-9d33-49f3-b3db-bb8fbb97a3b7",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -48,
        -752
      ],
      "parameters": {
        "width": 640,
        "height": 592,
        "content": "## I'm a note \n\nThis is a professional email automation framework\nThis workflow monitors your Gmail inbox on a schedule and looks for new, unreplied emails.\n\nWhen a new email is found, it:\n- Retrieves the full email content\n- Extracts the plain text body safely\n- Generates a professional reply draft using AI\n- Sends the draft to Slack for human review\n- Labels the email to prevent duplicate processing\n\nThe workflow does NOT send emails automatically.\nIt only creates draft replies for review.\n\n## Setup steps\n\n1. Connect your Gmail account\n2. Create a Gmail label called AUTO_REPLIED\n3. Connect your OpenAI (or compatible) API credentials\n4. Connect your Slack workspace and choose a channel\n5. Adjust the schedule trigger if needed\n\nOnce set up, the workflow will run automatically."
      },
      "typeVersion": 1
    },
    {
      "id": "cce1a803-016e-4a5c-bc29-eaedf4895ab3",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -48,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 304,
        "content": "## Email Monitoring\nChecks Gmail for new unreplied emails on a schedule."
      },
      "typeVersion": 1
    },
    {
      "id": "5f7db3e2-083e-4380-b87d-7828e94bd59e",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        672,
        -560
      ],
      "parameters": {
        "width": 256,
        "height": 208,
        "content": "## How to customize this framework\nOptional nodes are intentionally left unconnected.\nUsers can plug them into the flow depending on their use case.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "d0d365a8-73dd-4ce0-bd89-f46fdf49cd40",
      "name": "OPTIONAL \u2013 Auto-send reply",
      "type": "n8n-nodes-base.if",
      "position": [
        1488,
        192
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "0f2f78fe-2e4c-4ab9-b719-d551ed4b65cd",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "8604479b-d27c-43bf-b468-c458584dc81a",
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Search unreplied emails",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search unreplied emails": {
      "main": [
        [
          {
            "node": "Check if new emails exist",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if new emails exist": {
      "main": [
        [
          {
            "node": "Limit - Max emails per run",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract email body for AI": {
      "main": [
        [
          {
            "node": "AI - Draft professional email reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Limit - Max emails per run": {
      "main": [
        [
          {
            "node": "Gmail - Get message details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail - Get message details": {
      "main": [
        [
          {
            "node": "Extract email body for AI",
            "type": "main",
            "index": 0
          },
          {
            "node": "Mark email as AUTO_REPLIED",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify draft reply in Slack": {
      "main": [
        []
      ]
    },
    "AI - Draft professional email reply": {
      "main": [
        [
          {
            "node": "Notify draft reply in Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}