Posted on ::

I moved to Fastmail some time ago, but like many of us I kept one foot in Gmail: Fastmail's "fetch" tool keeps duplicating my incoming Gmail into my Fastmail account — a backup, an escape plan, and a bridge for family members who are not quite ready to leave Gmail yet.

But there was a hole: the labels I add on Gmail after the initial migration (manually, or with my rules) were never reproduced on Fastmail. So I wrote gmail-to-fastmail, a single Go binary that incrementally syncs your Gmail labels to Fastmail.

How it works🔗

It reads your Gmail via IMAP (read-only, X-GM-LABELS), and applies the labels on Fastmail via JMAP (a more efficient variant of IMAP), in batches of 10 000. Progress is kept in a local SQLite database, so each run resumes where the last one stopped — once caught up, a run takes about 15 seconds. Perfect for cron.

What it does🔗

  • Labels mapped: your Gmail labels become Fastmail labels, created on demand, never deleted.
  • Categories: Gmail's system categories (Inbox, Updates, Social...) become underscore-prefixed labels _Inbox, _Updates, _Social...
  • Trash: emails deleted on Gmail are not deleted on Fastmail, just labelled _Trash — a backup of your deleted mail, with an easy way to "empty the bin".
  • Local cache: unchanged emails are skipped, so Fastmail's API is left in peace.
  • Mirror mode: -m/-M optionally imports emails missing on Fastmail, not just labels. There are more options, detailed on the GitGub repository.

Installation, Usage, and more info🔗

See the GitHub repository.

Why Go?🔗

Because it is a single self-contained binary with no runtime dependencies — you know my thing about that. No Python env, no node_modules, no nothing. Free (MIT).

Also, AI co-written: don't like, don't use.

Table of Contents