Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 

Repository files navigation

👉 PERSONAL PROJECT -- NOT ASSOCIATED WITH OR ENDORSED BY MONARCH MONEY OR GOOGLE 👈

Gmail Label Forwarder

Auto-forward Gmail messages to any email address — including addresses you don't own, like Monarch Money's receipts@my.monarch.com.

Gmail's built-in forwarding won't do this: it only forwards to addresses you can click a verification link for, and only forwards new mail. Add-ons like Email Studio can do it, but you have to grant a stranger's app full access to your mailbox.

This is a ~60-line script that lives in your own Google account and clicks "Forward" for you on a timer. Nobody else's servers, nobody else's OAuth. It also works on old mail, not just new mail.

It ships preconfigured for Monarch: destination set to receipts@my.monarch.com, work tracked under a monarch label in your Gmail sidebar. One example rule (Apple receipts) is included — add your own merchants to the list. Forwarding somewhere other than Monarch is a one-line change (DEST).

No coding required. If you can copy, paste, and click, you can set this up in about 10 minutes.

How it works (30 seconds)

  1. You list what to forward (e.g. "receipts from Apple") as plain Gmail searches at the top of the script.
  2. Every 10 minutes, the script finds matching mail, tags it with a label, forwards each message, then moves it to a "sent" label so it's never forwarded twice.

Setup

Step 1 — Create the script

  1. Go to script.google.com and click + New project. (Sign in with the Gmail account that receives the mail you want forwarded.)
  2. You'll see an editor with a file called Code.gs containing a stub. Select all of it and delete it.
  3. Copy the entire contents of Code.gs from this repo and paste it in.
  4. Edit the lines at the top:
    • DEST — already set to Monarch's receipts@my.monarch.com; change it only if you're forwarding somewhere else
    • FROM — your own email address (see Step 2). For Monarch this must be the email address on your Monarch account, or Monarch ignores the mail
    • The two label names are fine as shipped — they'll appear in your Gmail sidebar nested under a monarch parent label, created automatically
    • RULES — one line per kind of email to forward. These are ordinary Gmail searches, the same thing you'd type in the Gmail search box. Example: 'from:no_reply@email.apple.com subject:"Your receipt from Apple"'
  5. Press Cmd-S (Mac) or Ctrl-S (Windows) to save. Name the project anything, e.g. "Forwarder".

Step 2 — Make sure FROM is an address Gmail can send as

If FROM is just your normal Gmail address, you're done with this step.

If it's a different address of yours (a work alias, a custom domain), Gmail must have it registered: Gmail → ⚙️ → See all settingsAccounts"Send mail as". If it's not listed, click "Add another email address" and follow the verification email.

Step 3 — Authorize the script

  1. In the script editor toolbar, use the function dropdown to select listAliases, then click Run.
  2. Google will warn you the app is "unverified". That's expected — it's your script, created 2 minutes ago, and Google hasn't reviewed it. Click Advanced → Go to (project name) and allow it. You are granting access to your own account's script, not to any third party.
  3. Check the log at the bottom: your FROM address must appear in the list. If it doesn't, redo Step 2.

Step 4 — Dry run

Select testRules in the dropdown → Run. The log shows what each rule matched — nothing is sent. Adjust RULES until it matches what you expect (and nothing you don't).

Step 5 — Turn it on

  1. Select run in the dropdown → Run once. Check your Sent folder: the forwards should be there.
  2. Click the ⏰ Triggers icon in the left sidebar → + Add Trigger:
    • Function: run
    • Event source: Time-driven
    • Type: Minutes timer, every 10 minutes
    • Save.

That's it. No "Deploy" button needed — that's for web apps; timed triggers always run your latest saved code.

First run: processing your old mail

New mail takes care of itself — the trigger catches anything from the last 2 days (LOOKBACK). Your backlog needs one deliberate pass, two ways to do it (they combine fine):

Widen the lookback (for mail your rules match).

  1. Change LOOKBACK to how far back you want, e.g. 'newer_than:1y'
  2. Run testRules first — a dry run that shows what would be forwarded
  3. Run run manually; each pass processes 50 threads, so repeat until the execution log shows nothing new happening
  4. Change LOOKBACK back to 'newer_than:2d' when done

Manually label (for anything, rules or not). In Gmail, select any old emails and apply the queue label (monarch/monarch-receipt-forward). Age doesn't matter — the next run forwards everything wearing that label, then moves it to the -sent label. This is also how you handle one-off receipts that don't fit any rule.

⚠️ Quota warning. Google limits mail sent by scripts to roughly 100 recipients/day on free Gmail and 1,500/day on Google Workspace. A big backlog can hit this — sends start failing until the quota resets (daily, midnight US Pacific). Forward a backlog in chunks across days if needed; the 50-thread batch size is there to keep any single run tame.

Before bulk-forwarding hundreds of receipts, send one and confirm it actually arrives (see the next section) — don't queue a pile into an unproven pipe.

If the forwards never arrive (read this before giving up)

Strict receivers — Monarch included — silently discard mail that fails authentication. No bounce, no error. If your Sent folder shows the forwards going out but the other side sees nothing:

Using a plain @gmail.com address as FROM? You're fine — Google already authenticates those. The likely cause is the receiver's own matching rules (e.g. Monarch only accepts mail from the email address on your Monarch account — check Settings there).

Using your own domain? Your domain must publish SPF and DKIM, or every forward fails authentication:

  1. SPF — a TXT record on your domain: v=spf1 include:_spf.google.com ~all (Never create a second record starting with v=spf1 — if one exists, add to its include: list instead.)
  2. DKIMadmin.google.com → Apps → Google Workspace → Gmail → Authenticate email → Generate new record → add the shown TXT record at google._domainkey.yourdomain.com in your DNS → click Start authentication. Without this, Google signs your mail as ...gappssmtp.com, which fails the receiver's domain-alignment check even when SPF passes.
  3. Prove it worked: send one fresh forward, open it in your Sent folder → ⋮ → Show original. The summary table must say SPF: PASS and DKIM: 'PASS' with domain yourdomain.com.

Check your DNS from a terminal:

dig +short TXT yourdomain.com
dig +short TXT google._domainkey.yourdomain.com

Troubleshooting

  • Script runs but nothing forwards — your RULES matched nothing (re-run testRules), or a label-name mismatch: run listLabels and make sure a filter isn't feeding a differently-named label. The script creates its own labels, so a typo quietly creates a second, empty one.
  • Mail goes out from the wrong addressFROM isn't a registered send-as alias; the option is silently ignored. Redo Step 2, verify with listAliases.
  • Duplicates — only happens if you manually re-label an already-processed thread; even then the script skips messages you sent, so it re-sends only the original.
  • Daily limit — Google caps script-sent mail at ~100 recipients/day for free Gmail, ~1,500/day for Google Workspace. Backfilling hundreds of old threads can hit this; it resets daily.
  • Receiver-side matching — services that attach receipts to transactions (Monarch, etc.) may discard receipts that match no transaction. Test with a receipt for a purchase that actually appears in the service.

FAQ

Is this safe? The script runs under your own Google account, visible at script.google.com, and its whole source is the one file you pasted. It sends mail as you and moves labels; it can't do anything you didn't paste.

Do I need Gmail filters? No. RULES in the script replaces them (and unlike filters, works on old mail and travels with this repo). But filters work too: point any filter at the queue label (LABEL_NAME) and the script will forward whatever the filter catches.

Why not just use Gmail's forwarding? It refuses addresses you can't verify, like receipts@my.monarch.com, and never touches old mail.

License

MIT

About

Auto-forward Gmail to any address (Monarch Money receipts, etc.) with a tiny Apps Script in your own account. No add-ons, no third-party mailbox access. Not associated with Monarch Money.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages