

How to Forward Gmail Emails to Slack with Pipedream
Watches a Gmail inbox for messages matching specific senders, subject keywords, or labels, then posts a formatted summary to a designated 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
Engineering or ops teams who want to route customer emails, vendor alerts, or labeled messages to specific Slack channels without writing a full backend service.
Not ideal for
Teams that need two-way email-to-Slack threading or want replies sent back via email — that requires a different architecture entirely.
Sync type
real-timeUse case type
notificationReal-World Example
A 12-person SaaS support team forwards all emails tagged with the Gmail label 'customer-inquiry' to #support in Slack so the whole team sees new tickets within seconds. Before this, a single support rep had to check a shared inbox and manually paste email content into Slack — which meant a 30-to-90-minute lag on busy days. With Pipedream running the workflow, the message hits Slack within 15 seconds of Gmail receiving the email.
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 Pipedream
Copy the pre-built Pipedream blueprint and paste it straight into Pipedream. 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.
Field Mapping
Map these fields between your apps.
| Field | API Name | |
|---|---|---|
| Required | ||
| Sender Email | from.email | |
| Subject Line | subject | |
| Snippet | snippet | |
| Slack Channel ID | ||
6 optional fields▸ show
| Sender Name | from.name |
| Gmail Label IDs | labelIds |
| Thread ID | threadId |
| Message ID | id |
| Received Timestamp | internalDate |
| Plain Text Body | body.text |
Step-by-Step Setup
pipedream.com > Workflows > New Workflow
Create a new Pipedream workflow
Go to pipedream.com and log in. From the left sidebar, click 'Workflows', then click the blue 'New Workflow' button in the top right. You'll land on a blank canvas with a single prompt: 'Add a trigger'. This is your starting point — everything flows from the trigger you pick here.
- 1Log in at pipedream.com
- 2Click 'Workflows' in the left sidebar
- 3Click the blue 'New Workflow' button in the top right
- 4Click the '+ Add Trigger' tile on the canvas
Trigger Panel > Search 'Gmail' > New Email
Add the Gmail trigger
In the trigger search panel, type 'Gmail' and select it. You'll see a list of available Gmail triggers. Choose 'New Email' — this fires every time a new message arrives in the connected inbox. Do not choose 'New Email Matching Search' unless you want to write a Gmail search query right now; you can add filters in a later step using code.
- 1Type 'Gmail' in the trigger search bar
- 2Click the Gmail app icon
- 3Select 'New Email' from the trigger list
- 4Click 'Connect Gmail Account' and authorize via the OAuth popup
Trigger Panel > Test Trigger
Test the Gmail trigger
Click 'Test Trigger'. Pipedream will pull the most recent email from your inbox as sample data. You'll see a JSON object appear with fields like `subject`, `from.email`, `snippet`, `labelIds`, and `body.html`. This sample data is what all downstream steps will reference. If your inbox is empty or the account is fresh, send yourself a test email first.
- 1Click the 'Test Trigger' button
- 2Wait 5-10 seconds for Pipedream to fetch a recent email
- 3Expand the returned JSON to inspect the `from`, `subject`, and `body` fields
Workflow Canvas > + > Run Node.js Code
Add a Node.js code step to filter emails
Click the '+' button below the trigger to add a new step. Choose 'Run Node.js code'. This is where you decide which emails actually get forwarded. You'll write a short filter that checks the sender address, subject line, or label — and calls `$.flow.exit()` to stop the workflow if the email doesn't match. Without this step, every single email in your inbox gets posted to Slack.
- 1Click the '+' button below the Gmail trigger tile
- 2Select 'Run Node.js code' from the step options
- 3Paste your filter logic into the code editor (see the pro tip below)
- 4Click 'Test' to confirm the filter runs against your sample email data
Paste this as your Step 2 Node.js filter + Step 3 formatter combined. It handles sender filtering, label matching, plain-text body extraction, and HTML tag stripping in one step — then exports everything the Slack step needs. Place it directly after the Gmail trigger, before the Slack step.
JavaScript — Code Step// Step: Filter + Format Gmail Email for Slack▸ Show code
// Step: Filter + Format Gmail Email for Slack
// Place this immediately after the Gmail trigger
export default defineComponent({... expand to see full code
// Step: Filter + Format Gmail Email for Slack
// Place this immediately after the Gmail trigger
export default defineComponent({
async run({ steps, $ }) {
const email = steps.trigger.event;
// --- FILTER CONFIGURATION ---
const ALLOWED_SENDERS = ['[email protected]', '[email protected]'];
const REQUIRED_LABEL = 'vendor-invoices'; // set to null to skip label check
const SUBJECT_KEYWORDS = ['invoice', 'payment', 'action required'];
// Check sender
const senderEmail = email.from?.email?.toLowerCase() ?? '';
const senderName = email.from?.name ?? senderEmail;
const senderMatch = ALLOWED_SENDERS.length === 0 || ALLOWED_SENDERS.includes(senderEmail);
// Check label
const labelMatch = !REQUIRED_LABEL || (email.labelIds ?? []).includes(REQUIRED_LABEL);
// Check subject keywords
const subject = email.subject ?? '';
const keywordMatch = SUBJECT_KEYWORDS.length === 0 ||
SUBJECT_KEYWORDS.some(kw => subject.toLowerCase().includes(kw.toLowerCase()));
if (!senderMatch || !labelMatch || !keywordMatch) {
$.flow.exit(`Email filtered out — sender: ${senderMatch}, label: ${labelMatch}, keyword: ${keywordMatch}`);
}
// --- FORMAT FOR SLACK ---
// Strip HTML tags from body if plain text unavailable
const rawBody = email.body?.text ?? email.snippet ?? '';
const cleanBody = rawBody
.replace(/<[^>]+>/g, '') // strip HTML tags
.replace(/\s+/g, ' ') // collapse whitespace
.trim()
.substring(0, 300); // cap at 300 chars for Slack readability
// Build Gmail deep link
const gmailLink = `https://mail.google.com/mail/u/0/#inbox/${email.threadId}`;
// Format received date
const receivedAt = email.internalDate
? new Date(parseInt(email.internalDate)).toLocaleString('en-US', { timeZone: 'America/New_York' })
: 'Unknown time';
// Export values for Slack step
return {
senderEmail,
senderName,
subject,
bodyPreview: cleanBody,
gmailLink,
receivedAt,
slackMessage: `*New email from ${senderName} <${senderEmail}>*\n*Subject:* ${subject}\n*Received:* ${receivedAt}\n\n${cleanBody}\n\n<${gmailLink}|Open in Gmail>`,
};
},
});
// In the Slack step, set Text = {{steps.filter_and_format.$return_value.slackMessage}}Workflow Canvas > + > Run Node.js Code
Extract and format the email fields
Add a second Node.js code step. This step pulls the fields you care about — sender name, sender email, subject, timestamp, and a plain-text snippet — and formats them into a clean Slack message string. Gmail's `body.html` is messy HTML; use a simple regex or string replacement to strip tags for the Slack preview. Export the formatted values so the Slack step can reference them.
- 1Click '+' below the filter step
- 2Select 'Run Node.js code'
- 3Write code to extract `steps.trigger.event.subject`, `steps.trigger.event.from.email`, and `steps.trigger.event.snippet`
- 4Use `$.export()` to make these values available to downstream steps
- 5Click 'Test' and verify the exported values appear in the Results tab
Workflow Canvas > + > Slack > Send Message to Channel
Add the Slack step
Click '+' below your formatting step and search for 'Slack'. Select the 'Send Message to Channel' action. Connect your Slack workspace via OAuth — Pipedream will open a Slack authorization popup. Once connected, select the target channel from the dropdown (e.g., #vendor-updates or #customer-inquiries). Pipedream lists all channels your bot has access to.
- 1Click '+' below the formatting step
- 2Type 'Slack' in the search bar and select the Slack app
- 3Choose 'Send Message to Channel'
- 4Click 'Connect Slack Account' and authorize via the OAuth popup
- 5Select your target channel from the 'Channel' dropdown
Slack Step > Text Field > {{}} Reference Picker
Build the Slack message text
In the 'Text' field of the Slack step, click the '{{}}' icon to reference exported values from earlier steps. Build a message that includes the sender, subject, and snippet. Use Slack's mrkdwn formatting — asterisks for bold, backticks for code. For example: `*New email from {{steps.format_email.$return_value.senderEmail}}*\n*Subject:* {{steps.format_email.$return_value.subject}}\n{{steps.format_email.$return_value.snippet}}`. Add a direct Gmail link using the `threadId` from the trigger payload.
- 1Click inside the 'Text' field in the Slack step
- 2Type your message template and use '{{}}' to insert dynamic values
- 3Reference `steps.format_email.$return_value.senderEmail` for the sender
- 4Reference `steps.trigger.event.threadId` to build a deep link to Gmail
- 5Click 'Test' to send a real message to your Slack channel
Workflow Canvas > + > Run Node.js Code
Add error handling with $.send.email()
Add a final Node.js step wrapped in a try/catch. If the Slack API call fails (network timeout, channel archived, token revoked), use Pipedream's built-in `$.send.email()` to notify your own inbox instead of silently dropping the event. This gives you a fallback that works without any external monitoring setup. Set the `to` field to the workflow owner's email.
- 1Click '+' after the Slack step
- 2Select 'Run Node.js code'
- 3Wrap a check of `steps.slack.$return_value` in a try/catch block
- 4In the catch block, call `$.send.email({ subject: 'Slack forward failed', text: error.message })`
- 5Click 'Test' to verify the step runs without errors on a successful flow
Workflow Canvas > Deploy > Event History
Deploy and monitor the workflow
Click the 'Deploy' button in the top right. Your workflow moves from Draft to Active status. From the workflow detail page, click 'Event History' in the left sidebar to watch live runs come in. Each row shows the event timestamp, which steps ran, how long each took, and whether the run succeeded, was cancelled (filtered out), or errored. This is your primary debugging surface.
- 1Click the blue 'Deploy' button in the top right corner
- 2Confirm the status indicator changes from 'Draft' to 'Active'
- 3Send a real test email to your Gmail inbox that matches your filter
- 4Click 'Event History' in the left sidebar to watch the run appear
- 5Click into the run to inspect step-by-step output
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 Pipedream for this if your team has at least one person comfortable reading JavaScript, you need the filter logic to go beyond simple keyword matching, or you want to add a second action (like a Gmail auto-reply or a Notion log entry) in the same workflow without paying per step. Pipedream's Node.js code steps make custom parsing — stripping HTML, resolving label IDs to human names, formatting timestamps by timezone — trivial to add. If nobody on your team will touch code and you just need 'forward emails with this label to this channel,' Zapier's Gmail + Slack Zap gets the job done in 8 minutes with zero code.
Pipedream's free tier gives you 10,000 credits per month. This workflow costs roughly 2 credits per run — one for the trigger, one for the Slack step. At 50 emails per day that match your filter, that's 3,000 credits per month, well inside the free tier. At 200 matching emails per day, you're at 12,000 credits — just over the free limit. The next paid tier is $29/month for 100,000 credits, which handles up to 1,650 matching emails per day. Zapier's equivalent at that volume costs $49-$73/month depending on task count. Make handles 1,000 operations per month free and then $9/month for 10,000 — cheaper than Pipedream for low volume, but Make's Gmail trigger polls every 15 minutes instead of reacting instantly.
Zapier gets the Gmail label filter right out of the box in the trigger config — no code required. Make has a better visual router for sending one email to multiple Slack channels based on conditions. n8n's Gmail node lets you batch-fetch emails with full header access, which is useful if you're processing digest-style. Power Automate has native Office 365 Mail integration but its Gmail connector is third-party and unreliable for production use. Pipedream beats all of them on latency — the Pub/Sub webhook fires within 5-10 seconds of email delivery, whereas Make and Zapier poll at 1-15 minute intervals on most plans. If your team needs to react to customer emails within seconds, that gap matters.
Three things you'll hit after go-live. First, Gmail label IDs are not the same as label names. The API returns strings like `Label_1234567890` for custom labels — not 'vendor-invoices'. You need to call the Gmail Labels API once to map IDs to names, or hardcode the ID after finding it in the trigger payload. Second, forwarded email threads with long reply chains can produce a `snippet` that's mid-sentence from a reply, not the original message — always check what snippet you're actually displaying. Third, if the Gmail account receives more than ~500 emails per day total, Pub/Sub delivery can occasionally be delayed 1-3 minutes during peak periods. This is a Gmail API infrastructure constraint, not a Pipedream bug, and there's no workaround other than switching to polling at short intervals — which defeats the purpose.
Ideas for what to build next
- →Add a daily digest instead of per-email pings — Swap the instant trigger for a scheduled Pipedream workflow that runs at 9am, queries the Gmail API for all matching messages from the past 24 hours, and posts a single Slack digest. This is better for high-volume inboxes where per-email Slack pings become noise.
- →Route to different channels based on sender domain — Extend the filter step to check the sender's domain and export a different `targetChannel` value for each — vendor emails go to #vendor-ops, customer emails go to #support, press emails go to #comms. One workflow replaces three.
- →Auto-reply to the sender via Gmail when the Slack message posts — Add a Gmail 'Send Email' step after the Slack step to fire an acknowledgment reply to the original sender — 'Your message has been received and routed to our team.' No extra workflow needed; it's a second step in the same flow.
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