Security is not a feature here. It is the licence to operate.
We hold other people's email — password resets, invoices, contracts, medical appointments. Here is exactly how it is isolated, encrypted, accessed and audited.
Four independent isolation layers
Application: every handler resolves the workspace from the verified credential and never from user input. Database: row-level security with FORCE, so a query missing its tenant clause returns nothing. Cryptographic: a per-workspace key bound by additional authenticated data, so a ciphertext moved between workspaces fails to decrypt. Provider: separate sending containers and separate DKIM keys per customer domain.
Object storage holds ciphertext only
Message bodies and attachments are encrypted before they touch storage, with a per-object key derived from the workspace key, which is itself wrapped by a root key held at a different provider. Possession of the object plus the storage credential is not sufficient to read anything.
Crypto-shredding
Deleting a workspace destroys its key. Every object belonging to it becomes permanently unreadable in the same instant, including copies in backups and replicas — a verifiable answer to “delete all my data” that object-by-object deletion cannot give.
No standing access
There is no standing production database access for anyone. Human access requires a stated reason, a second approver, a time-boxed credential and a session recording. Every decryption is written to an immutable audit entry with who, what, when and from where.
The vulnerability classes we design against
Every outbound fetch of a user-supplied URL goes through a guarded client that resolves DNS itself and rejects private, link-local, loopback and metadata ranges — including IPv6 and IPv4-mapped forms — re-checking after each redirect. The click redirector resolves destinations from server-side state, never from the URL. Header values are CR/LF-stripped before MIME assembly. The template evaluator has no file access, no network access and no arbitrary property traversal.
Tested, not asserted
For every resource type there is a test asserting that workspace B receives a 404 — never a 403 — for workspace A's object, via the API, via the download service, and via a direct database query under B's role. These tests block merges. So do the attachment tests: reading a raw object yields unparseable bytes, a download ticket cannot be redeemed twice, and a tampered ciphertext fails rather than returning partial data.
Who we are defending against, and with what.
| Adversary | Goal | Primary defences |
|---|---|---|
| Opportunistic attacker | Credential stuffing, relay abuse | Mandatory 2FA, rate limits, no open relay, breached-password checks |
| Spammer or abuser | Use us as a sending platform | KYC tiers, warm-up ladder, content scanning, thresholds below the provider's |
| Competitor or scraper | Enumerate customers and lists | Opaque prefixed ids, row-level security, no enumeration endpoints |
| Targeted attacker | Read one specific customer's mail | Envelope encryption, no standing access, audit, hardware-key MFA |
| Compromised customer account | Send spam, exfiltrate contacts | Anomaly detection, per-mailbox caps, export limits, session invalidation |
| Malicious insider | Bulk data access | Break-glass with dual approval, immutable audit, key-service rate limits |
| Supply chain | Malicious dependency | Pinned dependencies, SBOM per release, signed images, restricted egress |
| Compelled or breached provider | Read stored content | Ciphertext only; the root key is held at a different provider entirely |
We must be the most correctly configured domain we host.
- mailhaap.com publishes DMARC at p=reject, MTA-STS and TLS-RPT.
- No open relay, ever. Submission always requires authentication, and automated relay tests run hourly against our own hosts.
- TLS is mandatory for submission and IMAP. Inbound MX is opportunistic with MTA-STS offered — refusing plaintext inbound would silently drop legitimate mail from misconfigured senders.
- DKIM keys are 2048-bit, one per customer domain, stored envelope-encrypted, rotated annually with a 14-day overlap.
- SPF, DKIM, DMARC and ARC are verified on every inbound message, and the results are surfaced in the interface rather than hidden in the spam score.
- [email protected] is monitored with an SLA and feeds directly into the abuse workflow.
Where we are, and when.
| Milestone | Timing |
|---|---|
| Security page, DPA, sub-processor list | Gate 2 |
| External penetration test, full scope | Before general availability |
| Private bug bounty, then public | Gate 4 |
| SOC 2 Type I | Gate 5 |
| SOC 2 Type II | Gate 5 + 6 months |
| ISO 27001 | Evaluated at Gate 6 |
Restore drills run monthly, timed, into a scratch environment — an untested backup is not a backup. Target recovery time is four hours; target recovery point is fifteen minutes.
Found something? Tell us before you tell anyone else.
Report vulnerabilities to [email protected]. We acknowledge within one working day, we do not threaten researchers, and we credit you in the fix unless you ask us not to.