Table of Contents
Introduction
Open rates are noisy; conversations drive business. If your outbound process can send but not listen, you’ll miss genuine buying signals, annoy busy recipients with off‑timing follow‑ups, and lose track of which threads are worth your time. This guide shows how to transform a one‑way sender into a reply‑aware outreach system using n8n, Gmail/IMAP, and Google Sheets—with pragmatic classification (rules + LLM), routing (Slack/CRM), and follow‑up sequencing that respects time zones and human context.This article is part of our n8n series. The previous post covers sending personalized emails from Sheets via OpenAI and Gmail. Here we build the other half of the loop: detect replies, understand intent, and take the right next step. For context, see our previous guide or contact our team.
1) Why Replies Matter More Than Open Rates
Opens are affected by privacy features and image blocking; replies are concrete signals of intent. Optimizing for reply quality, not clickbait opens, leads to better relationships and accurate forecasting.
1. Timely context
If someone writes “back next Tuesday,” your system should know to pause and snooze until then.
2. Respectful outreach
Unsubscribe requests are captured and honored automatically.
3. Resource allocation
Teams react quickly to “interested” or “referral” replies, not just opens.
4. Measurability
Reply labels (interested, not now, OOO) inform campaign quality and future targeting.
Metrics to track: positive‑reply rate, time‑to‑first‑reply, follow‑up conversion, suppression growth.
2) Architecture Overview
- Outbound sends occur via your existing n8n flow (Sheets → LLM → Gmail). Each message carries a unique token and yields a threadId/messageId stored in Sheets.
- A Gmail/IMAP watcher polls the reply‑to inbox and pulls new messages thread‑by‑thread.
- A Code node strips quoted history and signatures to isolate the fresh text.
- A rules stage handles deterministic cases (unsubscribe, bounces, out‑of‑office). Anything else goes to an LLM classifier that returns { label, confidence, summary }.
- A router fans out to the right actions: Slack alert, CRM task, snooze job, suppression list update.
- A scheduler checks daily for contacts without replies after a window and sends F1/F2 in the same thread, then stops.
- Write‑backs keep Sheets updated for idempotency, analytics, and compliance.
Design principle: keep ingestion, understanding, decision, and action as separate stages. It’s easier to debug and evolve.
3) IMAP/Gmail Watcher Setup (threadId, messageId, tokens)
Prerequisites
- Dedicated reply‑to inbox (e.g., hello@yourdomain.com) with SPF/DKIM/DMARC configured.
- n8n credentials for Gmail/IMAP with least‑privilege scopes.
Tag outbound emails
- Append a short token to the subject or signature, e.g., [#LS‑{{rowId}}].
- Store rowId, email, sent_at, messageId, threadId, campaign in your Contacts sheet after sending.
Why tokens and thread IDs?
threadId keeps messages in the same Gmail conversation. The token survives forwards or clients that break threading and acts as a human‑readable cross‑reference.
n8n nodes
Thread‑safe matching
- First try threadId to match to the originating contact row.
- Fallback to token lookup via a regex on subject/body if threadId is missing/changed.
4) Stripping Quoted Text & Signatures (Code node)
Most replies include quoted history, legal footers, or mobile signatures. You want the fresh paragraph(s).
- Stop at common quote delimiters: lines starting with >, patterns like On Tue, … wrote:, From:, Sent:.
- For HTML replies, convert to text first (preserve line breaks), then apply the split.
Trim after removing signature blocks like dashes or Sent from my iPhone.
function htmlToText(html) {
return html
.replace(/
(\s*)/gi, ‘\n’)
.replace(/<\/(p|div|li|tr)>/gi, ‘\n’)
.replace(/