Disposable email aliases for every signup — built into Safari.
ShieldMail generates a unique @shld.me alias whenever you're about to fill in an email field. OTPs and verification links appear directly in the extension popup, so your real inbox stays clean and your identity stays private.
You type into a signup form
↓
ShieldMail detects the email field (content script)
↓
Click the shield icon → alias generated (Cloudflare Worker API)
↓
Alias injected into the field
↓
Signup email arrives → Cloudflare Email Routing → Email Worker
↓
OTP / link extracted → Durable Object (10-min buffer)
↓
Popup shows the code — copy with one click
No email server to operate. No long-term storage. OTPs auto-delete after 10 minutes.
ShieldMail/
├── workers/email-router/ Cloudflare Worker (API + Email + Durable Objects)
├── extension/ Safari Web Extension (macOS + iOS, TypeScript + Preact)
├── ios/ Swift native container (XcodeGen project.yml)
├── assets/icons/ SVG shield+envelope icons
└── docs/ ARCHITECTURE.md · UX_SPEC.md · PRIVACY_POLICY.md
| Tool | Version |
|---|---|
| Node.js | ≥ 20 |
| pnpm / npm | any recent |
| Wrangler CLI | ≥ 3 |
| Xcode | ≥ 15 (iOS build only) |
| XcodeGen | ≥ 2.40 (iOS build only) |
cd workers/email-router
npm install # generates package-lock.json — commit this file
npm ci # use this for reproducible deploysEdit wrangler.toml:
- Replace
REPLACE_WITH_REAL_KV_NAMESPACE_IDwith your KV namespace ID - Replace
REPLACE_WITH_REAL_KV_PREVIEW_IDwith your preview KV namespace ID - Uncomment and update
routeswith your actual zone
Create a KV namespace if you don't have one:
wrangler kv:namespace create ALIAS_KVSet required secrets:
wrangler secret put HMAC_KEY # random 32-byte hex stringIn the Cloudflare dashboard:
- Enable Email Routing for each domain (
d1.shld.me…d5.shld.me) - Set a catch-all rule: Send to Worker →
shieldmail-email-router
The Worker's email(...) handler receives all incoming mail automatically.
wrangler deploy# Generate an alias
curl -X POST https://api.shld.me/alias/generate \
-H "Content-Type: application/json" \
-d '{"mode":"ephemeral"}'
# Poll messages (use the pollToken from the response)
curl "https://api.shld.me/alias/<aliasId>/messages?token=<pollToken>"cd extension
npm install # generates package-lock.json — commit this file
npm ci # reproducible install from lockfile
NODE_ENV=production npm run build # outputs to dist/ (no sourcemaps)- Open Safari → Settings → Advanced → Show features for web developers
- Develop → Allow Unsigned Extensions
- Drag
extension/dist/into Safari's extension list
For a signed build, wrap dist/ in a .app bundle using Xcode's Safari Web Extension template and sign with your Apple Developer certificate.
brew install xcodegen
cd ios
xcodegen generate # creates ShieldMail.xcodeprojOpen ios/ShieldMail.xcodeproj in Xcode, select your target device, and run. The app shows an onboarding screen with instructions to enable the extension in Safari Settings.
Settings → Safari → Extensions → ShieldMail → Allow
- OTPs and email content are held in memory for ≤ 10 minutes, then permanently deleted
- No analytics, no tracking, no third-party SDKs
- Alias addresses and metadata are stored locally on your device only
- The only third-party processor is Cloudflare (infrastructure)
Full policy: docs/PRIVACY_POLICY.md
See docs/ARCHITECTURE.md for the full system design, data-flow diagrams, privacy threat model, and milestone roadmap.
MIT