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 →
{
"name": "Gmail \u2192 Telegram Daily Report (V3 AI Pro)",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"triggerAtHour": 7,
"triggerAtMinute": 0
}
]
}
},
"id": "schedule-trigger",
"name": "\u23f0 Trigger 7h S\u00e1ng",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [
240,
500
]
},
{
"parameters": {
"resource": "message",
"operation": "getAll",
"returnAll": false,
"limit": 100,
"filters": {
"q": "is:unread newer_than:1d"
},
"options": {}
},
"id": "gmail-get",
"name": "\ud83d\udcec L\u1ea5y Email (100)",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
480,
500
],
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// Pre-classify before sending to AI (reduces AI token cost)\nconst emails = $input.all();\n\nconst SPAM_PATTERNS = ['shopee', 'lazada', 'tiki', 'grab', 'noreply', 'no-reply', 'donotreply', 'unsubscribe'];\nconst PROMO_KW = ['gi\u1ea3m gi\u00e1', 'flash sale', 'khuy\u1ebfn m\u00e3i', '\u01b0u \u0111\u00e3i', '% off', 'sale', 'voucher', 'coupon'];\n\nconst preClassified = emails.map(item => {\n const e = item.json;\n const from = (e.from || '').toLowerCase();\n const subject = (e.subject || '').toLowerCase();\n const isObviousSpam = SPAM_PATTERNS.some(p => from.includes(p));\n const isObviousPromo = PROMO_KW.some(kw => subject.includes(kw));\n\n return {\n id: e.id,\n from: (e.from || '').replace(/<[^>]+>/g, '').trim(),\n subject: e.subject || '(no subject)',\n snippet: (e.snippet || e.textPlain || '').substring(0, 200),\n date: e.date,\n pre_category: isObviousSpam ? 'spam' : isObviousPromo ? 'promotion' : 'needs_ai_review'\n };\n});\n\nconst needsReview = preClassified.filter(e => e.pre_category === 'needs_ai_review');\nconst obviousSpam = preClassified.filter(e => e.pre_category === 'spam');\nconst obviousPromo = preClassified.filter(e => e.pre_category === 'promotion');\n\nconsole.log(`Pre-classified: ${obviousSpam.length} spam, ${obviousPromo.length} promo, ${needsReview.length} needs AI`);\n\nreturn [{ json: {\n all_emails: preClassified,\n needs_ai_review: needsReview,\n obvious_spam: obviousSpam,\n obvious_promo: obviousPromo,\n total: emails.length\n}}];"
},
"id": "pre-classify",
"name": "\ud83d\udd0d Pre-Classification (Rule-Based)",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
720,
500
],
"notes": "Ph\u00e2n lo\u1ea1i s\u01a1 b\u1ed9 tr\u01b0\u1edbc khi g\u1ecdi AI. M\u1ee5c \u0111\u00edch: gi\u1ea3m token cost AI, ch\u1ec9 g\u1eedi email c\u1ea7n ph\u00e2n t\u00edch."
},
{
"parameters": {
"jsCode": "// Prepare AI prompt with only emails needing review\nconst data = $input.first().json;\nconst emailsForAI = data.needs_ai_review;\n\nif (emailsForAI.length === 0) {\n return [{ json: { skip_ai: true, ...data } }];\n}\n\nconst emailList = emailsForAI.map((e, i) =>\n `[${i+1}] From: ${e.from}\\nSubject: ${e.subject}\\nSnippet: ${e.snippet}`\n).join('\\n---\\n');\n\nconst prompt = `B\u1ea1n l\u00e0 tr\u1ee3 l\u00fd qu\u1ea3n l\u00fd email. Ph\u00e2n lo\u1ea1i c\u00e1c email sau v\u00e0o m\u1ed9t trong c\u00e1c nh\u00f3m:\n- IMPORTANT: T\u1eeb s\u1ebfp/kh\u00e1ch h\u00e0ng/\u0111\u1ed1i t\u00e1c, c\u00f3 deadline, c\u1ea7n ph\u1ea3n h\u1ed3i\n- WORK: Li\u00ean quan c\u00f4ng vi\u1ec7c nh\u01b0ng kh\u00f4ng urgent\n- PERSONAL: Email c\u00e1 nh\u00e2n/gia \u0111\u00ecnh\n- NEWSLETTER: B\u1ea3n tin th\u00f4ng th\u01b0\u1eddng\n- SPAM: Qu\u1ea3ng c\u00e1o, r\u00e1c\n\nEmail c\u1ea7n ph\u00e2n lo\u1ea1i:\n${emailList}\n\nTr\u1ea3 l\u1eddi d\u1ea1ng JSON array, m\u1ed7i item c\u00f3: index (1-based), category, reason_vi (l\u00fd do b\u1eb1ng ti\u1ebfng Vi\u1ec7t, ng\u1eafn g\u1ecdn), action (\"keep_urgent\"/\"keep\"/\"archive\"/\"trash\"), priority (\"high\"/\"medium\"/\"low\").\n\nCh\u1ec9 tr\u1ea3 JSON, kh\u00f4ng gi\u1ea3i th\u00edch th\u00eam.`;\n\nreturn [{ json: { prompt, emails_for_ai: emailsForAI, pre_data: data } }];"
},
"id": "prepare-ai-prompt",
"name": "\ud83e\udd16 Chu\u1ea9n B\u1ecb AI Prompt",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
960,
400
],
"notes": "Chu\u1ea9n b\u1ecb prompt t\u1ed1i \u01b0u cho AI. Ch\u1ec9 g\u1eedi email ch\u01b0a r\u00f5 r\u00e0ng, kh\u00f4ng g\u1eedi spam/promo \u0111\u00e3 bi\u1ebft."
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "skip-ai-check",
"leftValue": "={{ $json.skip_ai }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "if-need-ai",
"name": "IF: C\u1ea7n G\u1ecdi AI?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
1200,
400
],
"notes": "N\u1ebfu t\u1ea5t c\u1ea3 email \u0111\u00e3 \u0111\u01b0\u1ee3c pre-classify \u2192 b\u1ecf qua AI \u0111\u1ec3 ti\u1ebft ki\u1ec7m chi ph\u00ed."
},
{
"parameters": {
"method": "POST",
"url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent",
"authentication": "genericCredentialType",
"genericAuthType": "httpQueryAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"contents\": [{\n \"parts\": [{\n \"text\": \"{{ $json.prompt }}\"\n }]\n }],\n \"generationConfig\": {\n \"temperature\": 0.1,\n \"maxOutputTokens\": 2048\n }\n}",
"options": {}
},
"id": "call-gemini",
"name": "\ud83e\udde0 G\u1ecdi Gemini API",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1440,
300
],
"credentials": {
"httpQueryAuth": {
"name": "<your credential>"
}
},
"notes": "\u26a0\ufe0f SECURITY NOTE: D\u00f9ng HTTP Query credential v\u1edbi key=YOUR_API_KEY. KH\u00d4NG hardcode API key tr\u1ef1c ti\u1ebfp v\u00e0o URL. Credential \u0111\u01b0\u1ee3c m\u00e3 h\u00f3a trong n8n database. Demo: D\u00f9ng Gemini 1.5 Flash (mi\u1ec5n ph\u00ed tier)."
},
{
"parameters": {
"jsCode": "// Parse AI response v\u00e0 k\u1ebft h\u1ee3p v\u1edbi pre-classification\nconst aiResponse = $input.first().json;\nconst prevData = $('\ud83e\udd16 Chu\u1ea9n B\u1ecb AI Prompt').first().json;\n\nlet aiResults = [];\ntry {\n const rawText = aiResponse.candidates?.[0]?.content?.parts?.[0]?.text || '[]';\n const jsonMatch = rawText.match(/\\[.*\\]/s);\n if (jsonMatch) {\n aiResults = JSON.parse(jsonMatch[0]);\n }\n} catch(e) {\n console.error('AI parse error:', e.message);\n // Fallback: treat all AI emails as 'work'\n aiResults = (prevData.emails_for_ai || []).map((_, i) => ({\n index: i + 1, category: 'WORK', action: 'keep', priority: 'medium',\n reason_vi: 'Kh\u00f4ng th\u1ec3 ph\u00e2n t\u00edch'\n }));\n}\n\n// Combine AI results with email data\nconst emailsForAI = prevData.emails_for_ai || [];\nconst aiClassified = aiResults.map(r => ({\n ...emailsForAI[r.index - 1],\n category: r.category,\n action: r.action,\n priority: r.priority,\n reason: r.reason_vi,\n classified_by: 'ai'\n})).filter(Boolean);\n\n// Merge all classifications\nconst preData = prevData.pre_data;\nconst allEmails = [\n ...aiClassified,\n ...(preData.obvious_spam || []).map(e => ({ ...e, category: 'SPAM', action: 'trash', priority: 'low', classified_by: 'rule' })),\n ...(preData.obvious_promo || []).map(e => ({ ...e, category: 'PROMOTION', action: 'archive', priority: 'low', classified_by: 'rule' }))\n];\n\nconst grouped = {\n important: allEmails.filter(e => e.category === 'IMPORTANT'),\n work: allEmails.filter(e => e.category === 'WORK'),\n personal: allEmails.filter(e => e.category === 'PERSONAL'),\n newsletter: allEmails.filter(e => e.category === 'NEWSLETTER' || e.pre_category === 'newsletter'),\n promotion: allEmails.filter(e => e.category === 'PROMOTION' || e.pre_category === 'promotion'),\n spam: allEmails.filter(e => e.category === 'SPAM' || e.pre_category === 'spam')\n};\n\nreturn [{ json: { grouped, all: allEmails, total: preData.total || allEmails.length } }];"
},
"id": "parse-ai-result",
"name": "\ud83d\udd17 K\u1ebft H\u1ee3p K\u1ebft Qu\u1ea3 AI",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1680,
300
],
"notes": "Parse JSON t\u1eeb AI response v\u00e0 k\u1ebft h\u1ee3p v\u1edbi k\u1ebft qu\u1ea3 rule-based. C\u00f3 error handling khi AI tr\u1ea3 v\u1ec1 l\u1ed7i."
},
{
"parameters": {
"jsCode": "// Generate comprehensive Telegram report\nconst data = $input.first().json;\nconst { grouped, total } = data;\n\nconst dateStr = new Date().toLocaleDateString('vi-VN', {\n weekday: 'long', year: 'numeric', month: 'long', day: 'numeric',\n timeZone: 'Asia/Ho_Chi_Minh'\n});\n\nconst fmtSection = (arr, max = 3) => {\n if (!arr || arr.length === 0) return '_Kh\u00f4ng c\u00f3_';\n const items = arr.slice(0, max).map((e, i) => {\n const tag = e.classified_by === 'ai' ? '\ud83e\udd16' : '\u26a1';\n const reason = e.reason ? ` _(${e.reason})_` : '';\n return ` ${i+1}. *${(e.subject||'').substring(0, 50)}*${reason}\\n \ud83d\udce4 ${(e.from||'').substring(0, 38)} ${tag}`;\n }).join('\\n');\n const more = arr.length > max ? `\\n _... v\u00e0 ${arr.length - max} email kh\u00e1c_` : '';\n return items + more;\n};\n\n// Build priority section\nconst urgentEmails = (grouped.important || []).filter(e => e.priority === 'high');\nconst urgentSection = urgentEmails.length > 0\n ? `\\n\ud83d\udea8 *C\u1ea6N X\u1eec L\u00dd NGAY:*\\n${fmtSection(urgentEmails)}`\n : '';\n\nconst cleanupCount = (grouped.spam?.length || 0) + (grouped.promotion?.length || 0);\nconst toTrashIds = (grouped.spam || []).map(e => e.id).filter(Boolean);\nconst toArchiveIds = (grouped.promotion || []).map(e => e.id).filter(Boolean);\n\nconst mainReport = `\ud83e\udd16 *B\u00c1O C\u00c1O EMAIL AI - S\u00c1NG NAY*\n\ud83d\udcc5 ${dateStr}\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\n\ud83d\udcca *Th\u1ed1ng k\u00ea to\u00e0n b\u1ed9:*\n\u2022 \u2b50 Quan tr\u1ecdng: ${grouped.important?.length || 0} email\n\u2022 \ud83d\udcbc C\u00f4ng vi\u1ec7c: ${grouped.work?.length || 0} email\n\u2022 \ud83d\udc64 C\u00e1 nh\u00e2n: ${grouped.personal?.length || 0} email\n\u2022 \ud83d\udcf0 Newsletter: ${grouped.newsletter?.length || 0} email\n\u2022 \ud83c\udff7\ufe0f Khuy\u1ebfn m\u00e3i: ${grouped.promotion?.length || 0} email\n\u2022 \ud83d\uddd1\ufe0f Spam: ${grouped.spam?.length || 0} email\n\u2022 \ud83d\udce8 *T\u1ed5ng: ${total} email*\n${urgentSection}\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\n\u2b50 *QUAN TR\u1eccNG:*\n${fmtSection(grouped.important)}\n\n\ud83d\udcbc *C\u00d4NG VI\u1ec6C:*\n${fmtSection(grouped.work)}\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\ud83e\uddf9 T\u1ef1 \u0111\u1ed9ng d\u1ecdn: *${cleanupCount} email* (spam + promo)\n\ud83e\udd16 Ph\u00e2n t\u00edch b\u1edfi Gemini AI`;\n\nreturn [{ json: { mainReport, toTrashIds, toArchiveIds, grouped, total } }];"
},
"id": "format-ai-report",
"name": "\ud83d\udcca T\u1ea1o B\u00e1o C\u00e1o AI",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1920,
300
],
"notes": "Format b\u00e1o c\u00e1o \u0111\u1ea7y \u0111\u1ee7 v\u1edbi k\u1ebft qu\u1ea3 AI ph\u00e2n t\u00edch. Hi\u1ec3n th\u1ecb l\u00fd do ph\u00e2n lo\u1ea1i c\u1ee7a AI."
},
{
"parameters": {
"chatId": "={{ $vars.TELEGRAM_CHAT_ID }}",
"text": "={{ $json.mainReport }}",
"additionalFields": {
"parse_mode": "Markdown"
}
},
"id": "send-main-report",
"name": "\ud83d\udcf1 G\u1eedi B\u00e1o C\u00e1o Ch\u00ednh",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
2160,
200
],
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// Prepare spam IDs for trashing\nconst toTrashIds = $('\ud83d\udcca T\u1ea1o B\u00e1o C\u00e1o AI').first().json.toTrashIds || [];\nconst toArchiveIds = $('\ud83d\udcca T\u1ea1o B\u00e1o C\u00e1o AI').first().json.toArchiveIds || [];\n\nif (toTrashIds.length === 0 && toArchiveIds.length === 0) {\n return [{ json: { nothing_to_clean: true } }];\n}\n\nconst tasks = [\n ...toTrashIds.map(id => ({ emailId: id, action: 'trash' })),\n ...toArchiveIds.map(id => ({ emailId: id, action: 'archive' }))\n];\n\nconsole.log(`Cleanup tasks: ${tasks.length} (${toTrashIds.length} trash, ${toArchiveIds.length} archive)`);\nreturn tasks.map(t => ({ json: t }));"
},
"id": "prepare-cleanup",
"name": "\ud83e\uddf9 Chu\u1ea9n B\u1ecb D\u1ecdn D\u1eb9p",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2160,
400
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "is-trash",
"leftValue": "={{ $json.action }}",
"rightValue": "trash",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "if-trash-or-archive",
"name": "IF: Trash hay Archive?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
2400,
400
]
},
{
"parameters": {
"resource": "message",
"operation": "trash",
"messageId": "={{ $json.emailId }}",
"options": {}
},
"id": "trash-email",
"name": "\ud83d\uddd1\ufe0f X\u00f3a Spam",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
2640,
300
],
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"notes": "\u26a0\ufe0f TH\u1eacN TR\u1eccNG: X\u00f3a email v\u00e0o Th\u00f9ng r\u00e1c. C\u1ea7n test k\u1ef9 tr\u01b0\u1edbc khi d\u00f9ng production."
},
{
"parameters": {
"resource": "message",
"operation": "archive",
"messageId": "={{ $json.emailId }}",
"options": {}
},
"id": "archive-promo",
"name": "\ud83d\udcc1 Archive Promo",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
2640,
500
],
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "const results = $input.all();\nconst report = $('\ud83d\udcca T\u1ea1o B\u00e1o C\u00e1o AI').first().json;\n\nconsole.log(`\u2705 V3 AI Pro completed: ${report.total} emails processed`);\nconsole.log(`\ud83d\uddd1\ufe0f Trashed: ${report.toTrashIds?.length || 0}`);\nconsole.log(`\ud83d\udcc1 Archived: ${report.toArchiveIds?.length || 0}`);\n\nreturn [{\n json: {\n status: 'completed',\n workflow_version: 'v3-ai-pro',\n total_processed: report.total,\n trashed: report.toTrashIds?.length || 0,\n archived: report.toArchiveIds?.length || 0,\n finished_at: new Date().toISOString()\n }\n}];"
},
"id": "final-log",
"name": "\u2705 Log Ho\u00e0n T\u1ea5t",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2880,
400
]
},
{
"parameters": {
"resource": "message",
"operation": "getAll",
"returnAll": false,
"limit": 5,
"filters": {
"q": "is:unread newer_than:1d label:IMPORTANT"
},
"options": {}
},
"id": "gmail-check-important",
"name": "\u2b50 Check Gmail Important Label",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
1440,
700
],
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"notes": "Ch\u1ea1y song song: L\u1ea5y email Gmail \u0111\u00e3 \u0111\u00e1nh d\u1ea5u Important \u0111\u1ec3 b\u1ed5 sung v\u00e0o b\u00e1o c\u00e1o."
}
],
"connections": {
"\u23f0 Trigger 7h S\u00e1ng": {
"main": [
[
{
"node": "\ud83d\udcec L\u1ea5y Email (100)",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udcec L\u1ea5y Email (100)": {
"main": [
[
{
"node": "\ud83d\udd0d Pre-Classification (Rule-Based)",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udd0d Pre-Classification (Rule-Based)": {
"main": [
[
{
"node": "\ud83e\udd16 Chu\u1ea9n B\u1ecb AI Prompt",
"type": "main",
"index": 0
}
]
]
},
"\ud83e\udd16 Chu\u1ea9n B\u1ecb AI Prompt": {
"main": [
[
{
"node": "IF: C\u1ea7n G\u1ecdi AI?",
"type": "main",
"index": 0
}
]
]
},
"IF: C\u1ea7n G\u1ecdi AI?": {
"main": [
[
{
"node": "\ud83d\udcca T\u1ea1o B\u00e1o C\u00e1o AI",
"type": "main",
"index": 0
}
],
[
{
"node": "\ud83e\udde0 G\u1ecdi Gemini API",
"type": "main",
"index": 0
}
]
]
},
"\ud83e\udde0 G\u1ecdi Gemini API": {
"main": [
[
{
"node": "\ud83d\udd17 K\u1ebft H\u1ee3p K\u1ebft Qu\u1ea3 AI",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udd17 K\u1ebft H\u1ee3p K\u1ebft Qu\u1ea3 AI": {
"main": [
[
{
"node": "\ud83d\udcca T\u1ea1o B\u00e1o C\u00e1o AI",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udcca T\u1ea1o B\u00e1o C\u00e1o AI": {
"main": [
[
{
"node": "\ud83d\udcf1 G\u1eedi B\u00e1o C\u00e1o Ch\u00ednh",
"type": "main",
"index": 0
}
],
[
{
"node": "\ud83e\uddf9 Chu\u1ea9n B\u1ecb D\u1ecdn D\u1eb9p",
"type": "main",
"index": 0
}
]
]
},
"\ud83e\uddf9 Chu\u1ea9n B\u1ecb D\u1ecdn D\u1eb9p": {
"main": [
[
{
"node": "IF: Trash hay Archive?",
"type": "main",
"index": 0
}
]
]
},
"IF: Trash hay Archive?": {
"main": [
[
{
"node": "\ud83d\uddd1\ufe0f X\u00f3a Spam",
"type": "main",
"index": 0
}
],
[
{
"node": "\ud83d\udcc1 Archive Promo",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\uddd1\ufe0f X\u00f3a Spam": {
"main": [
[
{
"node": "\u2705 Log Ho\u00e0n T\u1ea5t",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udcc1 Archive Promo": {
"main": [
[
{
"node": "\u2705 Log Ho\u00e0n T\u1ea5t",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1",
"saveManualExecutions": true,
"saveExecutionProgress": true,
"timezone": "Asia/Ho_Chi_Minh"
},
"tags": [
"personal",
"gmail",
"telegram",
"daily-report",
"v3-ai-pro",
"gemini",
"spam-cleanup"
],
"meta": {
"usage": "V3 AI PRO: 13 nodes. AI ph\u00e2n t\u00edch + b\u00e1o c\u00e1o th\u00f4ng minh + t\u1ef1 \u0111\u1ed9ng d\u1ecdn d\u1eb9p.",
"difficulty": "\u2b50\u2b50\u2b50\u2b50 Advanced",
"nodes_count": 13,
"setup_time": "60 ph\u00fat",
"ai_model": "Gemini 1.5 Flash (free tier)",
"security_notes": "API key d\u00f9ng n8n credential, kh\u00f4ng hardcode. Spam filter c\u1ea9n th\u1eadn \u0111\u1ec3 tr\u00e1nh x\u00f3a nh\u1ea7m."
}
}
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.
gmailOAuth2httpQueryAuthtelegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Gmail → Telegram Daily Report (V3 AI Pro). Uses gmail, httpRequest, telegram. Scheduled trigger; 15 nodes.
Source: https://github.com/congdinh2008/n8n-compose/blob/88a5ccac9ba7441519c42e9dd9b9b31e45baf125/workflows/personal/09-gmail-telegram-report/v3-ai-pro/workflow.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Template - SSL Expiry Alert System. Uses googleSheets, scheduleTrigger, httpRequest, stickyNote. Scheduled trigger; 21 nodes.
[](https://www.youtube.com/watch?v=q4d404G_OxY)
This workflow is ideal for administrators or IT professionals responsible for monitoring SSL certificates of multiple websites to ensure they do not expire unexpectedly.
url-uptime-monitor. Uses scheduleTrigger, splitOut, googleSheets, summarize. Scheduled trigger; 18 nodes.
MPE Kleinanzeigen Unified (Reminder + Poster). Uses gmail, httpRequest, telegram, googleSheets. Scheduled trigger; 15 nodes.