Intermediate~20 min setupCommunication & EmailVerified April 2026
Slack logo
Gmail logo

How to Send Gmail Sales Alerts to Slack with n8n

Polls Gmail every minute for high-priority prospect emails and posts a formatted Slack message with sender, subject, and email preview to a sales channel.

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 sales teams who self-host n8n and need instant Slack alerts when prospect emails land in Gmail without paying per-task fees.

Not ideal for

Teams using Outlook or needing sub-30-second latency — Gmail's API polling minimum is 1 minute and webhook push is not natively supported in n8n's Gmail node.

Sync type

real-time

Use case type

notification

Real-World Example

💡

A 12-person SaaS sales team uses this to ping their #inbound-leads Slack channel whenever a prospect from a tracked domain sends an email marked important in Gmail. Before this, AEs checked Gmail manually between calls and routinely missed responses for 2-3 hours during busy days. Now the whole team sees new prospect emails within 60 seconds and can claim follow-ups directly in Slack.

What Will This Cost?

Drag the slider to your expected monthly volume.

/mo
505005K50K

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

Skip the setup

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.

A Gmail account with 'gmail.readonly' and 'gmail.modify' OAuth scopes available — required for reading emails and marking them as read after processing
A Slack workspace where you have permission to install apps and a Slack app with 'chat:write' and 'channels:read' bot token scopes enabled
n8n instance running version 0.220 or later (earlier versions have a Gmail Trigger bug that causes duplicate executions on reconnect)
Admin access to your Google account or Workspace to complete the OAuth authorization flow without IT approval blocking it
The target Slack channel already created and your Slack bot app invited to that channel via '/invite @yourappname' in Slack

Field Mapping

Map these fields between your apps.

FieldAPI Name
Required
Sender Email Address
Sender Display Name
Email Subject
Email Body Preview
Gmail Thread ID
Gmail Message ID
2 optional fields▸ show
Email Received Timestamp
Importance Label

Step-by-Step Setup

1

n8n Dashboard > Workflows > + New Workflow

Create a new n8n workflow

Log into your n8n instance and click the '+ New Workflow' button in the top-right corner of the Workflows dashboard. Give it a name like 'Gmail → Slack Sales Alerts' so it's easy to find later. You'll land on a blank canvas with a single grey trigger node in the center. All subsequent nodes will chain off this.

  1. 1Log into your n8n instance at your host URL or localhost:5678
  2. 2Click '+ New Workflow' in the top-right corner
  3. 3Click the pencil icon next to 'My Workflow' and rename it to 'Gmail → Slack Sales Alerts'
  4. 4Click the grey trigger node in the center of the canvas to open the node selector
What you should see: You should see a blank canvas with the node selector panel open on the right side, ready to pick a trigger.
Common mistake — If you're on n8n Cloud, workflows must be manually activated before they poll. A workflow in 'inactive' state will never fire — even after you finish setup. Remember to flip the toggle at the top of the canvas before going live.
2

Canvas > Trigger Node > Search 'Gmail' > Gmail Trigger

Add and configure the Gmail trigger node

Search for 'Gmail' in the node selector and choose the Gmail node. Set the operation to 'Trigger' mode — this polls for new emails on a schedule. Set the poll interval to 1 minute (the minimum Gmail allows via the API). You'll see a 'Filters' section where you can restrict which emails fire the trigger.

  1. 1Type 'Gmail' in the search box and select 'Gmail Trigger'
  2. 2Click 'Create new credential' to connect your Google account
  3. 3Set 'Poll Times' to 'Every Minute'
  4. 4Under 'Filters', set 'Label' to 'IMPORTANT' to catch high-priority emails
  5. 5Optionally add a second filter: 'Search' field with value 'is:unread' to avoid reprocessing read emails
What you should see: The Gmail Trigger node should show a green credential badge and display your filter settings in the node summary panel.
Common mistake — The Gmail Trigger node uses the 'messages.list' API endpoint, which only returns emails received after the workflow was first activated. Emails that arrived before activation are not backfilled — they will never appear in the trigger output.
n8n
+
click +
search apps
Slack
SL
Slack
Add and configure the Gmail …
Slack
SL
module added
3

Gmail Trigger Node > Credential > + Create New > Google OAuth2

Connect your Google account credentials

Click 'Create new credential' inside the Gmail Trigger node. n8n will open a Google OAuth flow. You need to grant the 'gmail.readonly' scope at minimum. If you plan to mark emails as read after processing (recommended), also grant 'gmail.modify'. Complete the OAuth popup and return to n8n.

  1. 1Click the 'Credential' dropdown and select '+ Create New Credential'
  2. 2Choose 'Google OAuth2 API' from the credential type list
  3. 3Click 'Sign in with Google' and log in with the Gmail account you want to monitor
  4. 4Accept the permissions request in the Google popup
  5. 5Click 'Save' on the credential modal in n8n
What you should see: The credential dropdown in the Gmail Trigger node should now show your email address and a green dot indicating a valid connection.
Common mistake — If you're using a Google Workspace account managed by an IT admin, OAuth apps may need to be pre-approved in the Google Admin console. Personal Gmail accounts connect without this restriction. Check with your admin before wasting time debugging a blocked OAuth flow.
n8n settings
Connection
Choose a connection…Add
click Add
Slack
Log in to authorize
Authorize n8n
popup window
Connected
green checkmark
4

Canvas > + > Core > IF

Add a filter node to isolate high-priority senders

Click the '+' button to the right of the Gmail Trigger node and add an 'IF' node. This is where you filter by sender domain or specific email addresses — so only emails from real prospects fire the Slack alert. Without this, every important email (including internal ones) will notify the channel.

  1. 1Click the '+' connector on the right side of the Gmail Trigger node
  2. 2Search for 'IF' and select the IF node from the Core section
  3. 3Set Value 1 to the expression: {{ $json.from }}
  4. 4Set the condition to 'Contains'
  5. 5Set Value 2 to your prospect domain, e.g. 'acme.com', or use a comma-separated list by chaining multiple OR conditions
What you should see: The IF node should show two output branches: 'true' (emails that match your domain filter) and 'false' (emails that don't). Only the 'true' branch will connect to Slack.
Common mistake — Filters are the most common place setups break. Double-check the field name and value exactly match what your app sends — a single capital letter difference will block everything.
Slack
SL
trigger
filter
Priority
matches criteria?
yes — passes through
no — skipped
Gmail
GM
notified
5

Canvas > IF Node (true branch) > + > Core > Code

Add a Code node to extract and format email data

Connect a Code node to the 'true' output of the IF node. This is where you pull the sender name, email address, subject, and a plain-text preview of the email body. The Gmail Trigger returns the body as base64-encoded HTML — you need to decode and truncate it here before sending it to Slack. This step is what makes the Slack message actually readable.

  1. 1Click the '+' on the 'true' output of the IF node
  2. 2Search for 'Code' and select the Code node
  3. 3Set language to 'JavaScript'
  4. 4Paste the transformation script from the Pro Tip section below into the code editor
  5. 5Click 'Test step' to verify the output shows decoded subject, sender, and body preview fields
What you should see: After running the test, you should see a new output object with fields like 'senderName', 'senderEmail', 'subject', 'bodyPreview', and 'emailLink' — all formatted as plain readable strings.
Common mistake — Gmail encodes email bodies in base64url format, not standard base64. The characters '+' and '/' are replaced with '-' and '_'. If your decoded body looks like garbled characters, you're using the wrong decoder. The code in the Pro Tip handles this correctly.

Paste this into the Code node (step 5) between the IF node and the Slack node. It decodes the base64url email body, extracts sender name and address from the raw From header, truncates the body to 300 characters, and builds the Gmail thread URL — all fields the Slack Block Kit message needs.

JavaScript — Code Node// n8n Code Node — Gmail body decoder and field extractor
▸ Show code
// n8n Code Node — Gmail body decoder and field extractor
// Runs once per email item passed from the IF node
const items = $input.all();

... expand to see full code

// n8n Code Node — Gmail body decoder and field extractor
// Runs once per email item passed from the IF node

const items = $input.all();
const results = [];

for (const item of items) {
  const raw = item.json;

  // Extract sender name and email from 'From' header
  // Gmail returns: 'Display Name <[email protected]>' or just '[email protected]'
  const fromHeader = raw.from || '';
  const nameMatch = fromHeader.match(/^(.+?)\s*</);
  const emailMatch = fromHeader.match(/<([^>]+)>/);
  const senderName = nameMatch ? nameMatch[1].trim() : fromHeader;
  const senderEmail = emailMatch ? emailMatch[1] : fromHeader;

  // Decode base64url email body
  // Gmail uses base64url: '-' instead of '+', '_' instead of '/'
  let bodyPreview = raw.snippet || '(no preview available)';
  try {
    const parts = raw.payload?.parts || [];
    const textPart = parts.find(p => p.mimeType === 'text/plain')
      || parts.flatMap(p => p.parts || []).find(p => p.mimeType === 'text/plain');

    if (textPart?.body?.data) {
      const base64 = textPart.body.data
        .replace(/-/g, '+')
        .replace(/_/g, '/');
      const decoded = Buffer.from(base64, 'base64').toString('utf-8');
      // Trim whitespace and truncate to 300 chars for Slack readability
      bodyPreview = decoded.replace(/\s+/g, ' ').trim().substring(0, 300);
      if (decoded.length > 300) bodyPreview += '...';
    }
  } catch (e) {
    // Fall back to Gmail's snippet if body decode fails
    bodyPreview = raw.snippet || '(decode error — check email format)';
  }

  // Convert Gmail internalDate (Unix ms) to readable string
  const timestamp = raw.internalDate
    ? new Date(parseInt(raw.internalDate)).toLocaleString('en-US', {
        month: 'short', day: 'numeric', year: 'numeric',
        hour: 'numeric', minute: '2-digit', hour12: true
      })
    : 'Unknown time';

  // Build Gmail thread URL for one-click access from Slack
  const gmailLink = `https://mail.google.com/mail/u/0/#inbox/${raw.threadId}`;

  results.push({
    json: {
      senderName,
      senderEmail,
      subject: raw.subject || '(no subject)',
      bodyPreview,
      receivedAt: timestamp,
      gmailLink,
      messageId: raw.id,
      threadId: raw.threadId
    }
  });
}

return results;
6

Canvas > Code Node > + > Slack > Slack Node > Credential > + Create New

Connect your Slack credentials

Click '+' after the Code node and add a Slack node. In the node settings, click 'Create new credential' and choose 'Slack OAuth2 API'. You'll be redirected to Slack to authorize n8n as an app. Make sure you're authorizing into the correct Slack workspace — the one your sales team uses.

  1. 1Click '+' on the Code node's output and search for 'Slack'
  2. 2Select the 'Slack' node and set Resource to 'Message', Operation to 'Post'
  3. 3Click the Credential dropdown and select '+ Create New Credential'
  4. 4Choose 'Slack OAuth2 API' and click 'Connect'
  5. 5In the Slack authorization screen, select your workspace and click 'Allow'
What you should see: The Slack credential dropdown should display your workspace name with a green connected indicator.
Common mistake — The Slack app you authorize must have the 'chat:write' scope enabled. If you created your Slack app in the Slack API dashboard, check the OAuth & Permissions page to confirm this scope is listed under 'Bot Token Scopes'. Missing this scope causes a 'missing_scope' error at runtime.
7

Slack Node > Resource: Message > Operation: Post > Channel + Text

Configure the Slack message with email details

In the Slack node, set the Channel field to your sales channel name (e.g. #inbound-leads). Set the Message Text field using the output fields from the Code node. Use Slack's Block Kit format for a clean layout — include sender name, email address, subject line, and the body preview. The email link lets reps jump straight to Gmail.

  1. 1Set 'Channel' to your sales Slack channel, e.g. #inbound-leads
  2. 2Set 'Message Type' to 'Block'
  3. 3In the 'Blocks' field, paste or build the Block Kit JSON using the field references from the Code node
  4. 4Map 'senderName' to the header block, 'subject' and 'bodyPreview' to section blocks
  5. 5Add a button block with the 'emailLink' field pointing to the Gmail thread URL
What you should see: When you click 'Test step', you should see a formatted Slack message appear in your chosen channel with the sender's name, subject, body preview, and a link to the Gmail thread.
Common mistake — Slack channel names in n8n must be entered with the '#' prefix OR by using the channel ID (e.g. C04XXXXXX). If you type just 'inbound-leads' without the hash, the node may silently post to the wrong channel or return a 'channel_not_found' error.
8

Canvas > Slack Node > + > Gmail > Resource: Message > Operation: Mark as Read

Add a Gmail node to mark processed emails as read

After the Slack node, add a second Gmail node to mark the email as read. This prevents the trigger from picking up the same email on the next poll cycle. Set the Resource to 'Message', Operation to 'Mark as Read', and pass the email ID from the trigger output. This is the most important deduplication step in the entire workflow.

  1. 1Click '+' on the Slack node's output and add a Gmail node
  2. 2Set Resource to 'Message' and Operation to 'Mark as Read'
  3. 3Set 'Message ID' to the expression: {{ $('Gmail Trigger').item.json.id }}
  4. 4Use the same Gmail credential you configured in step 3
  5. 5Click 'Test step' to confirm the email disappears from the unread filter
What you should see: The target email in Gmail should change from bold (unread) to normal weight (read). On the next poll cycle, it will no longer appear in the trigger output.
Common mistake — This step requires the 'gmail.modify' scope, not just 'gmail.readonly'. If you only granted readonly access in step 3, this node will throw a 403 Forbidden error. You'll need to delete and recreate the credential with the modify scope.
9

Workflow Settings > Error Workflow > + Create Error Workflow

Add error handling with a fallback Error Trigger node

Click the three-dot menu on any node and select 'Add node after error'. Add an Error Trigger node at the workflow level by going to Workflow Settings. If Gmail's API returns a 429 rate limit error or Slack's API is temporarily down, n8n will route the execution to the error branch instead of silently failing. Connect this to a second Slack node that posts to an #ops-alerts channel.

  1. 1Click the three-dot menu (⋯) in the top-right of the canvas and select 'Settings'
  2. 2Find 'Error Workflow' and click '+ Create Error Workflow'
  3. 3In the error workflow canvas, add an 'Error Trigger' node — it fires automatically on failure
  4. 4Connect the Error Trigger to a Slack node posting to #ops-alerts
  5. 5Include {{ $execution.error.message }} and {{ $execution.error.node }} in the error Slack message
What you should see: You should now have two workflows in your n8n dashboard: the main Gmail-to-Slack workflow and a linked error workflow. The main workflow settings panel should show the error workflow name under 'Error Workflow'.
10

Canvas > Execute Workflow (top toolbar) > Execution Log

Test the full workflow end-to-end

Send a test email from an external email address to your monitored Gmail account. Mark it as Important in Gmail manually. Then return to n8n and click 'Execute Workflow' on the main canvas. Watch the execution flow through each node — the Gmail Trigger should pick it up, the IF filter should pass it through, the Code node should format it, and Slack should receive the message. Check the execution log for any red error indicators.

  1. 1Send a test email from a non-Google account to your monitored Gmail address
  2. 2In Gmail, open the email and click the 'Important' flag (yellow bookmark icon)
  3. 3Return to n8n and click 'Execute Workflow' in the top toolbar
  4. 4Watch each node turn green as data flows through
  5. 5Open your Slack sales channel and confirm the formatted message arrived
What you should see: Each node in the workflow should show a green execution badge. Your Slack channel should contain a formatted message with the sender's name, subject line, body preview, and a link back to the Gmail thread.
Common mistake — Click 'Execute Workflow' in the toolbar runs the workflow once manually — it does NOT start the polling schedule. After testing, you must click the 'Inactive' toggle in the top-right to switch it to 'Active'. Only then will it poll Gmail every minute automatically.
n8n
▶ Run once
executed
Slack
Gmail
Gmail
🔔 notification
received
11

Canvas > Top-right toggle > Inactive → Active

Activate the workflow and verify polling

Click the 'Inactive' toggle in the top-right of the canvas to activate the workflow. It will switch to 'Active' with a green indicator. n8n will now poll Gmail every minute. Wait 2 minutes, then send another test email to confirm the automated poll catches it without you manually triggering anything. Check the Executions tab to see the polling history.

  1. 1Click the 'Inactive' toggle in the top-right of the canvas — it should flip to 'Active' (green)
  2. 2Wait 60-90 seconds for the first automatic poll to fire
  3. 3Send another test email from your prospect domain
  4. 4Open the 'Executions' tab from the left sidebar to see the poll execution log
  5. 5Confirm a new execution ran and the Slack message appeared in your sales channel
What you should see: The Executions tab should show a new execution entry every minute. The most recent one triggered by your test email should show all green nodes and a success status.
Common mistake — The default polling interval is often 15 minutes. If you need faster delivery, check whether your plan supports shorter intervals before assuming it's a bug.

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

VerdictWhy n8n for this workflow

Use n8n for this if your team self-hosts or you're already paying for n8n Cloud — the per-execution pricing of Zapier would cost $49-$299/month for a sales team getting 200-2000 important emails monthly. n8n handles the same volume for $20/month on Cloud or effectively free if self-hosted. The second reason: the Code node. Decoding Gmail's base64url bodies and formatting Slack Block Kit messages cleanly requires actual JavaScript, and n8n gives you a full Node.js environment per execution. If your team uses Zapier exclusively and has no one comfortable editing a 30-line script, pick Make instead — its modules handle Gmail body parsing without code.

Cost

Real math: this workflow runs 1 execution per matched email. A sales team getting 10 high-priority prospect emails per day generates 300 executions/month. On n8n Cloud's Starter plan ($20/month, 2,500 executions included), that's 300 of your 2,500 — you'll never hit the limit. On Zapier's Professional plan ($49/month), 300 tasks barely registers, but if you add the IF filter as a separate Zap step, you're at 600 tasks/month. At 1,000 emails/month Zapier's Professional plan (2,000 tasks) gets tight and the next tier is $99/month. n8n self-hosted stays at server costs only — roughly $5-10/month on a small VPS.

Tradeoffs

Honest comparison: Zapier's Gmail trigger is genuinely easier to set up — 4 clicks versus n8n's credential OAuth flow, and the Slack formatter handles basic message layout without any code. If your team is non-technical and just needs sender + subject in a Slack message, Zapier's 8-minute setup wins. Make's Gmail module has better error handling out of the box and its 'Watch Emails' trigger lets you filter by label and sender in the module UI without a separate filter step. Power Automate has a native 'When a new email arrives (V3)' trigger that handles HTML-to-text conversion automatically, which saves you the base64 decode step — worth knowing if your org is already on Microsoft 365. Pipedream's Gmail source fires faster (near-instant via Gmail push notifications) rather than polling, which gives you true sub-10-second delivery versus n8n's 60-second poll. For a sales team where speed of response matters, Pipedream's latency advantage is real. n8n still wins on cost for self-hosters and on flexibility when you need to add CRM lookups, multi-channel routing, or conditional logic in the same workflow without paying per step.

Three things you'll hit after going live. First: Gmail's importance algorithm is inconsistent. Emails from new domains your account has never interacted with often skip the IMPORTANT label even if they match all your filter criteria — create a Gmail filter rule to force-label by domain. Second: the Gmail Trigger node in n8n does not deduplicate across workflow restarts. If your n8n instance crashes and restarts mid-poll, the same email can fire twice. The Mark as Read step reduces this risk significantly but doesn't eliminate it entirely for emails received during the crash window. Third: Slack's Block Kit has a 3,000-character limit per block. Email bodies longer than ~2,500 characters will cause the Slack node to throw a 'invalid_blocks' error silently. The Code node's 300-character truncation in this guide prevents this, but if you increase that limit, stay under 2,800 characters per block to be safe.

Ideas for what to build next

  • Route emails by priority into different Slack channelsAdd a second IF node after the Code node that checks for keywords like 'urgent', 'contract', or 'renewal' in the subject line and routes those to a #hot-leads channel while all others go to #inbound-leads. Takes about 10 minutes to add and dramatically improves how the team triages responses.
  • Log every lead email to a Google Sheet for reportingAdd a Google Sheets node after the Slack node to append each lead email as a new row with sender, subject, timestamp, and a link to the thread. After 30 days you'll have a clean dataset showing response time, email volume by domain, and which prospects email most frequently.
  • Add a daily digest summary instead of per-email alertsClone this workflow and change the trigger from polling to a schedule (7 AM each morning). Instead of firing per email, accumulate unread important emails from the last 24 hours and post a single summarized list to Slack. Reduces noise for teams that get 20+ prospect emails per day.

Related guides

Was this guide helpful?
Slack + Gmail overviewn8n profile →