Route RFC 5233 subaddressed mail to the base local part - #644
Conversation
user+tag@<platform domain> now routes to user's inbox and support+tag@<apex> to the corresponding operator system inbox: the base local part (before the first +) is what routes, so tags can never bypass the reserved or unknown-username checks. The full tagged address stays in the stored message's to_addresses so email.message.received package handlers can dispatch on the tag.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughAdds an exported ChangesSubaddressing feature
Estimated code review effort: 2 (Simple) | ~12 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
🔎 Preview deployed: https://kody-pr-644.kentcdodds.workers.dev Worker: Mocks:
|
Follow-up to #643: subaddressing (plus addressing) now routes. Mail to
{username}+{tag}@inbox.heykody.devreaches{username}'s inbox, andsupport+{tag}@heykody.devreaches the corresponding operator system inbox.Why
The Cloudflare zone-level subaddressing toggle only affects Cloudflare's own rule matching. Our catch-all hands the worker the full local part, and the worker previously looked up
username+tagas a literal username — which fails the username format check (+is not a valid username character) — so subaddressed mail bounced as "Unknown Kody email address." This unlocks a useful package pattern: anemail.message.receivedhandler that only processes mail addressed to its tag (e.g.{username}+invoices@…).What changed
splitEmailLocalParthelper inemail/address.ts: splits at the first+(user+a+b→ baseuser, taga+b).handleInboundEmailroutes on the base local part for both paths (user subdomain and apex system inboxes). All gates — reserved locals, unknown usernames, system-local matching — evaluate the base, so a tag can never smuggle past them.to_addresses(it comes from the parsed message, untouched), so package handlers can dispatch on the tag. No schema or payload changes needed.email-primitives.mdaddressing model documents the behavior and the package dispatch pattern.Tests
address.node.test.ts: splitter cases (no tag, tag, multi-+, empty tag, empty base).inbound.workers.test.ts:{username}+billing@routes to the same auto-provisioned inbox with the tagged address preserved into_addresses;help+tag@still rejects as reserved;missing+tag@still rejects as unknown.system-email.workers.test.ts:support+ticket-123@<apex>stores under the operatorsupportinbox with the tagged address preserved.npm run validategreen locally.System recap — composes existing primitives (low risk)
Mode: recap · Base:
main@cc9a9275· Head:022aec9eClassification: composes — inbound routing normalizes the local part before the existing lookups; no contracts, schemas, or payloads change.
Primitives touched
emailSystem map
Before / after
Summary by CodeRabbit
New Features
user+tag@domain, while still routing to the correct inbox.Bug Fixes
Documentation