

How to Forward Gmail Meeting Emails to Slack with n8n
Polls Gmail for emails containing meeting notes or action items, classifies them by type, and routes them to the correct Slack channel automatically.
Steps and UI details are based on platform versions at time of writing — check each platform for the latest interface.
Best for
Small-to-mid teams where external meeting confirmations and follow-ups land in one inbox but need to reach multiple Slack channels by topic or project.
Not ideal for
Teams using a shared inbox tool like Front or Missive — those have native Slack routing built in and n8n adds unnecessary complexity.
Sync type
scheduledUse case type
notificationReal-World Example
A 20-person consulting firm has one partner who handles all external client meetings — confirmations, recaps, and action items all land in their Gmail. Before this workflow, they forwarded emails manually to #client-updates in Slack, which happened inconsistently and sometimes days late. Now n8n polls Gmail every 5 minutes, detects meeting-related emails using subject-line keywords, and posts a formatted Slack message to the right channel within minutes of arrival.
What Will This Cost?
Drag the slider to your expected monthly volume.
Each platform counts differently — Zapier: 1 task per trigger. Make: 1 operation per module per record. n8n: 1 execution per run.





Prices shown for annual billing. Based on published pricing as of April 2026.
Estimated ROI
1000
min saved/mo
$583
labor value/mo
Free
no platform cost
Based on ~2 min manual effort per operation at $35/hr fully loaded labor cost.
Implementation
Import this workflow directly into n8n
Copy the pre-built n8n blueprint and paste it straight into n8n. All modules, filters, and field mappings are already configured — you just need to connect your accounts.
Before You Start
Make sure you have everything ready.
Optional
Field Mapping
Map these fields between your apps.
| Field | API Name | |
|---|---|---|
| Required | ||
| Email Subject | ||
| Sender Name | ||
| Sender Email | ||
| Email Body (Plain Text) | ||
| Received Date | ||
| Gmail Message ID | ||
| Meeting Type | ||
| Target Slack Channel | ||
1 optional field▸ show
| Email Thread ID |
Step-by-Step Setup
n8n Dashboard > Workflows > New Workflow
Create a new workflow in n8n
Log into your n8n instance (cloud at app.n8n.io or self-hosted). Click the orange 'New Workflow' button in the top-right corner of the Workflows dashboard. Give it a clear name like 'Gmail → Slack Meeting Distributor' — this matters when you're debugging later. You'll land on a blank canvas with a single gray 'Start' node.
- 1Click 'New Workflow' in the top-right corner
- 2Click the workflow name at the top and rename it to 'Gmail → Slack Meeting Distributor'
- 3Press Enter to save the name
Canvas > Add Node > Gmail > Trigger
Add and configure the Gmail trigger node
Click the gray Start node and search for 'Gmail'. Select the Gmail node and choose 'Trigger' mode. Set the operation to 'Message Received'. n8n will poll your Gmail inbox on the schedule you define in Step 3. Connect your Google account by clicking 'Create new credential' — you'll need to authorize Gmail access via OAuth2.
- 1Click the '+' icon on the canvas or on the Start node
- 2Type 'Gmail' in the search bar and select it
- 3Set 'Operation' to 'Message Received'
- 4Click 'Create new credential' under the Credential dropdown
- 5Sign in with your Google account and grant Gmail read access
Gmail Node > Parameters > Poll Times + Filters
Set polling interval and label filter
Inside the Gmail trigger node, set the 'Poll Times' field to every 5 minutes — this gives near-real-time delivery without hammering the Gmail API. Under 'Filters', add a label filter if you use Gmail labels for external meetings (e.g., 'external-meetings'). If you rely on subject keywords instead, leave the label field blank and you'll handle filtering in Step 5.
- 1Click the 'Poll Times' field and select 'Every 5 Minutes'
- 2Expand the 'Filters' section
- 3Set 'Label Names or IDs' to your meeting label, or leave blank to filter by keyword later
- 4Check 'Return All' is set to false — you want only new messages per poll
Gmail Node > Test Step button
Test the Gmail trigger with a real email
Click 'Test Step' on the Gmail node. n8n will immediately pull recent emails from your inbox matching your filter. You need at least one real meeting-related email in your inbox for the test data to be useful — send yourself a test email with a subject like 'Re: Project Kickoff Meeting Notes' before running this step. Look at the output panel on the right and expand one email item to see its structure.
- 1Send a test email to your Gmail with subject 'Re: Project Kickoff Meeting Notes'
- 2Click 'Test Step' on the Gmail node
- 3Expand the output item in the right panel
- 4Note the field paths for subject, snippet, from, and body fields
Canvas > Add Node > IF
Add an IF node to filter for meeting-related emails
Not every email in your inbox is a meeting follow-up. Add an IF node after the Gmail trigger to check whether the subject line contains relevant keywords. This prevents noise from being posted to Slack. You'll build a multi-condition check using OR logic across keywords like 'meeting', 'action items', 'follow-up', 'recap', and 'notes'.
- 1Click the '+' after the Gmail trigger node and search for 'IF'
- 2Set Condition 1: 'String' | '{{ $json.subject }}' | 'Contains' | 'meeting'
- 3Click 'Add Condition' and set Condition 2: subject Contains 'action items'
- 4Add Condition 3: subject Contains 'follow-up'
- 5Add Condition 4: subject Contains 'recap'
- 6Set the 'Combine' dropdown to 'OR'
Canvas > Add Node > Code
Add a Code node to classify and extract meeting data
After the true branch of the IF node, add a Code node. This is where n8n earns its place — you can write JavaScript to extract the sender name, detect the meeting type from the subject, strip HTML from the email body, and assign a target Slack channel based on keywords. This single node replaces 4-5 manual routing steps you'd need in Zapier.
- 1Click '+' after the IF node's true output
- 2Search for 'Code' and select it
- 3Set 'Language' to 'JavaScript'
- 4Paste the classification code from the Pro Tip section below
- 5Click 'Test Step' to verify output fields
Paste this into the Code node (Step 6) that sits after your IF filter node. It strips HTML from the email body, detects meeting type from subject keywords, assigns the correct Slack channel, and formats the sender name — all in one pass. The $input.all() call pulls every email that passed the IF filter in the current execution.
JavaScript — Code Node// n8n Code Node — Meeting Classification & Data Prep▸ Show code
// n8n Code Node — Meeting Classification & Data Prep // Place after the IF filter node, before the Slack node const items = $input.all();
... expand to see full code
// n8n Code Node — Meeting Classification & Data Prep
// Place after the IF filter node, before the Slack node
const items = $input.all();
const results = [];
// Map meeting types to Slack channels — update these to match your workspace
const channelMap = {
'action items': '#action-items',
'follow-up': '#follow-ups',
'follow up': '#follow-ups',
'recap': '#meeting-recaps',
'notes': '#meeting-recaps',
'confirmation': '#external-meetings',
'confirmed': '#external-meetings',
'meeting request': '#external-meetings',
'default': '#general-meetings'
};
for (const item of items) {
const email = item.json;
// --- 1. Strip HTML from body ---
const rawBody = email.text || email.snippet || '';
const cleanBody = rawBody
.replace(/<[^>]*>/g, ' ')
.replace(/ /g, ' ')
.replace(/&/g, '&')
.replace(/\s+/g, ' ')
.trim()
.substring(0, 500);
// --- 2. Extract sender name from 'from' field ---
// Gmail 'from' field is usually: "First Last <[email protected]>"
const fromRaw = email.from || '';
const nameMatch = fromRaw.match(/^([^<]+)/);
const senderName = nameMatch ? nameMatch[1].trim() : fromRaw;
const emailMatch = fromRaw.match(/<([^>]+)>/);
const senderEmail = emailMatch ? emailMatch[1] : fromRaw;
// --- 3. Classify meeting type by subject keyword ---
const subject = (email.subject || '').toLowerCase();
let meetingType = 'General Meeting';
let targetChannel = channelMap['default'];
for (const [keyword, channel] of Object.entries(channelMap)) {
if (keyword !== 'default' && subject.includes(keyword)) {
targetChannel = channel;
meetingType = keyword
.split(' ')
.map(w => w.charAt(0).toUpperCase() + w.slice(1))
.join(' ');
break;
}
}
// --- 4. Format received date ---
const rawDate = email.date || email.internalDate || '';
let formattedDate = 'Unknown date';
if (rawDate) {
const d = new Date(isNaN(rawDate) ? rawDate : parseInt(rawDate));
formattedDate = d.toLocaleString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric',
hour: 'numeric',
minute: '2-digit',
hour12: true
});
}
// --- 5. Build Slack message text ---
const emoji = meetingType.includes('Confirmation') ? '📅' : '📋';
const slackMessage = [
`${emoji} *${meetingType}* from ${senderName} (${senderEmail})`,
`*Subject:* ${email.subject}`,
`*Received:* ${formattedDate}`,
'',
cleanBody
].join('\n');
results.push({
json: {
...email,
senderName,
senderEmail,
cleanBody,
meetingType,
targetChannel,
formattedDate,
slackMessage,
messageId: email.id
}
});
}
return results;Canvas > Add Node > Slack > Send Message
Add the Slack node and configure message formatting
Add a Slack node after the Code node. Set the operation to 'Send Message'. In the 'Channel' field, use the dynamic value from your Code node output: '{{ $json.targetChannel }}'. This is what routes the message to the right Slack channel per email. Build the message text using Slack's Block Kit or a simple formatted string combining sender, subject, date, and a clipped body preview.
- 1Click '+' after the Code node and search for 'Slack'
- 2Select 'Send Message' as the operation
- 3Connect your Slack workspace by clicking 'Create new credential' and authorizing via OAuth2
- 4Set 'Channel' to '{{ $json.targetChannel }}'
- 5Set 'Message Text' to the formatted template (see field mapping section)
channel: {{channel}}
ts: {{ts}}
Canvas > Test Workflow button (top bar)
Test end-to-end with a real meeting email
Click 'Test Workflow' at the top of the canvas. n8n will run all nodes in sequence using real data. Watch each node light up green as it executes. Check the Slack channel you targeted — the message should appear within seconds of the test completing. Click each node's output panel to verify the data transformation happened correctly at each stage.
- 1Click 'Test Workflow' in the top toolbar
- 2Watch each node turn green as execution proceeds
- 3Open your target Slack channel and confirm the message arrived
- 4Click the Code node output panel to verify 'targetChannel' mapped correctly
- 5Click the Slack node output panel to confirm 'ok: true' in the response
Canvas > Three-dot menu > Settings > Error Workflow
Add an error handler for failed Slack posts
Real workflows fail. Add an Error Trigger node connected to a second Slack node that posts to a dedicated #automation-errors channel when the main workflow breaks. In n8n, click the three-dot menu on the workflow canvas and toggle 'Error Workflow'. Create a second minimal workflow with an Error Trigger that sends the error message and node name to your monitoring channel.
- 1Click the three-dot menu at the top of the canvas
- 2Select 'Settings'
- 3Under 'Error Workflow', click 'Select Workflow' and create or select an error-handling workflow
- 4In that error workflow, add an Error Trigger node and a Slack node posting to #automation-errors
Canvas > Active/Inactive toggle (top right)
Activate the workflow
Click the 'Inactive' toggle in the top-right corner of the canvas to switch it to 'Active'. n8n will immediately begin polling Gmail every 5 minutes according to your schedule. The workflow is now live. Leave the canvas — it runs independently in the background.
- 1Click the gray 'Inactive' toggle in the top-right corner
- 2Confirm the dialog if prompted
- 3Watch the toggle turn green and read 'Active'
- 4Navigate to the Executions tab to monitor the first few runs
Going live
Production Checklist
Before you turn this on for real, confirm each item.
Troubleshooting
Common errors and how to fix them.
Frequently Asked Questions
Common questions about this workflow.
Analysis
Use n8n for this if your team is already self-hosting or on n8n Cloud and someone on the team can read JavaScript. The keyword classification and HTML stripping you need for this workflow require real code — n8n's Code node handles it in one step. You also get full control over deduplication logic, which matters here because Gmail polling without deduplication will repost the same emails after any workflow reset. If nobody on your team touches code and you just need a basic 'email arrives → Slack message' without smart routing, use Zapier — the Gmail New Email trigger and Slack Send Message action are 10-minute setup with no code required.
Cost math: n8n Cloud's Starter plan is $20/month and includes 2,500 executions. This workflow uses 1 execution per email processed. A team receiving 20 meeting-related emails per day generates 600 executions/month — well within the Starter tier. At 100 meeting emails/day (3,000/month), you'd need the Pro plan at $50/month. Self-hosted n8n is free indefinitely at any volume, and this workflow's lightweight JS won't stress a basic $6/month VPS. Zapier's equivalent would cost $19.99/month for 750 tasks — cheaper at low volume, but Zapier can't do the routing logic without 3-4 extra Zaps eating into your task count fast.
Make handles multi-branch routing with its Router module natively, which is slightly cleaner than n8n's IF node for this use case — you'd build one branch per meeting type with no code required. Zapier's Gmail trigger is faster to configure but the routing requires Paths, which is a paid feature and costs tasks per branch. Power Automate has a solid Gmail connector via third-party but native support is through Outlook — if your team is Microsoft-first, the Outlook + Teams version of this workflow is better than forcing Gmail into Power Automate. Pipedream's Gmail source fires on actual Gmail push notifications via Google Pub/Sub, which means true real-time delivery instead of polling — if sub-minute latency matters, Pipedream is genuinely better here. n8n wins on total control and cost at mid-volume, but acknowledge Pipedream's edge on latency.
Three things you'll hit after go-live. First: Gmail's API returns email bodies in base64-encoded MIME parts for full message fetches — the snippet field is plain text and safe to use, but if you switch to fetching full bodies, you'll need to decode them with Buffer.from(part.body.data, 'base64').toString('utf-8') in your Code node. Second: Google's OAuth refresh tokens silently expire if your consent screen stays in Testing mode — you won't get an error email, the workflow just stops processing and shows credential failures in the Executions log. Third: Slack's rate limit for the chat.postMessage API is 1 request per second per channel. If a batch of meeting emails arrives simultaneously (e.g., after a conference day), the workflow can hit this limit and fail silently. Add a Wait node between Slack posts set to 1.1 seconds if you're processing more than a few emails in a single polling cycle.
Ideas for what to build next
- →Add a Gmail label after routing — Use a second Gmail node after the Slack post to automatically apply a label like 'Distributed-to-Slack' to processed emails. This gives you a clear audit trail inside Gmail and prevents confusion about which emails have been routed.
- →Build a daily digest version — Create a parallel workflow that collects all meeting emails over a 24-hour window using a Schedule trigger, batches them into a single Slack message, and posts a digest each morning at 8am. Useful for lower-urgency project channels that don't need real-time pings.
- →Route to Notion or a task manager for action items — When the detected meeting type is 'Action Items', fork the workflow to also create tasks in Notion, Asana, or Linear — one task per bullet point extracted from the email body using a Code node with a bullet-point regex parser.
Related guides
How to Share Notion Meeting Notes to Slack with Pipedream
~15 min setup
How to Share Notion Meeting Notes to Slack with Power Automate
~15 min setup
How to Share Notion Meeting Notes to Slack with n8n
~20 min setup
How to Send Notion Meeting Notes to Slack with Zapier
~8 min setup
How to Share Notion Meeting Notes to Slack with Make
~12 min setup
How to Create Notion Tasks from Slack with Pipedream
~15 min setup