Expensent
Expensent
PricingIntegrationsGuidesAboutContactGet Started
Menu
PricingIntegrationsGuidesAboutContactHelp
Privacy PolicyTerms of Service
Theme
Get Started
Home/Guides/Gmail to Expensify Workflow

Gmail to Expensify: The Complete Workflow Guide

A Gmail-specific guide to what actually works with Expensify: manual forwards, the forwarding verification trap, Apps Script, Google Workspace routing caveats, and practical ways to deal with older receipts already buried in your inbox.

By ilios Galil · Founder, Expensent

Published March 27, 2026 · Updated April 22, 2026

In This Guide

  1. 1. The Gmail → Expensify problem: ongoing plus backfill
  2. 2. How Expensify receives mail (quick recap)
  3. 3. Method A — Manual forward
  4. 4. Method B — Gmail filters: the verification trap
  5. 5. Method C — Google Workspace routing rules
  6. 6. Method D — Apps Script and Gmail API
  7. 7. Method E — Inbox-aware tools
  8. 8. Which method for which user
  9. 9. Backfilling years of historical receipts
  10. 10. Troubleshooting Gmail-specific quirks
  11. 11. Frequently Asked Questions

1. The Gmail → Expensify problem: ongoing plus backfill

If you've landed here, you probably already know the destination: receipts@expensify.com. Forwarding a single receipt there is well documented in our main Expensify email receipts guide. What that guide doesn't cover — and what this one does — is the real-world operational problem of connecting Gmail (personal or Google Workspace) to Expensify at scale, on an ongoing basis, and retroactively across years of old mail.

There are two jobs to solve, not one:

  1. 1.Ongoing: every new receipt from now on — every time Stripe, AWS, Shopify, or your SaaS vendor sends an invoice, it should end up in Expensify without you having to remember to forward it.
  2. 2.Backfill: the three years of receipts already in your inbox — the moment you sign up for Expensify, there's a pile of historical invoices already sitting in Gmail that your accountant would love to have.

Native Gmail features are built around job #1 and mostly fail at it. None of them solve job #2 at all. That asymmetry is what this guide exists to untangle.

2. How Expensify receives mail (quick recap)

A two-sentence refresher so the rest of this guide makes sense. Expensify ingests receipts through receipts@expensify.com, and it only accepts mail from senders whose address is registered as a primary or secondary login on an Expensify account. SmartScan then reads the attached receipt or forwarded receipt content and turns it into an expense under the sender's account.

Full walkthrough of the single-receipt flow: prerequisites, file format and size limits, Copilot delegation, and the step-by-step forward are all in How to email receipts to Expensify. This page assumes you already have that basic forwarding working and want to scale it up.

3. Method A — Manual forward

The baseline. Open the receipt in Gmail, hit Forward, type receipts@expensify.com, send. Done. SmartScan handles the rest and the expense appears in your Expensify account a few minutes later.

Pros: zero setup, no permissions to beg for from IT, works identically on personal Gmail and Google Workspace, and every forward is intentional so you never accidentally send Expensify something that isn't a receipt. Cons: it depends on you remembering to do it every single time, which is exactly the kind of thing humans forget. If you only get a handful of receipts a month and you already live in your inbox, Method A is genuinely fine. Most people need something more durable.

Pro tip:turn on Gmail's keyboard shortcuts (Settings → See all settings → General → Keyboard shortcuts on), then use f to forward the open message. It takes the forward from a 30- second detour to a 3-second one, which is the difference between doing it and not.

4. Method B — Gmail filters: the verification trap

The next thing everyone tries is a Gmail filter with Forward it to set to receipts@expensify.com. In theory this is perfect: narrow the filter to from:(billing@stripe.com OR receipts@uber.com), set the action to forward, and you're done. In practice, you will get stuck on the very first step.

The verification trap, step by step

  1. 1.Gmail will not let a filter forward to any address that isn't already on your verified list (Settings → Forwarding and POP/IMAP). Personal Gmail caps the list at 20 forward-to-address filters.
  2. 2.To add receipts@expensify.com, Gmail sends a confirmation code email to that address and asks you to paste it back into Settings.
  3. 3.receipts@expensify.com is an ingestion endpoint. There is no inbox to log into, no way to read the code, no human on the other side to forward it back to you.
  4. 4.Dead end. The verification step cannot be completed, so the destination cannot be added, so the filter cannot be created.

This is not a bug, a misconfiguration, or a missing permission. It's how Gmail is designed: the verification handshake exists to prevent malicious filters from silently exfiltrating your mail, and there is no user-facing way to opt out. Every personal @gmail.com account hits this wall.

Mark this one as "does not work" and move on. You'll see countless forum threads recommending Gmail filters for this. They all end with the original poster discovering the verification trap and never updating the thread.

5. Method C — Google Workspace routing rules

If your Gmail account is actually a Google Workspace account, there is an admin-level mail-routing tool in the Admin Console. It matters enough to mention here, but it is not the clean native answer many people hope it is.

Where it lives

Google Admin Console → Apps → Google Workspace → Gmail → Routing. You need super-admin or delegated Gmail admin permissions. The two rule types worth knowing:

  • •Recipient rules can add an envelope recipient to any message matching an address pattern (for example, BCC receipts@expensify.com on every message delivered to billing@yourdomain.com).
  • •Content compliance rules can match on sender, subject, headers, attachment type, or body text, and apply an action like "add more recipients" pointing at receipts@expensify.com. Useful when a Workspace admin wants to route invoice-like mail, but still not a guaranteed Expensify attribution fix.

The attraction is obvious: no per-user verification handshake, centralised policy management, and routing rules that can scope to a shared billing alias or an entire department. The catch is just as important: Google says routed or forwarded mail still appears to come from the original sender, while Expensify ties emailed receipts to linked sender addresses. That makes Workspace routing a mail admin tool, not a clean documented Expensify workaround. It also requires admin access you may not have, and the matching syntax is substring- and regex-based rather than semantic — so a routing rule for subject:invoice will happily forward the marketing email whose subject line is "Invoice your friends for a free month".

Corporate IT note: routing rules are considered a mail compliance control and usually require a change ticket. Expect your IT team to ask who owns receipts@expensify.com, whether a compliance footer is required, and whether the rule needs logging. Also expect to test whether the routed message still lands correctly in Expensify under the right linked sender.

Crucially, like every Gmail-native method, routing rules only apply to new mail going forward. They do not retroactively forward the old invoices already in everyone's inbox. Treat Method C as an admin caveat, not the main recommendation.

6. Method D — Apps Script and Gmail API

Method D is the DIY developer option. You write a Google Apps Script that uses GmailApp.search() to find matching messages and MailApp.sendEmail() (or GmailMessage.forward()) to push them to receipts@expensify.com. A time-driven trigger runs the script every 5, 10, 15, 30, or 60 minutes. No verification handshake required — the script sends as you, from your own mailbox, so Expensify sees an authenticated login as the sender.

Sketch of the script (illustrative, not production)

function forwardReceipts() {
  var query = 'label:unprocessed has:attachment ' +
              '(subject:invoice OR subject:receipt)';
  var threads = GmailApp.search(query, 0, 20);
  threads.forEach(function (thread) {
    thread.getMessages().forEach(function (msg) {
      msg.forward('receipts@expensify.com');
    });
    thread.removeLabel(GmailApp.getUserLabelByName('unprocessed'));
    thread.addLabel(GmailApp.getUserLabelByName('sent-to-expensify'));
  });
}

Pros: works on personal Gmail (unlike Method C), can handle both ongoing forwards and — with a widened query and a higher batch size — a bounded historical backfill, and costs nothing if you stay inside Google's free quotas. Cons: you are now a script maintainer. When Google deprecates a method, or a vendor changes its subject format, or you hit a quota, the script stops silently.

Quota warning: consumer Gmail gives Apps Script roughly 100 MailApp.sendEmail() recipients per day; Google Workspace gives most plans around 1,500. Each forwarded receipt counts as one recipient, subject to Google's current published quota. That is fine for day-to-day forwarding; it is a serious limitation for backfilling three years of invoices in one pass. You will have to resume across multiple days if the historical queue is big.

The Gmail API route (instead of Apps Script) gives you finer control and cleaner OAuth scopes (gmail.send, gmail.readonly), but the quota and maintenance picture is the same. Method D is a solid fit if you already write code for a living and genuinely enjoy owning one more tiny system. For everyone else, skip to Method E.

7. Method E — Inbox-aware tools (Expensent)

Method E is the practical answer for almost everyone who landed on this page. It's an inbox-aware tool that connects to Gmail via OAuth — not through a Gmail filter — so the verification trap from Method B simply doesn't apply. It also gives you a cleaner way to review older inbox results than rebuilding filters or scripts from scratch. Expensent is the tool we build; the rest of this section is specific to it.

How Expensent connects Gmail to Expensify

  1. 1.OAuth into your Gmail account (personal @gmail.com or Google Workspace). No app password, no filter, no admin ticket.
  2. 2.Paste receipts@expensify.com as the destination. Expensent forwards as you, from your own authenticated address, so SmartScan attaches the expense to your Expensify account.
  3. 3.Review what it found in the dashboard — grouped by next action: ready to forward, download from portal, needs review, false positive.
  4. 4.Forward any invoice with one click, or create a rule from an existing email in one click so the next invoice like it goes through automatically.
  5. 5.Backfill in one pass — pick a date range in Expensent (a few months, a year, or several years) and let it work through history. No Apps Script quota to ration across days.

Pros: sidesteps the verification trap, works on personal Gmail and Workspace identically, handles backfill (the one thing none of Methods A–D can do well), one-click rule creation from a real example, no scripts to maintain. Cons: it's a third-party tool, it's paid, and it asks for a Gmail OAuth scope to read and send mail on your behalf — the usual trade-off for any OAuth-based inbox tool.

If you want to go deeper, the Expensify integration page walks through the feature set, and our sibling guide on never missing a receipt in Expensify covers the longer-term habit side of the problem.

8. Which method for which user

Side-by-side, across the five methods:

MethodPersonal GmailWorkspaceOngoingBackfillSetup
A. Manual forwardYesYesManual onlyOne by oneNone
B. Gmail filtersBlocked (verification)Blocked (verification)———
C. Workspace routingNoYes (admin)AutomaticNoAdmin review
D. Apps ScriptYesYesEvery 5–60 minQuota-limitedDeveloper
E. ExpensentYesYesAutomaticHistorical reviewShort setup

Personal Gmail vs. Google Workspace in one line: personal Gmail users have Methods A, D, and E available. Workspace users can also test Method C with admin help, but it is a routing tool with sender-attribution caveats, not a clean documented Expensify fix. Method B is a dead end for everyone.

9. Backfilling years of historical receipts

Backfill is the job Gmail itself refuses to do. Filters and routing rules only act on incoming mail; they will not go back and re-send messages you received last year. If you just signed up for Expensify and want the last 24–36 months of receipts to actually live there, here are the realistic options in order of effort.

Step 1 — Find the receipts with a Gmail search

Start with a query like this in the Gmail search box. Tune it for your own senders.

has:attachment filename:pdf
(subject:(invoice OR receipt OR "order confirmation")
  OR from:(billing@ OR invoices@ OR receipts@))
newer_than:3y

Refine until the result set looks mostly like actual receipts. Then you have a choice about how to get them to Expensify.

Step 2 — Pick a backfill method

  • •Manual— works, but at one forward every ~5 seconds, 500 receipts is about 40 minutes of repetitive clicking. Doable for an evening, painful for years of history.
  • •Apps Script — can iterate your saved search in batches, but Google's daily send quota (~100 on consumer Gmail, ~1,500 on Workspace) forces you to spread the backfill across days. Good for small backfills, bad for big ones.
  • •Inbox-aware tool (Expensent) — not bound by Gmail's Apps Script quota, skips messages it has already processed, lets you review candidates before forwarding, and is the only option that pairs backfill with ongoing forwarding out of the box.
  • •Hybrid— use the tool for historical review and ongoing forwarding, or pair it with a custom script if you already maintain one.

Whichever method you pick, do the backfill first, then switch on ongoing forwarding second. If you reverse the order, the tool will forward an invoice while it's also being backfilled, and you'll end up chasing duplicates in Expensify. Related reading: SmartScan troubleshooting for when backfilled receipts come through with missing data, and Expensify for accountants if you're doing this on behalf of a client rather than yourself.

10. Troubleshooting Gmail-specific quirks

Forwarded receipt arrives without the original attachment

Cause:Gmail sometimes strips attachments when you forward inline instead of "as attachment," particularly on mobile. Fix:use the desktop web client and choose "Forward" (not "Forward as attachment") — Expensify's SmartScan actually prefers inline HTML plus the original PDF, which the desktop client preserves.

"Message clipped — view entire message"

Cause:Gmail truncates very long HTML bodies (>102 KB) in the web view, and some forwards include only the visible portion. Fix:open the original message, click "view entire message" once to expand, then forward — or attach the receipt PDF directly instead of relying on inline HTML.

Receipt lands in Gmail's Promotions tab and gets missed

Cause:Gmail's Categories classifier is not invoice-aware and regularly routes legitimate receipts to Promotions. Fix:either turn off Category tabs entirely (Settings → Inbox → Categories), or create a Gmail filter matching the vendor and set "Never send it to Spam" plus "Categorize as: Primary." Filters can still categorize — they just can't forward to an unverified address.

Expensify returns "unrecognized sender"

Cause: the forward was sent from a Gmail alias, a delegated mailbox, or a Workspace send-as identity that is not registered on your Expensify account. Fix:open Expensify → Settings → Account → Profile → Contact Methods and add the sending address as a secondary login. Verify it, then re-forward.

11. Frequently Asked Questions

Can I forward historical Gmail receipts to Expensify in bulk?
Not with any native Gmail feature. Gmail filters and Workspace routing rules only act on new mail going forward — they cannot retroactively forward a message that already sits in your inbox. Your options for backfill are: (1) manually forward matching emails from a Gmail search, (2) write a Google Apps Script that iterates GmailApp.search() results and calls MailApp.sendEmail() until your daily quota runs out, or (3) use an inbox-aware tool like Expensent to review historical inbox results and forward the receipts that matter. Backfill is the single biggest gap in the native Gmail toolkit.
Why won't Gmail let me add receipts@expensify.com as a forwarding address?
Gmail's Settings → Forwarding and POP/IMAP flow requires you to add a destination address and then confirm a code that Gmail emails to that destination. receipts@expensify.com is an ingestion endpoint — it accepts mail but there is no human inbox you can log in to in order to retrieve the verification code. That is why the forwarding setup fails at the confirmation step. The same restriction applies to any Gmail filter whose action is "Forward it to" — Gmail only lets you pick from addresses that have already been verified.
Do Google Workspace routing rules require admin access?
Yes. Recipient and content compliance rules live under Admin Console → Apps → Google Workspace → Gmail → Routing, and only Workspace super admins or delegated Gmail admins can create them. They may help with mail routing, but Google says routed or forwarded messages still appear to come from the original sender, so this is not a clean documented Expensify sender-attribution fix. Personal @gmail.com accounts have no admin console and cannot use this approach at all.
What Gmail search operators find invoice and receipt emails?
A good starting query is has:attachment filename:pdf (invoice OR receipt OR "order confirmation" OR statement) newer_than:3y. You can tighten it with from: clauses for known billing senders (for example from:(stripe.com OR paypal.com OR intuit.com)), or widen it with subject:(invoice OR receipt). Save the query as a Gmail search URL so you can re-run it before each backfill pass. Keep in mind that these operators search Gmail, not Expensify — you still have to get the matching messages into receipts@expensify.com somehow.
Does Gmail's "Promotions" tab block receipts from reaching Expensify?
Not directly. Gmail's Category tabs (Primary, Promotions, Updates, etc.) are purely a display grouping in the Gmail UI — they do not change what filters, routing rules, or OAuth-connected apps can see. An Apps Script using GmailApp.search() or an inbox-aware tool using the Gmail API will read messages regardless of which tab they land in. The only time tabs matter is when you are manually forwarding and simply do not notice a receipt because it was routed to Promotions. A quick fix is to create a filter that marks receipts as Primary.
Will Expensify accept receipts forwarded from a Gmail alias (+tag) address?
Expensify ties forwarded receipts to the sender's registered login. Register your base address (user@gmail.com) as a primary or verified contact method before forwarding — Gmail's plus-addressing is not officially documented by Expensify. If you rely on plus-addressing to segment work from personal mail, add the plus variant as a secondary login in Account Settings → Profile → Contact Methods before you start forwarding.
Does auto-forwarding break SPF/DKIM in a way Expensify cares about?
Gmail auto-forwarding rewrites the envelope sender, which can affect authentication signatures. Expensify does not publicly document the exact rules at its inbound endpoint, but in practice forwards from a verified login normally land correctly. Where it can matter is duplicate detection — if the same receipt arrives via both the vendor and your forward, Expensify may create two expense records.
Can I forward from a delegated Gmail mailbox to Expensify?
Gmail delegation (Settings → Accounts → Grant access to your account) lets a delegate read and send mail on behalf of the owner, including forwarding. The forwarded message is sent from the owner's address, so Expensify will attribute the receipt to the owner's login, not the delegate's. If you want the delegate (for example, an external bookkeeper) to be the submitter, use Expensify's Copilot feature, which gives them delegated access to your Expensify account directly — see Expensify's Copilot documentation for the current setup path.
What's the daily email quota for a Gmail Apps Script forwarder?
Google publishes a MailApp.sendEmail() daily quota of 100 recipients per day for consumer @gmail.com accounts and 1,500 recipients per day for most Google Workspace plans, subject to Google's current documented limits. An Apps Script that forwards every receipt counts against that quota one recipient at a time, so a busy inbox on a consumer account can hit the ceiling quickly. Quotas reset on a rolling 24-hour window. If your backfill exceeds the quota, the script throws an exception mid-run and you will need to resume the next day — which is why scripts are not a great fit for bulk historical imports.
How do I stop forwarding a vendor once I've set up a rule?
It depends on which method you picked. For Gmail filters, open Settings → Filters and Blocked Addresses and delete the filter. For Google Workspace routing, open Admin Console → Apps → Gmail → Routing and remove the rule (allow ~20 minutes for propagation). For an Apps Script, disable or delete the time-driven trigger in the script editor. For Expensent, open the forwarding rule in the dashboard and delete or pause it — the next invoice from that vendor stops being forwarded immediately.

Skip the Gmail verification trap entirely

Connect Gmail to Expensent. Forward any invoice with one click, create a rule so future similar emails go through automatically, and review older inbox results without relying on Gmail filters, Apps Script, or admin routing.

Get Started

Works with personal Gmail and Google Workspace. See pricing.

Expensent
Expensent

Finds your invoices. Forwards them your way.

ProductPricingIntegrationsHow it WorksComparevs Manual Forwardingvs Gmail Filters
Works WithExpensifyQuickBooksXeroFreshBooksZoho ExpenseSAP ConcurWaveRampBILL.comDext
Guides
QuickBooksExpensifyXeroFreshBooksBrexRampSAP ConcurDextBILL.comWaveZoho ExpenseDivvyEmburseHubdocPleoRydooRevolut Business
CompanyAbout UsContactHelp CenterPrivacy PolicyTerms of ServiceLegal Information

© 2025–2026 Expensent. All rights reserved.

Stripe Climate badgeExpensent contributes a portion of revenue to remove CO2 from the atmosphere.