Privacy
Inbox Unpack reads email files in your browser. No message, attachment, header, subject, address, search term or file name is sent anywhere. This page describes the mechanisms that make that true rather than merely intended, so you can check them yourself.
There is no upload endpoint
This site has no API routes, no server actions, no database and no file storage. It is a set of static pages and JavaScript. There is nothing to upload a message to, which is a stronger property than a promise not to.
The browser enforces it, not just the code
Every response carries a Content-Security-Policy including:
connect-src ‘self’— the browser refuses any fetch, XHR, WebSocket or beacon to another origin. A bug that tried to post your mailbox somewhere would be blocked, not merely discouraged by review.form-action ‘none’— nothing on this site can submit a form anywhere at all, including a form smuggled in through a message body.img-src ‘self’ data: blob:— every remote image in every message is blocked at the network layer, whatever the sanitiser did or did not do.frame-ancestors ‘none’— this site cannot be framed by another, so nothing can be overlaid on the message you are reading.object-src ‘none’,base-uri ‘self’.
The end-to-end tests record every network request the page makes during a full conversion and assert that none of them go to another origin, that none carry a request body, and that no request URL contains a file name, an address or an attachment name.
Why there is no “load remote images” button
Most viewers offer one. This one does not, and the reason is worth stating plainly rather than burying.
To fetch an image from a sender’s server, the page’s img-src directive would have to allow https:generally. A Content-Security-Policy is set per response, for the whole document; it cannot be narrowed to “only the message the reader just clicked on”. So the switch would not be a per-message permission at all — it would permanently widen the policy that is currently the strongest guarantee on this site, for every visitor and every message.
That is a bad trade for a convenience. Instead, every remote resource a message references is listed for you: the full URL, which element referenced it, the host, and whether it has the shape of an open-tracker with a per-recipient identifier. You can see precisely what would have been fetched, and who would have learned that you opened the message, without any of it happening. If you need the images rendered, download the original file — its bytes are preserved exactly — and open it in a mail client, knowing what that will tell the sender.
Analytics
The site includes Vercel Analytics, which counts page views. It is called once per page load with no arguments. No custom events are sent, and there is no code path anywhere in this project that passes a sender, a recipient, a subject, a Message-ID, a body, a sample of text, an attachment name, a file name, a file size or any other file metadata to it. The privacy end-to-end test asserts this against every request the page makes, not only against the analytics call.
There are no cookies, no accounts, no local storage of message content, and no fingerprinting. The one thing stored locally is your light or dark theme preference.
Fonts and libraries
Everything is served from this origin. The PDF font is vendored into the site at build time, pinned by SHA-256, and re-verified in your browser before it is used. No CDN, no third-party origin, no external font service is contacted at any point.
What happens to a file you open
It is read into memory, parsed, and discarded when you close the tab or press Start over. Nothing is written to disk except the files you explicitly download. Object URLs created for downloads are revoked once the browser has acted on them, so nothing is pinned in memory after you are done with it.
Malicious messages
Opening a suspicious message here is the case this was built for. Message HTML is sanitised, then rendered in an iframe with an empty sandbox attribute — no scripting, no same-origin access — whose document carries its own default-src ‘none’ policy, inside a page whose own policy blocks off-origin requests. Four layers, each of which would have to fail. See How it works for the detail.
Changes
If any of this ever stops being true, this page changes first. It describes the current behaviour of the deployed site, not an intention.