Owning Your Inbox: Archiving Years of Email Without Losing Any of It

Owning Your Inbox: Archiving Years of Email Without Losing Any of It

The problem: provider storage fills up, and old email matters

If you’re running low on provider storage, worried about losing important history, or just want years of email under your own control instead of a company’s, the fix is the same: download it yourself, verify it landed safely, and only then clear it off the provider. Email Archiving is the pipeline I built to do exactly that, repeatably.

What it does

mbsync pulls a mailbox via IMAP into a local staging folder, which then mirrors to NAS/backup storage — a deliberate two-stage transfer rather than syncing directly to the NAS, so a network hiccup mid-sync never touches the provider side, and the staged copy can be checked over before anything gets deleted. Only once the backup’s confirmed intact does an IMAP delete script clear the archived range from the provider, freeing quota without losing anything. Once archived, the mailbox becomes a plain folder of files fully under my control — directly searchable, or reachable by an AI agent for conversational search (the same underlying pattern as the SMS archive project).

The mistake I made on my own first run, and the actual recommendation

I downloaded my entire history in one shot the first time. In hindsight, year-by-year (oldest first) is clearly the better call — slower up front, but it keeps each archive chunk small enough to actually search later instead of producing one giant undifferentiated dump. That’s the real recommendation in the writeup now, learned the hard way rather than assumed from the start. Provider-side rate limits reinforce the same lesson: Gmail caps IMAP downloads around 2.5GB/day, so even a single year can span more than one run for a heavy inbox — planning for that up front beats assuming one sitting finishes it.

The credential problem, and a genuinely nasty debugging session

The app password (never the real account password — required once 2FA is on, and separately revocable) needs to stay out of a plaintext config file. mbsync supports this directly via a PassCmd option that runs a helper script pulling the password from a password manager at runtime instead of a static Pass line. On Linux, though, if the sync tool runs under AppArmor confinement, its shipped profile likely won’t allow executing a shell to run that helper — mine silently failed with “Permission denied” until I traced it to AppArmor denials in journalctl -k and added a local profile override. That’s a real, non-obvious debugging path: the failure gave no useful error at the tool level, and the actual cause was a full layer down in the OS’s confinement system.

The step I’m honest about not having proven yet

The eventual goal is a yearly scheduled run — sync, verify, delete, notify, entirely automated. As of this writing that hasn’t actually been tested end-to-end: the first backup was a manual one-time pass, and a full year hasn’t yet passed to trigger a real scheduled cycle. I’d rather say that plainly than claim something’s automated when only the plan for automating it exists — “I’m going to automate this” is easy to say and, on its own, changes nothing until it’s actually run once on its own schedule.

What it demonstrates

A verify-before-you-delete discipline on a one-way, provider-side-destructive operation, a willingness to admit and correct a real mistake (the one-shot-not-year-by-year download) rather than gloss over it, and a debugging instinct that didn’t stop at “permission denied” but traced it down to the actual OS-level cause. It’s also a plain example of being honest about a project’s actual state — flagging what’s proven versus what’s still just planned, which matters as much in a portfolio as it does in a real production system.

Part of the Homelab AI Blueprints series — see all nine blueprints for building and operating a self-hosted, AI-agent-run home server.


Discover more from Michael Allen

Subscribe to get the latest posts sent to your email.