DH
7 min read

Building a Gmail to AI Assistant Pipeline with Pub/Sub and Webhooks

Set up real-time Gmail notifications that route through an AI assistant to filter noise, extract insights, and only alert you when it matters.

aigmailwebhooksautomation

Tired of email noise? In this tutorial, we'll build a pipeline that watches your Gmail inbox in real-time, routes emails through an AI assistant, and only notifies you about what actually matters. Newsletters get summarized, receipts get ignored, and urgent emails get flagged immediately.

Key Takeaways

  • Gmail's Push Notifications API with Google Pub/Sub enables real-time email monitoring without polling
  • The gog CLI simplifies Gmail watch setup and webhook forwarding
  • Cloudflare Tunnels provide free, instant HTTPS endpoints for local webhook receivers
  • AI filtering can categorize emails and extract insights before they reach you
  • The entire pipeline runs locally with minimal cloud infrastructure

Architecture Overview

Here's what we're building:

Gmail Inbox
↓ (new email arrives)
Google Pub/Sub
↓ (push notification)
Cloudflare Tunnel (public HTTPS)

gog CLI (local webhook server)
↓ (forwards to your app)
Your Webhook Handler

AI Processing (classify, summarize, extract)

Notification (only if important)

Prerequisites

Before we start, you'll need:

  • A Google Cloud project with billing enabled
  • gcloud CLI installed and authenticated
  • Node.js 18+ (for the webhook handler)
  • A Gmail account to monitor

1. Install the Required Tools

First, install gog (a Gmail CLI) and cloudflared:

# Install gog via Homebrew
brew install gogcli

# Install cloudflared
brew install cloudflared

2. Set Up Google Cloud Pub/Sub

Gmail's push notifications work through Google Pub/Sub. Let's set up the infrastructure:

# Authenticate with Google Cloud
gcloud auth login
gcloud config set project YOUR_PROJECT_ID

# Enable required APIs
gcloud services enable gmail.googleapis.com pubsub.googleapis.com

# Create a Pub/Sub topic for Gmail notifications
gcloud pubsub topics create gmail-watch

# Allow Gmail to publish to your topic
gcloud pubsub topics add-iam-policy-binding gmail-watch \
--member=serviceAccount:[email protected] \
--role=roles/pubsub.publisher

3. Configure OAuth Credentials

You'll need OAuth credentials for gog to access Gmail:

  1. Go to Google Cloud Console → APIs & Credentials
  2. Click Create Credentials → OAuth client ID
  3. Select Desktop app as the application type
  4. Download the JSON credentials file and save it somewhere accessible (e.g., credentials.json in your project directory)
  5. Configure gog with your credentials:
gog auth credentials /path/to/credentials.json
gog auth login --account [email protected]

4. Start the Cloudflare Tunnel

Pub/Sub needs a public HTTPS endpoint to push notifications. Cloudflare Tunnels provide this for free:

# Start a tunnel pointing to your local webhook server (port 8788)
cloudflared tunnel --url http://127.0.0.1:8788

You'll see output like:

Your quick Tunnel has been created! Visit it at:
https://random-words-here.trycloudflare.com

Save this URL — you'll need it for the Pub/Sub subscription.

Note: Free Cloudflare tunnel URLs change on restart. For production, consider a named tunnel with a stable subdomain.

5. Create the Pub/Sub Subscription

Now create a push subscription that sends notifications to your tunnel:

TUNNEL_URL="https://your-tunnel-url.trycloudflare.com"
SHARED_TOKEN="your-secret-token-here"

gcloud pubsub subscriptions create gmail-watch-push \
--topic gmail-watch \
--push-endpoint "${TUNNEL_URL}/?token=${SHARED_TOKEN}"

6. Start the Gmail Watch

With gog, starting a Gmail watch is simple:

# Start watching your inbox
gog gmail watch start \
--account [email protected] \
--label INBOX \
--topic projects/YOUR_PROJECT_ID/topics/gmail-watch

This tells Gmail to send notifications to your Pub/Sub topic whenever new emails arrive.

7. Run the Webhook Server

Now let's run gog's built-in webhook server to receive and forward notifications:

gog gmail watch serve \
--account [email protected] \
--bind 127.0.0.1 \
--port 8788 \
--path / \
--token "$SHARED_TOKEN" \
--hook-url http://127.0.0.1:3000/api/gmail \
--hook-token "your-app-secret" \
--include-body \
--max-bytes 20000

Key flags:

  • --token: Validates incoming Pub/Sub requests
  • --hook-url: Where to forward processed emails
  • --include-body: Include email body content (not just metadata)
  • --max-bytes: Limit body size to avoid huge payloads

8. Build the AI Webhook Handler

Now for the fun part — the AI-powered webhook handler. Here's a Next.js API route example:

// app/api/gmail/route.ts
import { NextRequest, NextResponse } from 'next/server';
import Anthropic from '@anthropic-ai/sdk';

const anthropic = new Anthropic();

interface EmailPayload {
from: string;
subject: string;
body: string;
snippet: string;
}

export async function POST(req: NextRequest) {
// Verify the webhook token
const authHeader = req.headers.get('authorization');
if (authHeader !== `Bearer ${process.env.GMAIL_HOOK_TOKEN}`) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}

const payload: EmailPayload = await req.json();

// Use AI to classify and process the email
const analysis = await analyzeEmail(payload);

if (analysis.action === 'notify') {
await sendNotification(analysis.summary);
} else if (analysis.action === 'capture') {
await saveInsights(analysis.insights);
}
// 'ignore' action = do nothing

return NextResponse.json({ ok: true });
}

async function analyzeEmail(email: EmailPayload) {
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-5-20250514',
max_tokens: 500,
messages: [{
role: 'user',
content: `Analyze this email and respond with JSON:

From: ${email.from}
Subject: ${email.subject}
Body: ${email.body?.slice(0, 2000) || email.snippet}

Respond with:
{
"action": "notify" | "capture" | "ignore",
"category": "urgent" | "newsletter" | "transactional" | "personal" | "spam",
"summary": "one-line summary if action is notify",
"insights": ["key insight 1", "key insight 2"] // if newsletter worth capturing
}

Rules:
- "notify" for urgent, personal, or time-sensitive emails
- "capture" for newsletters with valuable content
- "ignore" for receipts, shipping updates, marketing spam`
}]
});

const text = response.content[0].type === 'text' ? response.content[0].text : '';
return JSON.parse(text);
}

async function sendNotification(message: string) {
// Integrate with your preferred notification service
// e.g., Pushover, ntfy, Telegram, SMS, etc.
console.log('📬 Notification:', message);
}

async function saveInsights(insights: string[]) {
// Save to database, file, or note-taking app
console.log('💡 Captured insights:', insights);
}

9. Environment Variables

Set up your environment:

# .env.local
GMAIL_HOOK_TOKEN=your-app-secret
ANTHROPIC_API_KEY=your-anthropic-key

10. Testing the Pipeline

Send yourself a test email and watch the logs:

# In terminal 1: Cloudflare tunnel
cloudflared tunnel --url http://127.0.0.1:8788

# In terminal 2: gog webhook server
gog gmail watch serve --account [email protected] ...

# In terminal 3: Your Next.js app
npm run dev

When an email arrives, you should see:

  1. Pub/Sub pushes to your tunnel
  2. gog fetches the email content
  3. Your webhook receives the payload
  4. AI analyzes and categorizes
  5. Notification (or silence) based on importance

Customizing the AI Behavior

The real power is in customizing the AI prompt. Here are some ideas:

Strict Newsletter Filter

Only capture newsletters about: software development, AI/ML, startups, productivity.
Ignore: marketing, sales pitches, promotional content.

Smart Summarization

For captured newsletters, extract:
- Main argument or thesis
- Actionable takeaways
- Links worth saving

Priority Detection

Mark as urgent if:
- From a known VIP contact
- Contains words like "urgent", "ASAP", "deadline"
- Is a reply to your recent email
- Security-related (password reset, login alerts)

Production Considerations

Before running this in production:

  1. Stable Tunnel URL: Use a named Cloudflare tunnel or alternative (ngrok with reserved domain, Tailscale Funnel)

  2. Error Handling: Add retry logic and dead-letter queues for failed webhook processing

  3. Rate Limiting: Gmail has API quotas — batch process during high-volume periods

  4. Token Refresh: gog handles OAuth token refresh, but monitor for auth failures

  5. Cost Management: Each AI call costs money — consider caching or batching for high-volume inboxes

Conclusion

You've now built an AI-powered email pipeline that:

  • Monitors Gmail in real-time via Pub/Sub
  • Filters out noise automatically
  • Extracts insights from valuable content
  • Only notifies you when it matters

The same pattern works for other use cases:

  • Slack message filtering
  • GitHub notification triage
  • RSS feed summarization
  • Any webhook-driven data source

Key Takeaways:

  • Gmail Pub/Sub + webhooks = real-time without polling
  • gog CLI simplifies the Gmail integration
  • Cloudflare Tunnels provide instant public endpoints
  • AI classification turns noise into signal
  • The whole stack runs locally with minimal infrastructure

Experiment with different AI prompts to tune the filtering to your workflow. The goal is inbox zero without the manual triage.

Damian Hodgkiss

Damian Hodgkiss

Senior Staff Engineer at Sumo Group, leading development of AppSumo marketplace. Technical solopreneur with 25+ years of experience building SaaS products.

Creating Freedom

Join me on the journey from engineer to solopreneur. Learn how to build profitable SaaS products while keeping your technical edge.

    Proven strategies

    Learn the counterintuitive ways to find and validate SaaS ideas

    Technical insights

    From choosing tech stacks to building your MVP efficiently

    Founder mindset

    Transform from engineer to entrepreneur with practical steps