Privacy Architecture
At a glance
MailMail has no server that stores or relays email. Your iPhone connects directly to your mail provider (Gmail, Outlook, Naver…), summaries and translations are produced by Apple's on-device models on the iPhone, and only summary cards cross to the watch. The one server we run is a wake-up beacon that tells the app "there may be new mail" — and all it knows is a push token.
1. What never leaves the device
| Data | Where it lives | Protection |
|---|---|---|
| Email bodies | Local database on iPhone/iPad (SwiftData) | Encrypted until first unlock (iOS file protection). Never sent to the watch, a server, or logs |
| AI summaries (headline, key points, labels) | Local DB → watch card | Generated on-device by Apple Foundation Models. No external AI API calls |
| Translations | Memory only | Apple Translation (on-device) → discarded right after summarizing. Never stored |
| App passwords · OAuth tokens | iPhone Keychain | Device-only (iCloud Keychain sync blocked). Never sent to the watch or a server |
| Sender · subject | Local DB → watch card | The watch card carries sender name, subject and summary only — it has no body field |
| Profile avatar photo | App-private folder on iPhone | 256px thumbnail only, original discarded. No backup, no sync |
| Personalization learning data | iPhone local | Senders stored as hashed tokens only (no plaintext email). Pro sync ships weights and hashes, end-to-end encrypted |
2. What leaves the device — the complete list
This is the entire set of outbound data. If it is not in this table, it is not sent.
| To | What | Why |
|---|---|---|
| Your mail provider (Gmail, Naver, Daum, work IMAP) | IMAP login, mail fetch, read/archive flags | Direct TLS connection to your own mailbox. We are not in the path |
| Microsoft (Outlook) | OAuth sign-in, Graph API mail reads | Same — direct. Tokens stay in Keychain |
| MailMail wake-up beacon (Cloudflare Worker) | { token, env } — the APNs push token and environment, exactly two fields | Sends a content-free push about every 10 minutes so the app can sync in the background. Any extra key is rejected with 400 |
| Same beacon (Outlook users) | subscription ID, push token, environment, verification hash | Where Microsoft posts "new mail" notifications. No mail content included |
| Apple (App Store) | Purchases and receipts | StoreKit. Verified on-device |
| Apple (iCloud, Pro, optional) | Encrypted personalization profile blob | Keeps your learning when you switch devices. Contents = weights, sender hashes, category affinity. Key lives in iCloud Keychain — we cannot decrypt it |
| Your own Reminders app | Extracted to-do title + mail subject | Pro feature, only when you tap. Never the body |
Verify it yourself: put the app behind Proxyman or Charles. The only requests to mailmail.app are /v1/register and /v1/unregister (plus /v1/graph/* for Outlook), and their bodies contain nothing but a token string.
3. What we don't do
- No sign-up, no account. You never give us your email address.
- No ad SDK, no analytics SDK, no crash-reporting SDK. Crash and performance diagnostics come from Apple MetricKit and are tallied on-device as counts only.
- No cloud AI. On devices without Apple Intelligence we do not fall back to a cloud model — we honestly show that summaries are unavailable.
- No body logging. Even debug builds contain no code that writes an email body to a log.
- No bodies to the watch. The watch card type has no body field at all.
4. How the code enforces it
Enforced by types and link structure, not by policy — so it is hard to break by accident later.
- Boundary types — the watch card, the beacon registration payload and the Reminders request are separate structs with no field a body could fit in. Unit tests fail if a body ever passes through.
- Cloud inference code is not linked — an experimental cloud-inference interface lives in a separate package that the shipping app does not link. It is not a runtime switch; it does not compile in.
- The server rejects surplus data — the beacon validates an exact two-field schema and returns 400 on any extra key.
- Device-only Keychain — credentials use
AfterFirstUnlockThisDeviceOnly, so they never sync via iCloud Keychain. - A fresh AI session per email — summary sessions are created and discarded per message, so one email's content never bleeds into another's prompt.
5. Honest limits
- Your mail provider (Google, Microsoft, Naver) of course has your mail. MailMail simply adds nothing in between.
- AI summaries require iPhone 15 Pro or later (Apple Intelligence). That is the cost of not having a cloud fallback.
- The on-device model and translation engine are Apple's. We verified they run on-device; their internals follow Apple's public documentation.
- Outlook goes through Microsoft's sign-in screen, which follows Microsoft's policies.
Changelog
- 2026-09-11 — First publication (as of build 24).