This workflow corresponds to n8n.io template #16590 — we link there as the canonical source.
This workflow follows the Emailsend → 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 →
{
"id": "wVpp9YLObaM3cm6J",
"name": "Send Microsoft 365 update digest via email with GPT-4o-mini",
"tags": [
{
"id": "xd5YuFsLIjvmlw1t",
"name": "Microsoft 365",
"createdAt": "2026-06-17T16:42:09.743Z",
"updatedAt": "2026-06-17T16:42:09.743Z"
},
{
"id": "QltqSrgshppJS0Mr",
"name": "Monitoring",
"createdAt": "2026-06-17T16:42:09.772Z",
"updatedAt": "2026-06-17T16:42:09.772Z"
},
{
"id": "wQki9FdAO0HBNZ6A",
"name": "Email",
"createdAt": "2026-06-17T16:42:09.798Z",
"updatedAt": "2026-06-17T16:42:09.798Z"
}
],
"nodes": [
{
"id": "6eddbad2-c2ed-48fb-beaa-4d7171a7f3ef",
"name": "Sticky Note - Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
-928,
64
],
"parameters": {
"width": 776,
"height": 924,
"content": "## \ud83d\udccb Send Microsoft 365 update digest via email with GPT-4o-mini\n\n**Who's it for**\nIT admins, M365 administrators, and helpdesk teams who need to stay on top of Microsoft 365 changes without manually checking multiple blogs every day.\n\n**What it does / How it works**\nThis workflow runs every morning and checks the official Microsoft Tech Community blogs for the M365 core service, Security & Compliance, and Teams/Roadmap boards. It pulls the latest posts from each RSS feed, keeps only items published in the last 24 hours, and removes duplicate titles across the three feeds. If new items are found, it bundles them into a single text block and sends it to GPT-4o-mini, which scores each update by priority (Critical/High/Medium/Low), category, and whether action is required, then writes a clean HTML summary. That summary is emailed to your IT team. If nothing new was published, a short \"no updates\" email is sent instead, so you always know the workflow ran.\n\n**How to set up**\n1. Add an OpenAI credential (HTTP Header Auth, `Authorization: Bearer sk-...`) to the GPT-4o-mini node.\n2. Add an SMTP credential to both email nodes.\n3. Update the `fromEmail` and `toEmail` fields to your own addresses.\n4. Confirm the RSS URLs below are still valid \u2014 Microsoft has changed TechCommunity feed paths before.\n\n**Requirements**\n- An OpenAI API key with access to GPT-4o-mini\n- An SMTP account for sending email\n\n**How to customize**\n- Change the schedule trigger to run at a different time.\n- Add or remove RSS feed sources to track other Microsoft blogs.\n- Edit the GPT-4o-mini system prompt to change the prioritization logic or HTML layout."
},
"typeVersion": 1
},
{
"id": "47403582-bd10-4d5a-81b4-443c2826b6b5",
"name": "Sticky Note - Trigger",
"type": "n8n-nodes-base.stickyNote",
"position": [
-112,
416
],
"parameters": {
"color": 4,
"width": 220,
"height": 348,
"content": "\u23f0 **Trigger**\nRuns every day at 07:00.\nEdit the cron expression to change the schedule."
},
"typeVersion": 1
},
{
"id": "74b42822-beed-4050-a0bb-89ea669924df",
"name": "Sticky Note - RSS Feeds",
"type": "n8n-nodes-base.stickyNote",
"position": [
144,
192
],
"parameters": {
"color": 5,
"width": 220,
"height": 764,
"content": "\ud83d\udce1 **Fetch RSS Feeds**\nPulls the latest posts from 3 official Microsoft Tech Community boards in parallel:\n\u2022 M365 Blog\n\u2022 Security & Compliance\n\u2022 Teams / Roadmap"
},
"typeVersion": 1
},
{
"id": "e954ad87-e6c9-447e-9521-a6b34f73ab9b",
"name": "Sticky Note - Parse",
"type": "n8n-nodes-base.stickyNote",
"position": [
384,
192
],
"parameters": {
"color": 3,
"width": 220,
"height": 604,
"content": "\ud83d\udd0d **Parse & Deduplicate**\nExtracts each RSS item, keeps only posts from the last 24h, and removes duplicate titles across the 3 feeds."
},
"typeVersion": 1
},
{
"id": "0bfbbe22-53b4-4d73-82fd-93892eeac24c",
"name": "Sticky Note - Decision",
"type": "n8n-nodes-base.stickyNote",
"position": [
608,
192
],
"parameters": {
"color": 6,
"width": 220,
"height": 604,
"content": "\u2753 **Any New Items?**\nNo new posts \u2192 fallback email.\nNew posts found \u2192 continue to AI analysis."
},
"typeVersion": 1
},
{
"id": "8eb8fa51-78a4-49e5-b5ae-75a209ec2b8f",
"name": "Sticky Note - No Update Email",
"type": "n8n-nodes-base.stickyNote",
"position": [
832,
704
],
"parameters": {
"color": 3,
"width": 220,
"height": 340,
"content": "\n\n\n\n\n\n\n\n\n\n **No Updates \u2013 Fallback**\nSent only when nothing new was published in the last 24 hours."
},
"typeVersion": 1
},
{
"id": "6f0a5d58-2ae1-45d9-9585-01a227a0ec98",
"name": "Sticky Note - Aggregate",
"type": "n8n-nodes-base.stickyNote",
"position": [
832,
208
],
"parameters": {
"color": 4,
"width": 200,
"height": 468,
"content": "\ud83e\udde9 **Aggregate**\nFormats every item into a single numbered text block ready to hand to the AI model."
},
"typeVersion": 1
},
{
"id": "74cd37f5-85de-42ff-bc62-df4a510170ce",
"name": "Sticky Note - AI Analysis",
"type": "n8n-nodes-base.stickyNote",
"position": [
1040,
208
],
"parameters": {
"color": 2,
"width": 220,
"height": 468,
"content": "\ud83e\udd16 **AI Triage (GPT-4o-mini)**\nScores each update \u2014 Priority, Category, Action Required, IT Impact \u2014 and writes the HTML email body.\n\n\u26a0\ufe0f Needs an OpenAI API key (HTTP Header Auth credential)."
},
"typeVersion": 1
},
{
"id": "7d8a7e2d-6f08-497d-8d3d-6f6076cafb01",
"name": "Sticky Note - Send Email",
"type": "n8n-nodes-base.stickyNote",
"position": [
1264,
208
],
"parameters": {
"color": 4,
"width": 220,
"height": 468,
"content": "\ud83d\udce7 **Send Digest**\nDelivers the final HTML email via SMTP.\n\u26a0\ufe0f Needs an SMTP credential + updated from/to addresses."
},
"typeVersion": 1
},
{
"id": "c398e540-ff6d-4566-b11e-a9369cc5e47a",
"name": "Daily at 07:00",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-48,
624
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 7 * * *"
}
]
}
},
"typeVersion": 1.1
},
{
"id": "239e31d6-92f8-4a18-9393-05d697fc961e",
"name": "RSS: M365 Blog",
"type": "n8n-nodes-base.httpRequest",
"position": [
192,
480
],
"parameters": {
"url": "https://techcommunity.microsoft.com/plugins/custom/microsoft/o365/custom-blog-rss?board=Microsoft365Blog",
"options": {
"timeout": 15000
}
},
"typeVersion": 4.1
},
{
"id": "3fc6e6a9-ba4e-4be3-ab48-e1f4c6f68dc2",
"name": "RSS: Security & Compliance",
"type": "n8n-nodes-base.httpRequest",
"position": [
192,
624
],
"parameters": {
"url": "https://techcommunity.microsoft.com/plugins/custom/microsoft/o365/custom-blog-rss?board=SecurityComplianceIdentity",
"options": {
"timeout": 15000
}
},
"typeVersion": 4.1
},
{
"id": "caee2a37-de4a-402f-a655-bc8e8d923d11",
"name": "RSS: M365 Roadmap Blog",
"type": "n8n-nodes-base.httpRequest",
"position": [
192,
752
],
"parameters": {
"url": "https://techcommunity.microsoft.com/plugins/custom/microsoft/o365/custom-blog-rss?board=MicrosoftTeamsBlog",
"options": {
"timeout": 15000
}
},
"typeVersion": 4.1
},
{
"id": "8aefbb94-726a-46db-bbc5-b342a0ac3341",
"name": "Parse & Deduplicate RSS",
"type": "n8n-nodes-base.code",
"position": [
432,
624
],
"parameters": {
"jsCode": "// Parse XML RSS feed and extract items from last 24 hours\nconst items = [];\nconst cutoff = new Date(Date.now() - 24 * 60 * 60 * 1000);\n\nfor (const input of $input.all()) {\n const body = input.json.data || '';\n const source = input.json.url || 'Unknown';\n\n // Extract <item> blocks\n const itemRegex = /<item[^>]*>([\\s\\S]*?)<\\/item>/gi;\n let match;\n while ((match = itemRegex.exec(body)) !== null) {\n const block = match[1];\n const get = (tag) => {\n const r = new RegExp(`<${tag}[^>]*><!\\\\[CDATA\\\\[([\\\\s\\\\S]*?)\\\\]\\\\]><\\/${tag}>|<${tag}[^>]*>([\\\\s\\\\S]*?)<\\/${tag}>`, 'i');\n const m = r.exec(block);\n return m ? (m[1] || m[2] || '').trim() : '';\n };\n\n const title = get('title');\n const link = get('link');\n const pubDate = get('pubDate');\n const description = get('description').replace(/<[^>]+>/g, '').substring(0, 300);\n const category = get('category');\n\n if (!title) continue;\n\n let published = pubDate ? new Date(pubDate) : null;\n if (published && published < cutoff) continue; // skip items older than 24h\n\n items.push({\n json: {\n title,\n link,\n pubDate: published ? published.toISOString() : 'Unknown',\n description,\n category,\n source\n }\n });\n }\n}\n\n// Deduplicate by title\nconst seen = new Set();\nconst unique = items.filter(i => {\n if (seen.has(i.json.title)) return false;\n seen.add(i.json.title);\n return true;\n});\n\nif (unique.length === 0) {\n return [{ json: { noItems: true, message: 'No new M365 updates in the last 24 hours.' } }];\n}\n\nreturn unique;"
},
"typeVersion": 2
},
{
"id": "f15fef79-8222-49ca-ba82-ebbfc8e3933a",
"name": "Any Items?",
"type": "n8n-nodes-base.if",
"position": [
656,
624
],
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $json.noItems }}",
"value2": true
}
]
}
},
"typeVersion": 1
},
{
"id": "e132cd7a-d220-4746-9a72-f5b40423a69d",
"name": "Aggregate Items",
"type": "n8n-nodes-base.code",
"position": [
864,
512
],
"parameters": {
"jsCode": "// Aggregate all items into one object for AI analysis\nconst allItems = $input.all().map(i => i.json);\n\nconst formatted = allItems.map((item, idx) => \n `[${idx + 1}] ${item.title}\\nSource: ${item.source}\\nDate: ${item.pubDate}\\nSummary: ${item.description}\\nURL: ${item.link}`\n).join('\\n\\n---\\n\\n');\n\nreturn [{\n json: {\n itemCount: allItems.length,\n formattedItems: formatted,\n rawItems: allItems\n }\n}];"
},
"typeVersion": 2
},
{
"id": "b661f874-bad0-4a60-be13-e0a538715443",
"name": "GPT-4o-mini: Analyze & Format",
"type": "n8n-nodes-base.httpRequest",
"position": [
1088,
512
],
"parameters": {
"url": "https://api.openai.com/v1/chat/completions",
"method": "POST",
"options": {
"timeout": 60000
},
"jsonBody": "={\n \"model\": \"gpt-4o-mini\",\n \"temperature\": 0.2,\n \"max_tokens\": 3000,\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"You are an IT analyst specializing in Microsoft 365. Analyze M365 updates and produce a structured daily digest for the IT team.\\n\\nFor each update assess:\\n- Priority: CRITICAL / HIGH / MEDIUM / LOW\\n- Category: Security | Compliance | Feature Change | Deprecation | New Feature | Maintenance\\n- Action Required: Yes / No\\n- Brief IT Impact (1 sentence)\\n\\nProduce a clean HTML email body with:\\n1. Summary header with date and total count\\n2. CRITICAL/HIGH section highlighted in red/orange (if any)\\n3. MEDIUM/LOW section\\n4. Each item: Title, Priority badge, Category, Action Required, Impact, Link\\n\\nUse inline CSS only. Return ONLY the HTML body content, no <html> or <body> tags.\"\n },\n {\n \"role\": \"user\",\n \"content\": \"Analyze these {{ $json.itemCount }} Microsoft 365 updates from the last 24 hours and produce the HTML digest:\\n\\n{{ $json.formattedItems }}\"\n }\n ]\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.1
},
{
"id": "53046255-7f1d-44f9-8083-edd6b8bbe6ea",
"name": "Send Email Digest",
"type": "n8n-nodes-base.emailSend",
"position": [
1312,
512
],
"parameters": {
"options": {},
"subject": "=\ud83d\udccb M365 Daily Update Digest \u2013 {{ $now.format('dd MMM yyyy') }}",
"toEmail": "user@example.com",
"fromEmail": "user@example.com"
},
"typeVersion": 2.1
},
{
"id": "eb0625a1-a7c9-40e8-b288-19a9e88cda96",
"name": "Send No-Update Email",
"type": "n8n-nodes-base.emailSend",
"position": [
864,
752
],
"parameters": {
"options": {},
"subject": "=\ud83d\udccb M365 Daily Digest \u2013 {{ $now.format('dd MMM yyyy') }} \u2013 No New Updates",
"toEmail": "user@example.com",
"fromEmail": "user@example.com"
},
"typeVersion": 2.1
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"executionOrder": "v1"
},
"versionId": "bc8cf650-9eb0-49cd-b53f-1ea5c5c7c06d",
"nodeGroups": [],
"connections": {
"Any Items?": {
"main": [
[
{
"node": "Send No-Update Email",
"type": "main",
"index": 0
}
],
[
{
"node": "Aggregate Items",
"type": "main",
"index": 0
}
]
]
},
"Daily at 07:00": {
"main": [
[
{
"node": "RSS: M365 Blog",
"type": "main",
"index": 0
},
{
"node": "RSS: Security & Compliance",
"type": "main",
"index": 0
},
{
"node": "RSS: M365 Roadmap Blog",
"type": "main",
"index": 0
}
]
]
},
"RSS: M365 Blog": {
"main": [
[
{
"node": "Parse & Deduplicate RSS",
"type": "main",
"index": 0
}
]
]
},
"Aggregate Items": {
"main": [
[
{
"node": "GPT-4o-mini: Analyze & Format",
"type": "main",
"index": 0
}
]
]
},
"RSS: M365 Roadmap Blog": {
"main": [
[
{
"node": "Parse & Deduplicate RSS",
"type": "main",
"index": 0
}
]
]
},
"Parse & Deduplicate RSS": {
"main": [
[
{
"node": "Any Items?",
"type": "main",
"index": 0
}
]
]
},
"RSS: Security & Compliance": {
"main": [
[
{
"node": "Parse & Deduplicate RSS",
"type": "main",
"index": 0
}
]
]
},
"GPT-4o-mini: Analyze & Format": {
"main": [
[
{
"node": "Send Email Digest",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow runs daily at 07:00 to pull the latest Microsoft 365, Security & Compliance, and Teams blog RSS posts, uses OpenAI (gpt-4o-mini) to triage and format a prioritized HTML digest, and sends the results to your team via SMTP email. Runs every day at 07:00 on a…
Source: https://n8n.io/workflows/16590/ — 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.
This n8n workflow automatically fetches monthly financial statements, normalizes the data, performs KPI calculations and trend analysis, detects anomalies, generates AI-powered executive insights and
Who is this for? Event organizers losing 80% of form starters who never finish registration and want automated follow-up emails triggered by abandonment beacons. What problem is this workflow solving?
n8n_email_diario_sem_ollama_fixed. Uses httpRequest, emailSend. Scheduled trigger; 10 nodes.
Weekly Documentation Update. Uses executeCommand, httpRequest, emailSend. Scheduled trigger; 8 nodes.
Daily Email Summary Workflow. Uses httpRequest, emailSend. Scheduled trigger; 5 nodes.