workflow recipe

n8n OpenAI Email Summary Workflow for Gmail Triage

Use Gmail to collect a narrow set of messages, Set or Code to clean the fields, OpenAI to summarize, and Slack or Gmail to deliver a concise digest.

Use when
n8n workflows, Gmail, OpenAI, email summaries
First check
Define the Gmail label or query that marks messages safe for summarization.
Time to check
5-10 minutes
Next step
Run the recommended steps, then verify a production execution.

Independent third-party notes. n8n is a trademark of its owner and is referenced only for compatibility and troubleshooting context.

Quick Answer

Use Gmail to collect a narrow set of messages, Set or Code to clean the fields, OpenAI to summarize, and Slack or Gmail to deliver a concise digest.

Problem Pattern

AI email summary workflows can leak too much content, summarize the wrong messages, or fail when prompts receive messy HTML and long threads.

Version awareness

Last reviewed 2026-05-21

Key Facts

Input control
Summarize only messages that match a specific label, query, or schedule window.
Prompt control
Use short, structured fields rather than raw email HTML when possible.
Output control
Send a digest to Slack, email, or a sheet depending on the team's workflow.
Privacy control
Avoid processing sensitive messages unless the data policy allows it.
  1. Define the Gmail label or query that marks messages safe for summarization.
  2. Extract only the fields needed for context: sender, subject, snippet, date, and selected body text.
  3. Use OpenAI with a compact instruction that asks for action items, urgency, and a one-sentence summary.
  4. Format the summary with Set before sending it to Slack, Gmail, or a sheet.
  5. Test with short, long, and noisy email threads before enabling the schedule.

Verification

  • Only labeled or query-matched emails enter the workflow.
  • The prompt receives clean text and useful metadata.
  • The output summary includes sender, topic, urgency, and action items.
  • Sensitive fields are excluded from the final digest.

Warnings

  • Do not summarize private or regulated emails without a clear data policy.
  • Raw HTML and long threads can produce poor summaries unless cleaned first.
  • Model output should be treated as a draft, not a guaranteed factual record.

Best For

  • Daily inbox triage
  • Lead or support email summaries
  • Small teams that need a digest before deeper review

Not For

  • Legal, medical, or regulated email processing without review
  • Workflows that require guaranteed extraction accuracy without human checks

Common Mistakes

  • Running the workflow over the entire inbox.
  • Sending raw email HTML into the prompt.
  • Forgetting to label safe messages before summarization.
  • Treating model output as a final decision rather than a triage aid.

Examples

Daily digest flow Keep the input narrow and the output easy to scan.
Schedule Trigger: every weekday morning
Gmail: find messages labeled summarize
Set: sender, subject, date, snippet, cleaned_text
OpenAI: summarize action items and urgency
Slack: post digest to team channel

Importable Workflow Starter

openai-email-summary-starter.json

Starter workflow for summarizing selected email text with OpenAI and posting the summary to a review destination. Node type names can vary by n8n version; verify after import.

Download JSON Compare automation tools Replace credentials and IDs before importing.

Node order

  1. Manual/Webhook test input
  2. Set email fields
  3. OpenAI summary
  4. Set summary output

Credential checklist

  • OpenAI credential configured in n8n.
  • Optional Gmail/IMAP credential if replacing the manual input with a real mailbox trigger.
Source field Destination field Notes
email.subject summary title Keep title short.
email.body OpenAI prompt body Strip signatures or quoted replies before production use.
email.messageId dedupe key Store before sending summaries.
Workflow JSON Replace credential names and destination IDs before activation.
{
  "name": "OpenAI email summary starter",
  "nodes": [
    {
      "parameters": {},
      "id": "Manual",
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "keepOnlySet": true,
        "values": {
          "string": [
            {
              "name": "messageId",
              "value": "msg_example_456"
            },
            {
              "name": "subject",
              "value": "Weekly vendor update"
            },
            {
              "name": "body",
              "value": "Replace this with sanitized email body text before calling OpenAI."
            }
          ]
        }
      },
      "id": "SetEmail",
      "name": "Set email fields",
      "type": "n8n-nodes-base.set",
      "typeVersion": 2,
      "position": [
        240,
        0
      ]
    },
    {
      "parameters": {
        "resource": "chat",
        "operation": "complete",
        "model": "REPLACE_WITH_MODEL",
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "Summarize operational email context without exposing secrets."
            },
            {
              "role": "user",
              "content": "={{\"Subject: \" + $json.subject + \"\\n\\nBody: \" + $json.body}}"
            }
          ]
        }
      },
      "id": "OpenAI",
      "name": "Summarize with OpenAI",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 1,
      "position": [
        480,
        0
      ],
      "credentials": {
        "openAiApi": {
          "id": "REPLACE_WITH_CREDENTIAL_ID",
          "name": "REPLACE_WITH_OPENAI_CREDENTIAL"
        }
      }
    },
    {
      "parameters": {
        "keepOnlySet": true,
        "values": {
          "string": [
            {
              "name": "messageId",
              "value": "={{$(\"Set email fields\").item.json.messageId}}"
            },
            {
              "name": "summary",
              "value": "={{$json.text || $json.message?.content || $json.choices?.[0]?.message?.content || \"Review OpenAI output shape\"}}"
            }
          ]
        }
      },
      "id": "SetSummary",
      "name": "Set summary output",
      "type": "n8n-nodes-base.set",
      "typeVersion": 2,
      "position": [
        720,
        0
      ]
    }
  ],
  "connections": {
    "Manual Trigger": {
      "main": [
        [
          {
            "node": "Set email fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set email fields": {
      "main": [
        [
          {
            "node": "Summarize with OpenAI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Summarize with OpenAI": {
      "main": [
        [
          {
            "node": "Set summary output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "active": false,
  "pinData": {},
  "versionId": "replace-after-import"
}
Sample input
{
  "messageId": "msg_example_456",
  "subject": "Weekly vendor update",
  "body": "Long email body goes here."
}
Expected output
{
  "messageId": "msg_example_456",
  "summary": "Short operational summary.",
  "nextAction": "Review vendor dates."
}

Failure paths

  • Prompt includes private data that should be redacted.
  • Output shape changes and downstream node expects a fixed key.
  • OpenAI credential or model setting differs between environments.

Activation checklist

  • Import into a non-production workflow first.
  • Replace placeholder credential names and destination IDs.
  • Run the minimal test payload with non-sensitive data.
  • Confirm error paths do not leak secrets.
  • Activate only after one successful end-to-end production-shaped test.

Duplicate prevention: Use a stable event ID, message ID, or payload hash in a datastore/sheet column before writing side effects.

Minimal test payload
{
  "subject": "Smoke test",
  "body": "Summarize this short email in one sentence."
}

What to change before import

  • Credential names and credential IDs.
  • Slack channel, sheet ID, email labels, or other destination identifiers.
  • Webhook path and response body.
  • Any sample fields that differ from your payload.

FAQ

Can this summarize all unread email?

It can, but that is usually too broad. A label or query keeps privacy, noise, and cost easier to control.

Why are summaries vague?

The input may be mostly HTML, quoted thread text, or missing key context. Clean the text and pass structured metadata.

Sources