AutomationFlowsAI & RAG › Daily Positive News Digest with Openai and Gmail

Daily Positive News Digest with Openai and Gmail

ByPiotr Sobolewski @piotrsobolewski on n8n.io

How it works

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

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

This workflow follows the Gmail → OpenAI 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
{
  "nodes": [
    {
      "name": "Daily Morning Trigger (7 AM)",
      "type": "n8n-nodes-base.cron",
      "notes": {
        "text": "### 1. Daily Morning Trigger (7 AM)\n\nThis `Cron` node triggers the workflow automatically every **day at 7:00 AM** (based on your n8n server's local time zone).\n\n**To change the schedule:** Adjust the 'Hour' and 'Minute' fields to your preferred time for receiving the news digest.",
        "position": "right"
      },
      "position": [
        240,
        300
      ],
      "parameters": {
        "mode": "everyDay",
        "value": {
          "hour": [
            7
          ],
          "minute": [
            0
          ]
        },
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "name": "Fetch Positive News (RSS)",
      "type": "n8n-nodes-base.rssFeed",
      "notes": {
        "text": "### 2. Fetch Positive News (RSS)\n\nThis `RSS Feed` node fetches the latest articles from the Good News Network, a reliable source for positive stories.\n\n**Setup:**\n1.  **URL:** Pre-filled with `https://www.goodnewsnetwork.org/feed/`.\n2.  **To add more sources:** You can add more `RSS Feed` nodes in parallel and then use an `Item Lists` node set to 'Merge Items' to combine their outputs before the 'Prepare for AI' node.",
        "position": "right"
      },
      "position": [
        480,
        300
      ],
      "parameters": {
        "url": "https://www.goodnewsnetwork.org/feed/",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "name": "Prepare for AI",
      "type": "n8n-nodes-base.function",
      "notes": {
        "text": "### 3. Prepare for AI\n\nThis `Function` node formats the news articles' titles and descriptions into a single `articleText` field, which is easier for the AI to process.\n\nIt also preserves the original title, description, and link for the final summary.\n\n**No configuration needed**; it automatically processes the RSS feed items.",
        "position": "right"
      },
      "position": [
        720,
        300
      ],
      "parameters": {
        "options": {},
        "function": "const preparedItems = [];\n\nfor (const item of items) {\n  const title = item.json.title || 'No Title';\n  const description = item.json.contentSnippet || item.json.description || 'No Description';\n  const link = item.json.link || '#';\n\n  preparedItems.push({\n    json: {\n      originalTitle: title,\n      originalDescription: description,\n      originalLink: link,\n      articleText: `Title: ${title}\\nDescription: ${description}`\n    }\n  });\n}\n\nreturn preparedItems;"
      },
      "typeVersion": 1
    },
    {
      "name": "AI: Summarize Positive News",
      "type": "n8n-nodes-base.openAi",
      "notes": {
        "text": "### 4. AI: Summarize Positive News\n\nThis `OpenAI` node is the core of the 'positive news' filtering and summarization.\n\n**Setup:**\n1.  **OpenAI Credential:** Click 'Credentials' and select 'New Credential'. Provide your OpenAI API Key (starts with `sk-`). Save it.\n2.  **Model:** `gpt-3.5-turbo` is pre-selected. For higher quality summaries and better sentiment discernment, consider `gpt-4o` (may incur higher costs).\n3.  **Prompts:** The 'System' prompt guides the AI to only summarize positive/neutral-to-positive articles and output 'SKIP' otherwise.\n\n**Output:** The AI's summary or the word 'SKIP'.",
        "position": "right"
      },
      "position": [
        960,
        300
      ],
      "parameters": {
        "model": "gpt-3.5-turbo",
        "options": {},
        "messages": [
          {
            "role": "system",
            "content": "You are a news summarizer focused only on positive and uplifting news. Read the provided article text. If it is clearly positive or neutral-to-positive, summarize its core message in 2-3 concise sentences, focusing on the positive aspects. If it is negative, neutral, or not news (e.g., ads), output the single word 'SKIP'."
          },
          {
            "role": "user",
            "content": "Article:\n{{ $json.articleText }}"
          }
        ]
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "name": "Filter & Prepare Positive Summaries",
      "type": "n8n-nodes-base.function",
      "notes": {
        "text": "### 5. Filter & Prepare Positive Summaries\n\nThis `Function` node filters out any items where the AI responded with 'SKIP' (meaning the news was not positive enough).\n\nFor the remaining items, it prepares a clean object containing the original title, link, and the AI-generated positive summary.\n\n**No configuration needed**; it automatically processes the AI output.",
        "position": "right"
      },
      "position": [
        1200,
        300
      ],
      "parameters": {
        "options": {},
        "function": "const positiveSummaries = [];\n\nfor (const item of items) {\n  const aiResponse = item.json.choices[0].message.content.trim();\n\n  if (aiResponse.toUpperCase() !== 'SKIP') {\n    positiveSummaries.push({\n      json: {\n        originalTitle: item.json.originalTitle,\n        originalLink: item.json.originalLink,\n        summary: aiResponse\n      }\n    });\n  }\n}\n\nreturn positiveSummaries;"
      },
      "typeVersion": 1
    },
    {
      "name": "If Positive News Found",
      "type": "n8n-nodes-base.if",
      "notes": {
        "text": "### 6. If Positive News Found\n\nThis `If` node checks if any positive news articles were actually found and summarized after filtering.\n\n* **'True' branch:** If positive news exists, the workflow proceeds to format and send the email.\n* **'False' branch:** If no positive news was found for the day, the workflow will still send an email, but with a message indicating no positive news was found (handled by the 'Format No Positive News Message' node).\n\n**No configuration needed**; it checks if the array of items is not empty.",
        "position": "right"
      },
      "position": [
        1440,
        300
      ],
      "parameters": {
        "conditions": [
          {
            "value1": "={{ $json.length }}",
            "value2": "0",
            "operation": "notEqual"
          }
        ]
      },
      "typeVersion": 1
    },
    {
      "name": "Format Positive News Email",
      "type": "n8n-nodes-base.function",
      "notes": {
        "text": "### 7. Format Positive News Email\n\nThis `Function` node compiles all the positive news summaries into a single, formatted email body.\n\n**Customization:**\n* You can customize the greeting, closing, and the way each news item is presented.\n* The email body is formatted using Markdown for bolding and line breaks, which Gmail supports.\n\n**No configuration needed** if your previous node's output matches expectations.",
        "position": "right"
      },
      "position": [
        1680,
        220
      ],
      "parameters": {
        "options": {},
        "function": "let emailBody = \"\";\n\nemailBody += \"Good morning! Here's your daily dose of positive news:\\n\\n\";\n\nfor (const item of items) {\n  emailBody += `**${item.json.originalTitle}**\\n` +\n               `${item.json.summary}\\n` +\n               `Read more: ${item.json.originalLink}\\n\\n---\\n\\n`;\n}\n\nemailBody += \"Have a wonderful day!\\n\\nThis digest was brought to you by n8n.\";\n\nreturn [{ json: { emailSubject: \"\u2600\ufe0f Your Daily Positive News Digest!\", emailBody: emailBody } }];"
      },
      "typeVersion": 1
    },
    {
      "name": "Format No Positive News Message",
      "type": "n8n-nodes-base.function",
      "notes": {
        "text": "### 7. Format No Positive News Message\n\nThis `Function` node creates a fallback message for your email if the workflow doesn't find any positive news articles after filtering.\n\n**No configuration needed**; it provides a default message when there's no positive news.",
        "position": "right"
      },
      "position": [
        1680,
        380
      ],
      "parameters": {
        "options": {},
        "function": "return [{ json: { emailSubject: \"\u2601\ufe0f Daily Positive News Digest: No Positive News Today\", emailBody: \"Good morning!\\n\\nUnfortunately, I couldn't find any predominantly positive news articles for your digest today.\\n\\nStay positive, and check back tomorrow!\\n\\nThis digest was brought to you by n8n.\" } }];"
      },
      "typeVersion": 1
    },
    {
      "name": "Send Daily Digest Email",
      "type": "n8n-nodes-base.gmail",
      "notes": {
        "text": "### 8. Send Daily Digest Email\n\nThis `Gmail` node sends the final email digest (either with positive news or the 'no news found' message) to your mailbox.\n\n**Setup:**\n1.  **Gmail Credential:** Select your Gmail API credential.\n2.  **From Email:** Enter your Gmail address (must match the authenticated account).\n3.  **To Email:** **IMPORTANT: Change `YOUR_RECIPIENT_EMAIL@example.com` to your actual email address!**\n4.  **Subject & Text:** These fields pull the formatted subject and body from the previous 'Format' nodes.\n\n**Test this node by running the workflow** to ensure you receive the email.",
        "position": "right"
      },
      "position": [
        1920,
        300
      ],
      "parameters": {
        "text": "={{ $json.emailBody }}",
        "options": {},
        "subject": "={{ $json.emailSubject }}",
        "toEmail": "user@example.com",
        "fromEmail": "user@example.com"
      },
      "credentials": {
        "gmailApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    }
  ],
  "version": 1,
  "connections": {
    "Prepare for AI": {
      "main": [
        [
          {
            "node": "AI: Summarize Positive News",
            "type": "main"
          }
        ]
      ]
    },
    "If Positive News Found": {
      "main": [
        [
          {
            "node": "Format Positive News Email",
            "type": "main"
          }
        ],
        [
          {
            "node": "Format No Positive News Message",
            "type": "main"
          }
        ]
      ]
    },
    "Fetch Positive News (RSS)": {
      "main": [
        [
          {
            "node": "Prepare for AI",
            "type": "main"
          }
        ]
      ]
    },
    "Format Positive News Email": {
      "main": [
        [
          {
            "node": "Send Daily Digest Email",
            "type": "main"
          }
        ]
      ]
    },
    "AI: Summarize Positive News": {
      "main": [
        [
          {
            "node": "Filter & Prepare Positive Summaries",
            "type": "main"
          }
        ]
      ]
    },
    "Daily Morning Trigger (7 AM)": {
      "main": [
        [
          {
            "node": "Fetch Positive News (RSS)",
            "type": "main"
          }
        ]
      ]
    },
    "Format No Positive News Message": {
      "main": [
        [
          {
            "node": "Send Daily Digest Email",
            "type": "main"
          }
        ]
      ]
    },
    "Filter & Prepare Positive Summaries": {
      "main": [
        [
          {
            "node": "If Positive News Found",
            "type": "main"
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

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

About this workflow

How it works

Source: https://n8n.io/workflows/6667/ — 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

Personalized Outreach & Follow-Up - Phase 2. Uses googleSheets, openAi, gmail, gmailTrigger. Scheduled trigger; 59 nodes.

Google Sheets, OpenAI, Gmail +2
AI & RAG

A scheduled process aggregates content from eight distinct data sources and standardizes all inputs into a unified format. AI models perform sentiment scoring, detect conspiracy or misinformation sign

HTTP Request, OpenAI, Postgres +2
AI & RAG

This workflow monitors filesystem sync and backup jobs by validating their execution logs, not by running or inspecting the jobs themselves.

Google Cloud Storage, Gmail, GitHub +2
AI & RAG

This advanced workflow automates brand monitoring and media coverage tracking for musicians, bands, and music labels. The system uses multiple search queries (dorky) to discover mentions across the we

Google Sheets, Gmail, @Brave/N8N Nodes Brave Search +1
AI & RAG

Stop wasting billable hours on manual time-tracking. AutoTimesheet Pro uses AI to collect emails, meetings, and GitHub work, then writes a clean timesheet straight into Google Sheets. Perfect for deve

Google Calendar, Gmail, GitHub +3