AutomationFlowsAI & RAG › Get a Morning Email and Calendar Brief with Gmail, Google Calendar,…

Get a Morning Email and Calendar Brief with Gmail, Google Calendar,…

Original n8n title: Get a Morning Email and Calendar Brief with Gmail, Google Calendar, Gpt-4o-mini and Telegram

ByisaWOW @isawow on n8n.io

Activate this workflow once and every weekday morning at 8AM your phone receives a complete day briefing on Telegram — automatically. It fetches your unread emails and today's and tomorrow's calendar events in parallel, sends everything to GPT-4o-mini which filters out…

Cron / scheduled trigger★★★★☆ complexityAI-powered14 nodesGmailGoogle CalendarAgentOpenAI ChatTelegram
AI & RAG Trigger: Cron / scheduled Nodes: 14 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Agent → Gmail 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
{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "a98f6394-ea87-4ca2-94e9-de0113cf812d",
      "name": "Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -752,
        816
      ],
      "parameters": {
        "color": 4,
        "width": 524,
        "height": 1092,
        "content": "## Daily Morning Intelligence Brief \u2014 Gmail + Calendar + GPT-4o-mini + Telegram\n\nFor founders, executives, and busy professionals who want their full day context delivered to Telegram before they open a single app. Every weekday at 8AM this workflow automatically fetches unread emails from the last 24 hours and today and tomorrow's calendar events in parallel, merges the data, sends it to GPT-4o-mini which filters out promotions and noise, and delivers one clean structured brief to Telegram. You wake up with urgent emails, your schedule, tomorrow's preparation, and one recommended focus \u2014 all in one message.\n\n## How it works\n- **1. Schedule \u2014 Every Weekday 8AM** triggers the workflow automatically Monday to Friday\n- **2. Set \u2014 Config Values** stores your Telegram chat ID, Gmail address, name, and timezone\n- **3. Gmail \u2014 Fetch Unread Emails** fetches all unread inbox emails from the last 24 hours in parallel\n- **4. Google Calendar \u2014 Fetch Today and Tomorrow** fetches primary calendar events for today and tomorrow in parallel\n- **5. Code \u2014 Merge Emails and Calendar** reads both parallel branches, formats emails with sender and preview, separates events into today and tomorrow, and builds clean text for GPT\n- **6. AI Agent \u2014 Write Morning Brief** uses GPT-4o-mini to write a 4-section brief: urgent emails only (promotions filtered), today's schedule, tomorrow preparation with tips, and one focus recommendation\n- **8. Code \u2014 Prepare Telegram Message** adds a timezone-aware timestamp footer and a fallback message if GPT fails\n- **9. Telegram \u2014 Send Morning Brief** delivers the formatted brief with Markdown to your Telegram chat\n\n## Set up steps\n1. In **2. Set \u2014 Config Values** \u2014 replace PASTE_YOUR_TELEGRAM_CHAT_ID_HERE, PASTE_YOUR_GMAIL_ADDRESS_HERE, PASTE_YOUR_NAME_OR_COMPANY_HERE, and set your timezone (examples: Asia/Kolkata, America/New_York, Europe/London)\n2. In **3. Gmail \u2014 Fetch Unread Emails** \u2014 connect your Gmail OAuth2 credential\n3. In **4. Google Calendar \u2014 Fetch Today and Tomorrow** \u2014 connect your Google Calendar OAuth2 credential\n4. In **7. OpenAI \u2014 GPT-4o-mini Model** \u2014 connect your OpenAI credential\n5. In **9. Telegram \u2014 Send Morning Brief** \u2014 connect your Telegram Bot API credential\n6. Before first run \u2014 open Telegram, find your bot, and send /start to activate it\n7. Get your Telegram Chat ID by messaging @userinfobot on Telegram"
      },
      "typeVersion": 1
    },
    {
      "id": "7d20de47-a135-4f54-8f11-21cf9993ebc1",
      "name": "Section \u2014 Schedule and Config",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -160,
        1120
      ],
      "parameters": {
        "color": 5,
        "width": 468,
        "height": 356,
        "content": "## Schedule and Config\nWorkflow triggers automatically every weekday at 8AM. Config stores your Telegram chat ID, Gmail address, name, timezone, and all date variables used across the workflow."
      },
      "typeVersion": 1
    },
    {
      "id": "b87e4d35-22b1-4f38-97d2-11a1777d4274",
      "name": "Section \u2014 Parallel Data Fetch",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        416,
        880
      ],
      "parameters": {
        "color": 6,
        "width": 324,
        "height": 852,
        "content": "## Parallel Data Fetch\nGmail and Google Calendar are fetched simultaneously to save time. Gmail gets unread inbox emails from the last 24 hours. Calendar gets all events for today and tomorrow from the primary calendar."
      },
      "typeVersion": 1
    },
    {
      "id": "50a2a0dd-6e77-43f4-87fb-6f7d75c30ed8",
      "name": "Section \u2014 Data Merge and AI Brief Writing",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        864,
        1088
      ],
      "parameters": {
        "color": 6,
        "width": 596,
        "height": 580,
        "content": "## Data Merge and AI Brief Writing\nThe Code node reads both parallel branches using .all() and formats emails and events into clean text. GPT-4o-mini writes a structured 4-section brief: urgent emails, today's schedule, tomorrow preparation, and one focus recommendation. Promotions and notifications are filtered out."
      },
      "typeVersion": 1
    },
    {
      "id": "334046db-d5e2-4152-b74b-4bfd46c1688c",
      "name": "Section \u2014 Telegram Delivery",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1536,
        1104
      ],
      "parameters": {
        "color": 4,
        "width": 580,
        "height": 404,
        "content": "## Telegram Delivery\nAdds a timezone-aware timestamp footer and a fallback message if GPT fails. Sends the complete formatted brief to your Telegram chat with Markdown rendering."
      },
      "typeVersion": 1
    },
    {
      "id": "465fbadf-3c07-4703-9d93-0b81406473a7",
      "name": "1. Schedule \u2014 Every Weekday 8AM",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -96,
        1264
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8 * * 1-5"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "3671ecad-99b5-43cc-8d88-cebbd6b44175",
      "name": "2. Set \u2014 Config Values",
      "type": "n8n-nodes-base.set",
      "position": [
        144,
        1264
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cfg-001",
              "name": "telegramChatId",
              "type": "string",
              "value": "PASTE_YOUR_TELEGRAM_CHAT_ID_HERE"
            },
            {
              "id": "cfg-002",
              "name": "gmailUserId",
              "type": "string",
              "value": "PASTE_YOUR_GMAIL_ADDRESS_HERE"
            },
            {
              "id": "cfg-003",
              "name": "companyName",
              "type": "string",
              "value": "PASTE_YOUR_NAME_OR_COMPANY_HERE"
            },
            {
              "id": "cfg-004",
              "name": "timezone",
              "type": "string",
              "value": "Asia/Kolkata"
            },
            {
              "id": "cfg-005",
              "name": "todayFormatted",
              "type": "string",
              "value": "={{ $now.toFormat('cccc, dd MMMM yyyy') }}"
            },
            {
              "id": "cfg-006",
              "name": "todayISO",
              "type": "string",
              "value": "={{ $now.toISO() }}"
            },
            {
              "id": "cfg-007",
              "name": "tomorrowISO",
              "type": "string",
              "value": "={{ $now.plus({days: 1}).toISO() }}"
            },
            {
              "id": "cfg-008",
              "name": "dayAfterTomorrowISO",
              "type": "string",
              "value": "={{ $now.plus({days: 2}).startOf('day').toISO() }}"
            },
            {
              "id": "cfg-009",
              "name": "yesterdayISO",
              "type": "string",
              "value": "={{ $now.minus({days: 1}).toISO() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "cdc47741-beda-4e78-8cc8-7820429336a6",
      "name": "3. Gmail \u2014 Fetch Unread Emails",
      "type": "n8n-nodes-base.gmail",
      "position": [
        512,
        1088
      ],
      "parameters": {
        "filters": {
          "labelIds": [
            "INBOX",
            "UNREAD"
          ],
          "readStatus": "unread",
          "receivedAfter": "={{ $json.yesterdayISO }}"
        },
        "operation": "getAll"
      },
      "typeVersion": 2.1
    },
    {
      "id": "82baeb6b-eaca-469a-b784-f279ced44a6b",
      "name": "4. Google Calendar \u2014 Fetch Today and Tomorrow",
      "type": "n8n-nodes-base.googleCalendar",
      "position": [
        512,
        1408
      ],
      "parameters": {
        "options": {},
        "calendar": {
          "__rl": true,
          "mode": "id",
          "value": "primary"
        },
        "operation": "getAll"
      },
      "typeVersion": 1.3
    },
    {
      "id": "b4553e33-6150-42bd-af13-e623f894e404",
      "name": "5. Code \u2014 Merge Emails and Calendar",
      "type": "n8n-nodes-base.code",
      "position": [
        912,
        1280
      ],
      "parameters": {
        "jsCode": "// Collect emails and calendar events from parallel branches\nconst config = $('2. Set \u2014 Config Values').item.json;\n\n// Process emails\nlet emailItems = [];\ntry {\n  const gmailItems = $('3. Gmail \u2014 Fetch Unread Emails').all();\n  emailItems = gmailItems.map(item => {\n    const msg = item.json;\n    return {\n      from: msg.from || 'Unknown sender',\n      subject: msg.subject || 'No subject',\n      date: msg.date || '',\n      snippet: (msg.snippet || '').substring(0, 200)\n    };\n  });\n} catch (e) {\n  emailItems = [];\n}\n\n// Process calendar events\nlet calendarItems = [];\ntry {\n  const calItems = $('4. Google Calendar \u2014 Fetch Today and Tomorrow').all();\n  calendarItems = calItems.map(item => {\n    const event = item.json;\n    const startTime = event.start?.dateTime || event.start?.date || '';\n    const endTime = event.end?.dateTime || event.end?.date || '';\n    let timeDisplay = 'All day';\n    if (event.start?.dateTime) {\n      const start = new Date(event.start.dateTime);\n      const end = new Date(event.end?.dateTime || event.start.dateTime);\n      timeDisplay =\n        start.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' }) +\n        ' to ' +\n        end.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' });\n    }\n    const eventDate = new Date(startTime);\n    const today = new Date();\n    const isToday = eventDate.toDateString() === today.toDateString();\n    const tomorrow = new Date(today);\n    tomorrow.setDate(today.getDate() + 1);\n    const isTomorrow = eventDate.toDateString() === tomorrow.toDateString();\n    return {\n      title: event.summary || 'Untitled event',\n      time: timeDisplay,\n      location: event.location || '',\n      attendees: (event.attendees || []).length,\n      isToday,\n      isTomorrow\n    };\n  });\n} catch (e) {\n  calendarItems = [];\n}\n\nconst todayEvents = calendarItems.filter(e => e.isToday);\nconst tomorrowEvents = calendarItems.filter(e => e.isTomorrow);\n\n// Format emails for GPT\nlet emailText = 'No unread emails in the last 24 hours.';\nif (emailItems.length > 0) {\n  emailText = emailItems.slice(0, 20).map((e, i) =>\n    (i + 1) + '. From: ' + e.from + '\\n   Subject: ' + e.subject + '\\n   Preview: ' + e.snippet\n  ).join('\\n\\n');\n}\n\n// Format today events for GPT\nlet todayText = 'No events scheduled for today.';\nif (todayEvents.length > 0) {\n  todayText = todayEvents.map((e, i) =>\n    (i + 1) + '. ' + e.title + ' \u2014 ' + e.time +\n    (e.location ? ' \u2014 ' + e.location : '') +\n    (e.attendees > 0 ? ' (' + e.attendees + ' attendees)' : '')\n  ).join('\\n');\n}\n\n// Format tomorrow events for GPT\nlet tomorrowText = 'No events scheduled for tomorrow.';\nif (tomorrowEvents.length > 0) {\n  tomorrowText = tomorrowEvents.map((e, i) =>\n    (i + 1) + '. ' + e.title + ' \u2014 ' + e.time +\n    (e.location ? ' \u2014 ' + e.location : '') +\n    (e.attendees > 0 ? ' (' + e.attendees + ' attendees)' : '')\n  ).join('\\n');\n}\n\nreturn [{\n  json: {\n    emailText,\n    todayText,\n    tomorrowText,\n    totalEmails: emailItems.length,\n    totalTodayEvents: todayEvents.length,\n    totalTomorrowEvents: tomorrowEvents.length,\n    todayFormatted: config.todayFormatted,\n    companyName: config.companyName,\n    telegramChatId: config.telegramChatId\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "77b38857-9919-451e-9665-ff7fd022adbf",
      "name": "6. AI Agent \u2014 Write Morning Brief",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1152,
        1280
      ],
      "parameters": {
        "text": "=You are a smart personal assistant creating a morning brief for {{ $json.companyName }}.\n\nToday is {{ $json.todayFormatted }}.\n\nUNREAD EMAILS (last 24 hours) \u2014 {{ $json.totalEmails }} total:\n{{ $json.emailText }}\n\nTODAY'S CALENDAR \u2014 {{ $json.totalTodayEvents }} events:\n{{ $json.todayText }}\n\nTOMORROW'S CALENDAR \u2014 {{ $json.totalTomorrowEvents }} events:\n{{ $json.tomorrowText }}\n\nWrite a clean morning brief for Telegram. Use plain text only. No HTML.\nYou may use basic Telegram markdown: *bold* for headings, and dashes for lists.\n\nStructure it exactly like this:\n\nGood morning [name]! Here is your brief for [today's date].\n\n*URGENT EMAILS*\nList only emails that need a reply or action today. Skip newsletters, promotions, automated notifications, and receipts. For each urgent email write one line: who sent it and what action is needed. If no urgent emails write: No urgent emails today.\n\n*TODAY'S SCHEDULE*\nList all events for today with their time. If no events write: No meetings today \u2014 a free day.\n\n*PREPARE FOR TOMORROW*\nList tomorrow's events so the user can prepare. If tomorrow has meetings with more than 2 attendees, add one preparation tip. If no events write: Nothing scheduled for tomorrow.\n\n*ONE FOCUS FOR TODAY*\nBased on the emails and calendar, write one sentence recommending the most important thing to focus on today.\n\nKeep the entire brief under 300 words. Be direct and clear.",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "dcfc7f3f-2e4a-4f1c-ac82-d0c8f0160014",
      "name": "7. OpenAI \u2014 GPT-4o-mini Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1152,
        1488
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini"
        },
        "options": {
          "maxTokens": 600,
          "temperature": 0.4
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "ac24f86a-bb32-43cd-b45e-0a95adccb45f",
      "name": "8. Code \u2014 Prepare Telegram Message",
      "type": "n8n-nodes-base.code",
      "position": [
        1648,
        1280
      ],
      "parameters": {
        "jsCode": "// Get the brief text from GPT output\nconst briefText = $input.first().json.output || 'Good morning! Your brief could not be generated today. Please check your credentials.';\nconst config = $('2. Set \u2014 Config Values').item.json;\n\n// Add a timestamp footer\nconst timeNow = new Date().toLocaleTimeString('en-GB', {\n  hour: '2-digit',\n  minute: '2-digit',\n  timeZone: config.timezone || 'UTC'\n});\n\nconst fullMessage = briefText + '\\n\\n_Brief generated at ' + timeNow + ' \u2014 powered by n8n_';\n\nreturn [{\n  json: {\n    telegramMessage: fullMessage,\n    telegramChatId: config.telegramChatId\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "545aceff-2baa-4aaf-b17a-f1dce5519b51",
      "name": "9. Telegram \u2014 Send Morning Brief",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1872,
        1280
      ],
      "parameters": {
        "text": "={{ $json.telegramMessage }}",
        "chatId": "={{ $json.telegramChatId }}",
        "additionalFields": {
          "parse_mode": "Markdown",
          "appendAttribution": false
        }
      },
      "typeVersion": 1.2
    }
  ],
  "connections": {
    "2. Set \u2014 Config Values": {
      "main": [
        [
          {
            "node": "3. Gmail \u2014 Fetch Unread Emails",
            "type": "main",
            "index": 0
          },
          {
            "node": "4. Google Calendar \u2014 Fetch Today and Tomorrow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "7. OpenAI \u2014 GPT-4o-mini Model": {
      "ai_languageModel": [
        [
          {
            "node": "6. AI Agent \u2014 Write Morning Brief",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "3. Gmail \u2014 Fetch Unread Emails": {
      "main": [
        [
          {
            "node": "5. Code \u2014 Merge Emails and Calendar",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "1. Schedule \u2014 Every Weekday 8AM": {
      "main": [
        [
          {
            "node": "2. Set \u2014 Config Values",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6. AI Agent \u2014 Write Morning Brief": {
      "main": [
        [
          {
            "node": "8. Code \u2014 Prepare Telegram Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8. Code \u2014 Prepare Telegram Message": {
      "main": [
        [
          {
            "node": "9. Telegram \u2014 Send Morning Brief",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5. Code \u2014 Merge Emails and Calendar": {
      "main": [
        [
          {
            "node": "6. AI Agent \u2014 Write Morning Brief",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "4. Google Calendar \u2014 Fetch Today and Tomorrow": {
      "main": [
        [
          {
            "node": "5. Code \u2014 Merge Emails and Calendar",
            "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

Activate this workflow once and every weekday morning at 8AM your phone receives a complete day briefing on Telegram — automatically. It fetches your unread emails and today's and tomorrow's calendar events in parallel, sends everything to GPT-4o-mini which filters out…

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

This workflow automates customer outreach for marketing campaigns, including customer prioritization, AI-generated emails, automated sending, reply tracking, and meeting scheduling. Data Synchronizati

Agent, Data Table, OpenAI Chat +6
AI & RAG

My workflow 14. Uses rssFeedRead, chainLlm, lmChatOpenAi, openWeatherMap. Scheduled trigger; 40 nodes.

RSS Feed Read, Chain Llm, OpenAI Chat +6
AI & RAG

This workflow automates the process of generating, reviewing, and publishing blog posts across multiple platforms, now enhanced with support for RSS Feeds as a content source. It streamlines the manag

HTTP Request, Html Extract, RSS Feed Read +9
AI & RAG

This n8n workflow automates the daily generation of comprehensive analytics reports from multiple websites, processes them using OpenAI's powerful language models, and then delivers the insights direc

Memory Buffer Window, Google Analytics, Agent +6
AI & RAG

This n8n automation workflow is designed for sales teams, client managers, consultants, or anyone who regularly schedules and follows up on meetings — and wants to save time doing it. If you often fin

Google Calendar, Google Sheets, N8N Nodes Rapiwa +5