Email audit via Gmail labels
Every email FinMatch sends through SendGrid carries a self-copy BCC to a
plus-addressed alias of the From mailbox. A Gmail filter on each From
mailbox routes the self-copy to a dedicated Sent (audit) label, giving
us a searchable audit trail without standing up any new infrastructure.
This is the only audit channel for FinMatch outbound mail right now. The
admin Emails page (/emails) shows what gets sent; the Gmail label shows
the actual sent copy — useful for verifying delivery, message
formatting, and timing.
How it works
SendGrid sends from FinMatch's MTAs, which means outbound mail does
not appear in the Sent folder of the From Gmail account — Google only
sees a mail in Sent when Google itself sent it. The plus-addressing
trick (address+tag@domain) routes a copy back to the same mailbox via
BCC; Google then accepts that copy on inbound and a filter labels it.
+----------------------+ +-----------+ +----------------------+
| merchant-api or | send | SendGrid | deliver | recipient inbox |
| finance-assistant |-------->| |-------->| (merchant contact |
+----------------------+ +-----+-----+ | or james@...) |
| +----------------------+
| bcc
v
+-----------+
| Gmail of |
| the From |
| mailbox |
+-----+-----+
|
v filter
Sent (audit)
Address aliases used
| Sending service | From | Audit BCC |
|---|---|---|
| Merchant management templates (merchant-api) | support@finmatch.io | support+audit@finmatch.io |
Monitoring alerts (/admin/send-monitoring-alert) | support@finmatch.io | support+audit@finmatch.io |
| Per-merchant config drift regression (template send) | support@finmatch.io | support+audit@finmatch.io |
| Finance assistant customer enquiry receipt | finance.assistant@finmatch.io | finance.assistant+audit@finmatch.io |
The audit BCC for monitoring alerts is hardcoded in
cloud-run/merchant-api/index.js (MONITORING_ALERT_BCC) so it cannot
drift if Cloud Run env vars change. The other audit BCCs are driven by
the SENDGRID_BCC env var on each Cloud Run service (set in the
deploy workflows).
Gmail filter setup
Run these once per mailbox. You must be signed in as the mailbox owner (or have delegated access with filter permissions).
support@finmatch.io
-
Open Gmail as
support@finmatch.io. -
Settings (gear) -> See all settings -> Filters and Blocked Addresses -> Create a new filter.
-
In the To field enter:
support+audit@finmatch.io -
Click Create filter.
-
Tick:
- Skip the Inbox (Archive it)
- Mark as read
- Apply the label: create a new label called
Sent (audit) - (Optional) Never send it to Spam
-
Click Create filter.
finance.assistant@finmatch.io
Repeat the steps above, signed in as finance.assistant@finmatch.io,
with the To field set to:
finance.assistant+audit@finmatch.io
Use the same label name Sent (audit) so the audit experience is
consistent across both inboxes.
Verifying the filter
- Trigger a known send. Easiest options:
- Admin -> Emails -> Merchant management -> open a merchant and send the Header snippet template.
- Manually run
.github/workflows/merchant-config-monitoring.ymlviaworkflow_dispatchin GitHub Actions.
- In the relevant Gmail inbox, click the
Sent (audit)label in the left sidebar. - Confirm the new mail appears, and that it is not in Inbox.
If the mail lands in Inbox instead of (or as well as) the label, the filter's Skip the Inbox tick was missed — edit the filter and add it.
Limitations
- Open / bounce status is not visible from the audit label. Gmail only knows about the BCC self-copy, not the recipient's delivery outcome. For deliverability investigations use the SendGrid dashboard directly.
- The audit copy is not a perfect facsimile. Gmail rewrites some headers on inbound; treat it as proof of send + body content, not as a forensic source.
- Plus-addressing on the From mailbox could be filtered out by a recipient's mail server in the unlikely event the BCC alias is ever exposed externally. It is not, currently — the BCC is only used for internal self-routing.
Related
- Admin UI: /emails — accordion of every email-sending path with its From / To / Reply-To / BCC.
- Merchant API:
cloud-run/merchant-api/index.js- Pinned monitoring constants near the top of the file.
- Finance Assistant:
cloud-run/finance-assistant/index.jssendEnquiryEmail()andbuildEnquiryEmail().