AutomationFlowsAI & RAG › Extract Email Tasks with Gmail, Chatgpt-4o and Supabase

Extract Email Tasks with Gmail, Chatgpt-4o and Supabase

ByPaul Taylor @ptylr on n8n.io

This n8n workflow automates the extraction of actionable tasks from unread Gmail messages using OpenAI's GPT API, stores the resulting task metadata in Supabase, and avoids re-processing previously handled emails. Triggers on a schedule to check for unread emails in your Gmail…

Cron / scheduled trigger★★★★☆ complexityAI-powered9 nodesOpenAIHTTP RequestGmailSupabase
AI & RAG Trigger: Cron / scheduled Nodes: 9 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #5496 — we link there as the canonical source.

This workflow follows the Gmail → HTTP Request recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "8mU5BDEPNPCBrcNG",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Gmail \u2192 GPT \u2192 Supabase | Task Extractor",
  "tags": [],
  "nodes": [
    {
      "id": "60d16e90-4a70-4aca-9643-997141a65cdf",
      "name": "Trigger Workflow",
      "type": "n8n-nodes-base.scheduleTrigger",
      "notes": "Runs the workflow on a schedule (every X minutes) to check for new unread emails.",
      "position": [
        -580,
        -430
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes"
            }
          ]
        }
      },
      "notesInFlow": true,
      "typeVersion": 1.2
    },
    {
      "id": "501a117f-93ff-43e9-8a49-5f0c58c4e496",
      "name": "Prepare ChatGPT Prompt",
      "type": "n8n-nodes-base.code",
      "notes": "Formats the email content into a prompt for GPT, asking it to extract a structured task in JSON format.",
      "position": [
        520,
        -580
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "return {\n  prompt: `You are an AI productivity assistant. Given the email below, extract any actionable task(s). Respond in this format:\n  {\n    \"task\": \"Brief title of the task\",\n    \"description\": \"Expanded detail if needed\",\n    \"due_date\": \"2025-07-01\" or null,\n    \"estimated_minutes\": 30,\n    \"deep_work\": true\n  }\n  If no actionable task exists, respond with null.\\n\\nEmail:\\n${$('Loop Over Items').item.json.snippet}`\n};\n"
      },
      "executeOnce": false,
      "notesInFlow": true,
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "cec2c062-7333-499a-b5c3-5f7831022d34",
      "name": "Extract Task Detail from Email",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "notes": "Sends the email to ChatGPT-4o to extract task details like title, description, due date, duration, and focus level.",
      "position": [
        740,
        -580
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "chatgpt-4o-latest",
          "cachedResultName": "CHATGPT-4O-LATEST"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "={{ $json.prompt }}"
            }
          ]
        },
        "jsonOutput": true
      },
      "notesInFlow": true,
      "typeVersion": 1.8
    },
    {
      "id": "d708c9c3-d5ec-4b2a-8f8a-b5b123fa44ea",
      "name": "Insert Email Detail to Supabase",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "Inserts the processed email and GPT-extracted task into the Supabase emails table. Uses upsert to avoid duplicates.",
      "position": [
        1116,
        -505
      ],
      "parameters": {
        "url": "={{ $vars.Supabase_TaskManagement_URI + '/rest/v1/emails?on_conflict=email_id' }}",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"email_id\": {{ JSON.stringify( $('Get Unread Emails from Inbox').item.json.id) }},\n  \"subject\": {{ JSON.stringify($('Get Unread Emails from Inbox').item.json.Subject) }},\n  \"sender\": {{ JSON.stringify($('Get Unread Emails from Inbox').item.json.From) }},\n  \"received_at\": {{ JSON.stringify(new Date(Number($('Get Unread Emails from Inbox').item.json.internalDate)).toISOString()) }},\n  \"body\": {{ JSON.stringify($('Get Unread Emails from Inbox').item.json.snippet) }},\n  \"gpt_summary\": {{ JSON.stringify($json.message.content) }},\n  \"requires_deep_work\": {{ JSON.stringify($json.message.content.deep_work) }},\n  \"deleted\": false\n}",
        "sendBody": true,
        "jsonHeaders": "={\n  \"apikey\": \"{{ $vars.Supabase_TaskManagement_ANON_KEY }}\",\n  \"Authorization\": \"Bearer {{ $vars.Supabase_TaskManagement_ANON_KEY }}\",\n  \"Content-Type\": \"application/json\",\n  \"Prefer\": \"resolution=ignore-conflict\"\n}",
        "sendHeaders": true,
        "specifyBody": "json",
        "specifyHeaders": "json"
      },
      "notesInFlow": true,
      "typeVersion": 4.2,
      "alwaysOutputData": false
    },
    {
      "id": "5b774acc-8e19-4576-9970-91a060d25d87",
      "name": "Get Unread Emails from Inbox",
      "type": "n8n-nodes-base.gmail",
      "notes": "Fetches all unread emails from the inbox using Gmail API. These are the raw email inputs for analysis.",
      "position": [
        -360,
        -430
      ],
      "parameters": {
        "filters": {
          "labelIds": [
            "INBOX"
          ],
          "readStatus": "unread"
        },
        "operation": "getAll",
        "returnAll": true
      },
      "notesInFlow": true,
      "typeVersion": 2.1,
      "alwaysOutputData": false
    },
    {
      "id": "5d856e76-d335-4a72-8807-556417a35d2d",
      "name": "Get Email from Database",
      "type": "n8n-nodes-base.supabase",
      "notes": "Checks Supabase to see if this email has already been processed (by matching on email_id). Prevents duplicate GPT calls.",
      "position": [
        80,
        -580
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "email_id",
              "keyValue": "={{ $json.id }}"
            }
          ]
        },
        "tableId": "emails",
        "operation": "get"
      },
      "executeOnce": false,
      "notesInFlow": true,
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "4d1d53a4-14c4-4d53-b9cb-1f29d425060b",
      "name": "Check if Email in Database",
      "type": "n8n-nodes-base.if",
      "notes": "If the email does not exist in Supabase, continue with GPT processing. Otherwise, skip this email.",
      "position": [
        300,
        -580
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "5969f38d-31d4-4ed0-ad6c-d8bb522db40f",
              "operator": {
                "type": "boolean",
                "operation": "false",
                "singleValue": true
              },
              "leftValue": "={{ $json.isEmpty() }}",
              "rightValue": ""
            }
          ]
        },
        "looseTypeValidation": true
      },
      "notesInFlow": true,
      "typeVersion": 2.2,
      "alwaysOutputData": false
    },
    {
      "id": "9ff6b95c-9d19-4925-a718-15ca5774d81d",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "notes": "Loops through each unread email individually, allowing per-item processing (dedup, GPT, insert).",
      "position": [
        -140,
        -430
      ],
      "parameters": {
        "options": {}
      },
      "notesInFlow": true,
      "typeVersion": 3
    },
    {
      "id": "a46fc69d-9711-4846-b6ff-e77394f518b5",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1680,
        -640
      ],
      "parameters": {
        "width": 1000,
        "height": 1840,
        "content": "## \ud83d\udce9 Gmail \u2192 GPT \u2192 Supabase | Task Extractor\n\nThis n8n workflow automates the extraction of actionable tasks from unread Gmail messages using OpenAI's GPT API, stores the resulting task metadata in Supabase, and avoids re-processing previously handled emails.\n\n---\n\n## \u2705 What It Does\n\n1. **Triggers on a schedule** to check for unread emails in your Gmail inbox.\n2. **Loops through each email individually** using `SplitInBatches`.\n3. **Checks Supabase** to see if the email has already been processed.\n4. If it's a new email:\n   - Formats the email content into a structured GPT prompt\n   - Calls **ChatGPT-4o** to extract structured task data\n   - Inserts the result into your `emails` table in Supabase\n\n---\n\n## \ud83e\uddf0 Prerequisites\n\nBefore using this workflow, you must have:\n\n- An active **n8n Cloud or self-hosted instance**\n- A connected **Gmail account** with OAuth credentials in n8n\n- A **Supabase project** with an `emails` table and:\n  ```sql\n  ALTER TABLE emails ADD CONSTRAINT unique_email_id UNIQUE (email_id);\n  ```\n- An **OpenAI API key** with access to GPT-4o or GPT-3.5-turbo\n\n---\n\n## \ud83d\udd10 Required Credentials\n\n| Name            | Type       | Description                       |\n|-----------------|------------|-----------------------------------|\n| Gmail OAuth     | Gmail      | To pull unread messages           |\n| OpenAI API Key  | OpenAI     | To generate task summaries        |\n| Supabase API    | HTTP       | For inserting rows via REST API   |\n\n---\n\n## \ud83d\udd01 Environment Variables or Replacements\n\n- `Supabase_TaskManagement_URI` \u2192 e.g., `https://your-project.supabase.co`\n- `Supabase_TaskManagement_ANON_KEY` \u2192 Your Supabase anon key\n\nThese are used in the HTTP request to Supabase.\n\n---\n\n## \u23f0 Scheduling / Trigger\n\n- Triggered using a **Schedule node**\n- Default: every X minutes (adjust to your preference)\n- Uses a Gmail API filter: **unread emails with label = INBOX**\n\n---\n\n## \ud83e\udde0 Intended Use Case\n\n> Designed for productivity-minded professionals who want to extract, summarize, and store actionable tasks from incoming email \u2014 without processing the same email twice or wasting GPT API credits.\n\nThis is part of a larger system integrating GPT, calendar scheduling, and optional task platforms (like ClickUp).\n\n---\n\n## \ud83d\udce6 Output (Stored in Supabase)\n\nEach processed email includes:\n- `email_id`\n- `subject`\n- `sender`\n- `received_at`\n- `body` (email snippet)\n- `gpt_summary` (structured task)\n- `requires_deep_work` (from GPT logic)\n- `deleted` (initially false)"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "a7ad1235-9417-4c86-a3fd-cd72849f51dc",
  "connections": {
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "Get Email from Database",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger Workflow": {
      "main": [
        [
          {
            "node": "Get Unread Emails from Inbox",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare ChatGPT Prompt": {
      "main": [
        [
          {
            "node": "Extract Task Detail from Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Email from Database": {
      "main": [
        [
          {
            "node": "Check if Email in Database",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if Email in Database": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Prepare ChatGPT Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Unread Emails from Inbox": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Task Detail from Email": {
      "main": [
        [
          {
            "node": "Insert Email Detail to Supabase",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert Email Detail to Supabase": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This n8n workflow automates the extraction of actionable tasks from unread Gmail messages using OpenAI's GPT API, stores the resulting task metadata in Supabase, and avoids re-processing previously handled emails. Triggers on a schedule to check for unread emails in your Gmail…

Source: https://n8n.io/workflows/5496/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

The News Site from Colt, a telecom company, does not offer an RSS feed, therefore web scraping is the choice to extract and process the news.

OpenAI, HTTP Request, Noco Db +1
AI & RAG

Domain Outbound Machine is an n8n workflow designed to fully automate the domain sales process: lead generation, email extraction, personalized outreach, and automated email sending. It also stores ex

Google Sheets, HTTP Request, Gmail +1
AI & RAG

Sales Team V2. Uses supabase, httpRequest, crypto, openAi. Scheduled trigger; 25 nodes.

Supabase, HTTP Request, Crypto +2
AI & RAG

Monitor YouTube channels, fetch stats, classify videos as viral (≥ 1000 likes) or normal, and auto‑generate LinkedIn/email summaries with GPT‑4. Deliver via Gmail or SMTP. Clear node names, examples,

RSS Feed Read, HTTP Request, OpenAI +1
AI & RAG

This template automates invoice processing for teams that currently copy data from PDFs into spreadsheets by hand. It is ideal for small businesses, back-office teams, accounting, and operations who w

Google Drive, HTTP Request, OpenAI +1