How to Detect and Unsubscribe from Newsletters with OpenClaw in Paradime
Feb 26, 2026
How to Auto-Unsubscribe From Newsletters Using Paradime, OpenClaw, and the Gmail API
Stop drowning in newsletter noise. If you're an analytics engineer — or really, anyone with a Gmail inbox — you know the drill: hundreds of marketing emails pile up, you never read them, and the "unsubscribe" links hide behind three clicks and a CAPTCHA. What if you could identify every newsletter you haven't opened in months, extract the unsubscribe links, and review them in one place — automatically, every Sunday?
That's exactly what we're building in this guide. We'll wire up Paradime's Bolt scheduler with OpenClaw's agent capabilities and the Gmail API to create a hands-off newsletter cleanup pipeline. No local config headaches, no cron jobs running on your laptop at 3 AM. Just a secure, UI-driven setup that runs in production.
Let's get into it.
What Is Paradime?
Paradime is an all-in-one AI platform that replaces dbt Cloud™. It gives analytics teams a single workspace to code, ship, fix, and scale data pipelines — whether for analytics or AI workloads. Think of it as the operating system for your entire dbt™ workflow.
The features that matter for this project:
Code IDE — An AI-native IDE that cuts dbt™ and Python development time by 83%+. Full context awareness across data, docs, and lineage.
Bolt — Paradime's scheduler and orchestration engine. It runs dbt™ commands and Python scripts on a cron schedule, with a configure-and-forget UI. Deploy jobs 50% faster than legacy tools.
Environment Variables — Managed through a secure UI. Admin-controlled, with per-schedule overrides. No
.envfiles floating around in Slack DMs.
Bolt is the star here. It supports cron-based triggers, on-merge triggers, API triggers, and even chained schedule triggers. And critically for us, it can run Python scripts alongside dbt™ commands — meaning our unsubscribe logic lives right next to our data pipeline.
Why not just use dbt Cloud™? Paradime's Bolt supports Python script execution natively as a first-class command type, alongside dbt™ commands, Elementary, Lightdash, Tableau refreshes, and more. That's not something you get out of the box elsewhere.
What Is OpenClaw?
OpenClaw is an open-source, local-first personal AI agent that runs on your own hardware. It connects to messaging platforms you already use (WhatsApp, Telegram, Slack, Discord, etc.) and executes real-world tasks: reading email, browsing the web, running shell commands, and managing files — all with persistent memory across sessions.
Here's what makes OpenClaw relevant to our newsletter problem:
Email management — Categorize messages, unsubscribe from spam, draft replies, summarize urgent items.
Skills system — Modular plugins (100+) that extend what the agent can do. You can download skills from ClawHub or let the agent write its own.
Model-agnostic — Works with Anthropic, OpenAI, Gemini, DeepSeek, or local models via Ollama.
Gateway architecture — An always-on control plane on your machine that routes requests, manages sessions, and handles authentication.
Install is straightforward:
The onboarding wizard walks you through model selection, channel pairing, and permissions. Configuration lives at ~/.openclaw/openclaw.json, and your workspace (skills, prompts, memories) lives at ~/.openclaw/workspace.
Setup: OpenClaw + Gmail API
Before we write the unsubscribe script, we need OpenClaw connected to Gmail with proper OAuth credentials. No app passwords. No hacks. OAuth 2.0 with scoped permissions.
Figure 1: OAuth flow connecting OpenClaw to the Gmail API.
Step-by-Step
1. Create a Google Cloud Project
Head to Google Cloud Console. Create a new project — name it something like Openclaw Gmail Integration.
2. Enable the Gmail API
Navigate to APIs & Services → Library, search for "Gmail API", and click Enable.
3. Configure the OAuth Consent Screen
Go to APIs & Services → OAuth consent screen. Select External user type. Fill in your app name (Openclaw Agent), support email, and developer contact. Save and continue.
4. Add OAuth Scopes
Add these scopes — and nothing more:
Scope | Purpose |
|---|---|
| Read, label, and delete emails |
| Send emails (optional) |
Principle of least privilege. Don't grant full account access when you only need to read and label messages.
5. Create OAuth Credentials
Go to APIs & Services → Credentials → Create Credentials → OAuth client ID. Select Desktop app, name it Openclaw Desktop Client, and download the credentials file.
6. Save Credentials for OpenClaw
7. Configure the OpenClaw Google Adapter
Create ~/.openclaw/adapters/google/config.json:
8. Authorize OpenClaw
Then, from your messaging surface, send:
This opens a browser, prompts Google sign-in, and stores OAuth tokens securely.
9. Verify the Connection
You should see:
The Script: Identify, Extract, and Log Newsletter Unsubscribe Candidates
Now for the core logic. We'll write a Python script that:
Identifies newsletter and marketing emails you haven't engaged with
Extracts unsubscribe links from
List-Unsubscribeheaders and email bodiesLogs candidates to a review file — it does not auto-click unsubscribe links (that's your call)
This is the safe, opinionated approach. Automated unsubscribing without human review is how you accidentally lose access to a service you actually care about.
Figure 2: Newsletter cleanup pipeline — from Gmail fetch to human review.
The Python Script
Create a file called unsubscribe_scanner.py in your dbt™ project root:
How It Works
Step | What happens |
|---|---|
Authenticate | Reads |
Query Gmail | Searches |
Parse headers | Checks |
Deduplicate | One entry per sender — you don't need 47 rows for the same SaaS company |
Output | Writes |
The script does not click any unsubscribe links. It logs them for your review. This is deliberate. Automated unsubscribing without oversight is how you lose access to things like password reset emails from services that share a domain with their marketing arm.
Environment Variables: GOOGLE_CREDENTIALS_JSON and OPENCLAW_API_KEY
Both secrets need to be configured securely — and neither belongs in your codebase.
In Paradime (for Bolt Schedules)
Navigate to Settings → Workspaces → Environment Variables
In the Bolt Schedules section, click Add New
Add the following:
Key | Value | Purpose |
|---|---|---|
| Your OAuth credentials JSON (the full contents of | Gmail API authentication |
| Your OpenClaw API key or model provider key | OpenClaw agent authentication |
Click the Save icon
Admin access required. Only admins can add, edit, or remove Bolt environment variables. This is a feature, not a limitation — it prevents credential sprawl.
You can also bulk upload variables via CSV if you're setting up multiple schedules:
Per-schedule overrides are supported too — if you want one schedule to use a different Google account, override GOOGLE_CREDENTIALS_JSON at the schedule level without touching the global default.
In OpenClaw (for Local Development)
OpenClaw reads environment variables from multiple sources with a never-override rule:
Figure 3: OpenClaw environment variable precedence — process env always wins.
For local development, add your keys to ~/.openclaw/.env:
Or inline in ~/.openclaw/openclaw.json:
The ${VAR} syntax resolves from the process environment at activation time — useful when you want config to reference secrets without hardcoding them.
Bolt Schedule: Cron Weekly Sunday
Here's where the setup becomes truly hands-off. We configure a Bolt schedule to run our unsubscribe scanner every Sunday morning.
Option 1: Schedules as Code (YAML)
Add this to your paradime_schedules.yml file in your dbt™ project root:
The cron expression 0 8 * * 0 means: every Sunday at 8:00 AM. The 0 at the end is Sunday in standard cron syntax (0 = Sunday, 6 = Saturday). Validate at crontab.guru.
Option 2: UI-Based Setup
If you prefer clicks over YAML:
Go to Bolt in Paradime
Click Create Schedule
Set Trigger Type to Scheduled Run
Enter cron expression:
0 8 * * 0Select timezone (e.g.,
America/New_York)Add commands:
Configure notifications for
failedeventsClick Deploy
Figure 4: Weekly Bolt schedule execution flow — Python scan then optional dbt™ run.
Tip: Bolt auto-refreshes schedules from
paradime_schedules.ymlevery 10 minutes, or you can manually trigger a parse via Bolt → Parse Schedules.
Monitoring and Debugging
Once your schedule is running, you need visibility into what's happening — and what's failing. Paradime's Bolt gives you three levels of logs:
Log Level | Use Case | Detail Level |
|---|---|---|
Summary Logs | Quick health check — DinoAI-generated overview with warnings and suggested fixes | Low |
Console Logs | Detailed chronological record of all operations | Medium |
Debug Logs | System-level operations, dbt™ internals, performance tuning | High |
Accessing Logs
Navigate to Bolt in Paradime
Click on your
weekly_newsletter_cleanupscheduleOpen the Run History section
Click on a specific run
Scroll to Logs and Artifacts
The DinoAI-powered Summary Logs are genuinely useful here — if the Gmail API throws a token refresh error at 3 AM on Sunday, the summary will tell you what went wrong and suggest a fix before you've had your coffee.
Artifacts
Each run produces artifacts you can download:
Run SQL files — if your schedule includes dbt™ commands
Compiled SQL — useful for debugging model logic
Manifest files — for lineage and dependency tracking
CSV output — your
unsubscribe_candidates.csvfile
OpenClaw Monitoring
On the OpenClaw side, monitor your agent's Gmail operations with:
This checks Gateway status, channel connections, and active sessions. For deeper debugging:
The --verbose flag outputs detailed request/response logs, including Gmail API calls and token refresh events.
Troubleshooting Common Issues
1. GOOGLE_CREDENTIALS_JSON Not Found
Symptom: EnvironmentError: GOOGLE_CREDENTIALS_JSON environment variable is not set
Fix: Verify the variable is set in Paradime Settings → Workspaces → Environment Variables → Bolt Schedules. Only Admin roles can manage these. Also check: did you set it in the Code IDE section instead of Bolt Schedules? They're separate.
2. Gmail OAuth Token Expired
Symptom: google.auth.exceptions.RefreshError: Token has been revoked
Fix: OAuth refresh tokens can expire if:
You revoked access in Google Account Security
The Google Cloud project is in "Testing" mode (tokens expire after 7 days)
The app hasn't been used in 6 months
Solution: Move your OAuth consent screen to "Production" status (even for internal use) or re-authorize with /connect google in OpenClaw.
3. Missing Production Warehouse Connection (PARA-1000)
Symptom: PARA-1000: Missing production warehouse connection
Fix: Your Bolt schedule needs a production warehouse connection, even for Python-only jobs. Add one in Account Settings → Connections. See the Paradime Error List for details.
4. OpenClaw Gateway Not Running
Symptom: OpenClaw commands hang or return connection errors.
Fix: Verify the gateway is running:
If it's down, restart:
On macOS, ensure the daemon is installed:
5. Rate Limiting from Gmail API
Symptom: HttpError 429: Rate Limit Exceeded
Fix: The Gmail API has a quota of 250 quota units per user per second. Our script fetches up to 200 messages per category — if you have a massive inbox, add a sleep between API calls:
6. Schedule Not Triggering
Symptom: Your cron job never runs.
Fix: Check these in order:
Is the schedule
suspended: truein your YAML? Set it tofalse.Is the cron expression valid? Test at crontab.guru.
Is the YAML file on your default branch (main/master)? Bolt reads from the default branch only.
Try Bolt → Parse Schedules to force a refresh.
Figure 5: Troubleshooting decision tree for non-triggering Bolt schedules.
Wrapping Up
Here's what we built:
Component | Role |
|---|---|
Paradime Bolt | Schedules the Python script on a weekly Sunday cron. Manages environment variables securely. Provides monitoring, logs, and notifications. |
OpenClaw | Connects to Gmail via OAuth. Provides agent capabilities for email management. Handles credential storage and token refresh. |
Gmail API | Reads promotional/marketing emails. Exposes |
Python Script | Identifies newsletter candidates (unread, 90+ days, promotional category). Extracts unsubscribe links. Logs to CSV for human review. |
The beauty of this approach is that nothing runs on your laptop. The credentials live in Paradime's secure environment variable store. The schedule runs in Bolt's managed infrastructure. The Gmail API tokens refresh automatically. And you get a CSV every Sunday morning with a clean list of newsletters you can unsubscribe from — or not.
No local config pain. No cron jobs dying silently on a MacBook that went to sleep. Just a production-grade pipeline that keeps your inbox clean.
Next Steps
Add OpenClaw auto-review — Have the agent scan the CSV and flag high-confidence unsubscribe candidates (e.g., senders you haven't opened in 6+ months)
Load to your warehouse — Use a dbt™ model to track unsubscribe trends over time
Add a Slack notification — Post the candidate count to your team channel every Sunday
Extend to other categories — Add
category:socialorcategory:forumsto cast a wider net
The whole setup takes about 30 minutes. Most of that is the Google Cloud OAuth dance. Once it's running, you'll wonder why you ever manually clicked "unsubscribe" on 200 emails on a Saturday afternoon.
Your inbox deserves better. So does your time.
Further reading:

