Your whole mailbox in one downloadable file

Someone exports their inbox to migrate accounts or to keep a copy before a server move. The tool spits out one .mbox file, they drop it in a folder to grab it later, and that folder turns out to be one the web server serves. Now the entire mailbox is a public download and nobody knows.

An mbox is exactly what it sounds like: a complete mailbox in a single file. Every message the account ever received or sent, one after another, headers and bodies and attachments inline. Password-reset links. One-time codes. Invoices with names and addresses on them. Support threads where someone pasted a credential to get help. It's all in there because that's the format's whole job, to hold a mailbox in one place.

The reason that's worse than it sounds is the format itself. An mbox is plain text. Message follows message follows message, and you don't need an email client to read it. You need grep.

What a stranger pulls out of it

Open the file and the structure is trivial. Every message starts on its own line, the body is right there beneath the headers, and there's no index to defeat and no client to install. A stranger searches for reset, for verify, for code, for invoice, and the matching lines fall out in order.

The reset links are the sharp edge. Plenty of them are still valid, because plenty of apps issue tokens that don't expire for hours or days, and some never expire until they're used. A live reset link is an account, no password required. The OTPs are the same story when the window hasn't closed. Then there's everything that needs no trick at all: the invoices give you names, billing addresses, and amounts; the support threads give you whatever people were careless enough to paste; the headers alone map out who the account talks to. One file is a privacy breach and an account-takeover kit at the same time.

request
GET /inbox.mbox HTTP/1.1\nHost: yoursite.com
response
HTTP/1.1 200 OK
Content-Type: application/octet-stream
From [email protected] Mon Jan 06 09:14:22 2026
Subject: Reset your password
https://yoursite.com/reset?token=...
(thousands more messages below)
That From line with no colon is the mbox separator. It's how you know this isn't one email, it's the whole archive.

How it ends up servable

Nobody publishes a mailbox on purpose. It happens in the same messy moments that leak everything else. You export your mail to move providers and stage the file where the deploy can reach it, then forget the deploy directory is also the public one. You back up a shared mailbox before a server migration and leave the copy next to index.html. A script writes archive.mbox into a folder you assumed was private. The server doesn't know the file is secret. A request for it is a request for a static file, and the server hands over the bytes.

The names are predictable, which is the whole problem, because crawlers carry a wordlist of exactly these:

  1. https://yoursite.com/mail.mbox
  2. https://yoursite.com/inbox.mbox
  3. https://yoursite.com/archive.mbox
  4. https://yoursite.com/backup.mbox

A 404 on all of them is the result you want. A 200 with a real Content-Length means the mailbox is downloadable right now. And once it's downloaded, the rest is local and silent.

$ yoursite.com
$ curl -sI yoursite.com/inbox.mbox | head -1
HTTP/2 200
$ curl -s yoursite.com/inbox.mbox | grep -c '^From '
4127 (messages)
reset links, OTP codes, attachments, all readable
Two commands, then it's offline: grep counts the messages, grep reads them, no email client and no login involved.

Checking it from the outside

Whether a mailbox is downloadable is decided entirely by what your server hands out, so you can settle it the same way a crawler would, from the curb, without going anywhere near your mail. The danger is that nobody on your team would ever request /inbox.mbox on purpose, so the file sits there for months unnoticed.

SurfaceCheckr requests the common mbox names against your domain and watches what comes back. The part that keeps it honest is the confirmation. A 200 isn't enough, because soft-404 catch-alls return 200 for everything, and a normal From: header field would match a lazy check. So the scanner confirms on the actual RFC 4155 mbox separator: a From line, with a space and no colon, anchored to the start of a line, the way every message in a real mbox begins. That line is too specific for a fake page or an ordinary header to fake, which is what makes the check FP-safe. It reads only enough to see the separator, never the messages, and it isn't a pentest of your app. It answers one question: is your mailbox sitting in the web root with the door open.

If the path was reachable, the file has been public for as long as it's been deployed, so treat it that way. Delete it, then move any mail exports out of any web-served directory and into storage with no public access. And assume every secret those messages carried is already gone: rotate the reset tokens and credentials, and force a password reset on any account whose reset link or OTP was in that file. The same misconfiguration that exposes a leftover backup.sql or a public .env file exposes this too, so it's worth checking all three while you're at the doormat.

Find it before someone else does.

Paste your domain. The grade and issue count are free, and you'll see in a couple of minutes exactly what's reachable from outside.