Recipe 021

One Pantry: The $0 Email Centralization Recipe

Email is where a small company's outside world arrives — and it sits scattered across inboxes no agent can read. We built the fix in one afternoon: a $0 Gmail collector, three accounts, every mail landing as a plain file. Here's the recipe, plus three decision rules — including when not to build.

In the last automation recipe we made the case that office automation starts with one boring folder — ingredients first, heat second. Fair question we got back: which ingredient first?

Easy. Of everything on that map, email is the heaviest crate in the walk-in. At a small company, almost everything the outside world sends you arrives by mail: invoices, statements, official letters, the vendor thread where the real decision happened. And all of it sits locked inside per-person inboxes that no agent can see.

So this week we stopped theorizing and built the email half of the pantry. One afternoon of vibe coding. Three Gmail accounts. Sixty-five mails flowing into plain markdown files. Total cost: $0.00 — and not "free tier until you grow" free. The Gmail API has no usage fees; we never even attached a billing account.

What we built (and tasted first)

A few small Node.js scripts, standard library only — no npm install, no framework to rot in six months:

  • Enroll. Each mailbox owner clicks through one Google consent screen (read-only scope, nothing else). The script catches the callback on localhost and stores a token per account.
  • Collect. For every enrolled account: fetch recent inbox mail and save each message as work-data/mail/{account}/date-subject.md, with From / To / Date headers on top and a plain-text body below.
  • Mask before disk. A regex gate strips national-ID and card-number patterns before anything is written. The pantry should be useful, not radioactive.
  • Increment. A state file remembers which mail IDs were already fetched. Second run: zero duplicates, a few seconds.
  • Offboard. One command tells Google to revoke an account's token and deletes it locally. Consent you can't withdraw isn't consent.

Speed bumps, honestly plated: we ate a 403 access_denied because we forgot to add the account as a test user on the OAuth consent screen. Then we learned Google's testing mode quietly kills refresh tokens after seven days — the fix is the "Publish app" button. The scary unverified app warning stays, but for your own accounts that's fine, and the tokens stop expiring.

The three decision rules

Building it is what showed us where the real edges are. What survived became three rules — the whole methodology fits on an index card:

Rule 1 — Small crew (up to roughly ten people): consent-based collection, but the company owns the accounts. Don't chase personal inboxes. Create the accounts centrally, enroll each one in the collector, then hand them to staff — and set one written policy: no password changes; if one happens, re-enroll. Here's the twist that makes this workable: Google revokes Gmail-scope tokens the moment an account's password changes. Sounds like a bug; it's a feature twice over. A policy violation announces itself — collection fails loudly for exactly one account. And offboarding is a single password reset: mail access and data collection both cut in one move.

Rule 2 — Past ten people or so: stop being clever and rent the platform. Google Workspace, or whatever your region's equivalent is. At that size the subscription is a rounding error next to revenue, and the grown-up version comes included: admin-level delegation lets the collector read mail without anyone's password or token mattering at all, so Rule 1's entire policy dissolves. Clever scripts are for when you're small; boring platforms are what you graduate to.

Rule 3 — Never self-host the mail server itself. This one tempts every builder eventually. Receiving mail is genuinely a weekend project now — sending is the trap. Spam reputation, IP warmup, one blocklist entry and your invoices stop arriving at customers. Deliverability is a profession, not a feature. Rent the battle-tested mailbox; build only the thin collector on top. Knowing what not to cook is part of the recipe.

Why this crate first

Because the moment mail lands in the folder, layer 2 lights up. "Read this week's mail across all three inboxes and brief me — what needs a reply, what's an invoice, what can wait" stops being an integration project and becomes a one-sentence prompt. That briefing is the next dish on our stove, and the collector above is everything it needs.

Order up

Paste this into your agent — it builds the single-inbox version on your own Gmail, tonight:

I want to centralize my Gmail into plain files so you can cook with
them later. Build me a tiny collector — Node.js, built-in modules
only, no npm installs.

1. First, walk me through Google Cloud Console step by step:
   new project, enable the Gmail API, OAuth consent screen
   (external), add my address as a test user, create a
   "Desktop app" OAuth client. I'll paste the client ID and
   secret into a local .env file.
2. Before writing any code, add .env, tokens*, and work-data/
   to .gitignore.
3. Auth script: open the consent page, catch the localhost
   callback, save tokens locally. Read-only Gmail scope only.
4. Collect script: fetch the last 7 days of my inbox and save
   each mail as markdown in work-data/mail/ with From / Date /
   Subject headers, preferring the plain-text body.
5. Add a masking step that strips anything matching national-ID
   or card-number patterns BEFORE writing to disk.
6. Keep a state file of seen mail IDs so re-runs only fetch
   what's new.

Then run it and show me the first file.

Twenty minutes, most of it Google Console clicking. When the first mail appears as a markdown file, you'll feel it: your inbox just became an ingredient.

How many inboxes does your work actually live in right now? Count them, then tell us at @AgentKitchenHQ.

Hungry for more?

New recipes land in your inbox as they leave the kitchen. No spam, unsubscribe anytime.