Read, export and repair Outlook .pst and .ost files on Windows. No Outlook, no
licence, no per-mailbox fee, no fake progress bar. MIT licensed, free forever.
Two self-contained executables. Run them, close them, delete them. No installer, no service, nothing left behind — and neither one ever asks for a password, because a PST password is not a lock.
Delete both of a PST's B-tree roots and it still recovers every message, byte for byte —
then writes the whole thing back out as a clean file Outlook can open. At any size, since
v0.2.0: a 726MB rebuild takes about three seconds, and a sweep of a 400MB file went from 14
seconds to 0.4. Point it at an .ost and it writes a .pst instead — v0.3.0 — which is
the other thing there is an industry selling.
New in v0.4.0: search the whole mailbox, subject, sender and message body; export one folder or one message instead of all of it; rich-text messages readable in the window rather than only after export; and Outlook 97–2002 ANSI files, which used to be refused outright and now open, export and convert to the modern format.
New in v0.5.0: search in the window no longer freezes it on a big mailbox — it runs in the background with a progress count, like export and repair — and Japanese, Chinese, Greek, Cyrillic and every other code page Windows knows now reads correctly in the window and in search, instead of only in an export.
v0.5.1 is the first release shaped by somebody else's real recovery. A technician converted a customer's OST — mail that had been deleted from the server — found pstfree was the one converter of several that kept the messages and the folder tree, got the mail back, and then traced exactly why Outlook did not like the result (issue #1). Both problems were in the converted store, and both are fixed: it no longer asks for a password nobody set, and Outlook now opens straight into the recovered folders instead of an empty mailbox.
Download the two executables — no installer, no runtime, nothing to build. Or build it yourself, it takes one command.
Sister project to bulkhead, futureburn, opennote and vncfree — same attitude: find the Windows payware, read the published spec it is hiding behind, give it away. Why.
There is an entire industry selling PST tools for $50–$300. "PST Repair." "OST to PST Converter." "PST Password Recovery." Kernel, Stellar, SysTools, DataNumen, Aryson — dozens of near-identical products with the same SEO blogspam, the same three-pane screenshot, and the same free trial that shows you your own email and then asks for money before it will save it.
Here is what they are selling:
- The file format is published by Microsoft. MS-PST is a public, versioned, several-hundred-page specification. Not reverse-engineered, not leaked — downloadable.
- The "password" is not encryption. A PST password is stored as a CRC32 of the
password. The block obfuscation uses a fixed table with no key at all, identical
whether the file has a password or not. MS-PST section 5 calls the two ciphers
"keyless" in as many words. The products charging $30–$50 to "recover" a PST password
are charging you to skip an
ifstatement. pstfree reads a password-protected file and never asks; there is no code in it that could. - "OST to PST" is a format conversion, and the format is the published one. An
Outlook 2013 OST is the same file the specification describes, with 4K pages and its
blocks zlib-compressed. Reading it out and writing it back as a PST is work, but it is
ordinary work against a document anyone can download.
--rebuilddoes it. - Repair is the only genuinely hard part — and the part the marketing is vaguest about.
If anyone tries to sell you this software, they're scamming you. Walk away.
Classic Outlook's opt-out phase starts April 2026; enterprises stop being able to defer in
March 2027; support ends entirely in Q2 2029. New Outlook is a web client — it does not
mount PST files, it imports from them. scanpst.exe, the only free repair tool, ships
with classic Outlook and leaves on the same schedule.
So twenty-plus years of archives, legal holds and ex-employee .ost files are about to
have no first-party reader at all. That is the moment the $300 tools are waiting for.
Better if something free is standing there instead.
libpff is the serious one — the deepest format coverage anywhere, and the reference this project measures itself against on every release. XstReader is the closest existing free Windows GUI. java-libpst, libpst and freepst are all real work by people who got there first, and freepst supplies the public test fixtures used here.
None of them is a bad project and none of this is a complaint about their code. The gap is
not "can a PST be parsed" — that was solved years ago. The gap is that nothing free
seriously attempts repair: libpff recovers deleted items from an intact file, which is
a different and also impressive problem. When scanpst.exe gives up, the free world
currently gives up too, and that is the entire reason the payware has a business. The
longer version is in docs/prior-art.md.
Take pstfree-gui.exe and pstfree.exe from the
latest release and run them, or
build them with cargo build --release — there is one dependency and no build script.
pstfree-gui.exe archive.pst the window
pstfree.exe archive.pst --tree the command line
pstfree.exe archive.pst --verify what is wrong with it
pstfree.exe archive.pst --find invoice every message that mentions it
pstfree.exe mailbox.ost --rebuild archive.pst an OST, written out as a PST
pstfree.exe old.pst --rebuild new.pst an ANSI PST, written out as Unicode
This is a password-protected PST. No password was set, supplied or requested:
> pstfree.exe passworded.pst --tree
(root)
Top of Personal Folders
Inbox
Calendar
Contacts (2)
...
Freebusy Data (1)
Here is a PST with both B-tree root pages overwritten with zeroes — as dead as
scanpst can describe — read, and then written back out as a working file:
> pstfree.exe torn.pst --list
Block index unreadable. Carved 184 blocks out of the file itself.
Node index unreadable. Swept 128 nodes from 27 surviving pages.
date folder from subject
2016-08-02 00:27 Calendar Unknown Test appointment [22533 bytes]
2014-05-25 13:58 Contacts Unknown test dist list [1164 bytes]
> pstfree.exe torn.pst --rebuild fixed.pst --salvage
Wrote fixed.pst: 128 node(s), 184 block(s), 125952 bytes.
libpff refuses to open torn.pst and reads all four messages out of fixed.pst.
| command | what it does |
|---|---|
--tree |
the folder tree, with message counts |
--list |
every message: date, folder, sender, subject |
--props <nid> |
every property on one node, named where the file names them |
--find <text> |
every message whose subject, sender or body mentions it |
--export <dir> [--format eml|mbox|msg] [--folder <name>] |
write the mail out, all of it or one folder |
--rebuild <out.pst> |
write a clean copy with a fresh index — from an .ost, a converted .pst |
--verify |
check every checksum, and what a sweep would recover |
--salvage |
on any command: ignore the header's index and rebuild it |
--version |
which build this is |
Reading — Unicode PST and OST, and ANSI PST. Folder tree, messages, properties, attachments, embedded messages, plain/HTML/compressed-RTF bodies, calendar and contacts. Named properties resolved through the file's own map. A message with only an HTML body has its markup taken off and is read in the window like any other — not rendered, which would mean hosting a browser in a program whose whole promise is that there is nothing to install. Password ignored, because there is nothing there to ignore.
Search — --find, and the box in the window: subject, sender and body, one
case-insensitive substring, across every folder at once. It works the same on a file whose
index had to be rebuilt by sweeping as on an intact one, which is the only version of this
feature worth having in a recovery tool. The result says which field matched, because most
hits are in the body and a row with nothing visibly matching on it otherwise looks broken.
Export — .eml per message with attachments inline, .mbox per folder, or .msg with
the MAPI properties kept — all of it, one folder and everything under it, or the one
message you are looking at. Nothing is invented: no timezone the file does not record, no
character set re-guessed. Nothing stops: one unreadable message is counted and named, and
the rest are written. See docs/exporting.md.
Repair — the differentiator. Validate every checksum and say in plain language what is
wrong; rebuild the node and block B-trees from surviving pages; carve blocks straight out
of the file with no index at all; and write the result back out as a clean .pst, at any
size. See docs/repair.md.
Convert — --rebuild on an .ost writes a .pst. The 4K-page format Outlook 2013 and
later use for an OST stores blocks compressed and up to 64KB each, where a PST's are plain
and hold 8176 bytes, so nothing can be copied: every data stream is decoded and laid out
again. libpff reads the source OST and the converted PST and gets 46 folders, 3 messages
and 202 properties out of each, identical id for id and byte for byte. The same pass
converts an ANSI PST — Outlook 97 to 2002 — to the modern Unicode format, and lifts the
2GB ceiling that generation of files is stuck behind. See
docs/converting.md.
The window does all of it too. Folders, messages and bodies; a search box; export in any
of the three formats, or of one folder or one message; repair to a new .pst; and a
plain-language report of everything wrong with the file rather than a count of it. The long
jobs run on their own thread with a live count, so a mailbox-sized repair neither freezes
the window nor looks like a hang on the command line.
It also, as of v0.4.0, looks like a program from this decade: the common controls Windows
has shipped since 2001 rather than the ones from 1995, the font the rest of the system is
using rather than the stock bitmap one, an icon, a toolbar, and a window that is sharp on a
scaled display. None of that needed a build script or a dependency — the manifest is
embedded by the linker and the icons are drawn from geometry by
asset-forge's ui_icons.py, the same generator
opennote's toolbar uses.
Not in scope — writing to a live Outlook profile, MAPI, Exchange, and new Outlook's own undocumented local store. Reading a file is a different job from being a mail client.
Stated plainly, because a repair tool that overstates itself is the thing this replaces.
- ANSI PST (Outlook 97–2002) has never been tested against a real file. It reads, exports and converts, and every ANSI-specific difference — the 512-byte header, the 32-bit ids, the 12-byte trailers with the id and the checksum the other way round, the subnode block with no padding — is covered by tests. But no public ANSI PST exists; the fixture those tests use is one this repo writes itself from MS-PST 2.2.2.6 and 2.2.2.7. That is real evidence and it is not the same evidence as a file Outlook 97 wrote. If you have one, it is the single most useful thing anybody could send.
--rebuildalways writes a 512-byte-page Unicode PST. Hand it an Outlook 2013 OST and it converts: every block decoded, inflated and laid out again as a PST stores them. That is a new file rather than a copy, so it says so, and the check that backs it is libpff reading both — see below.- An OST's sync-state nodes are carried across, not dropped. Types
0x14–0x19are the OST's own record of its conversation with a server, and mean nothing in a PST. They are kept because discarding what you do not understand is the wrong instinct in a recovery tool, and because nothing has shown they do any harm. 83 of the 308 nodes in the test OST are these. - Outlook wants SCANPST run over a rebuild before it will open it. The allocation maps go out marked invalid, and Outlook reports that as a file not closed properly. SCANPST fixes it in seconds. Writing valid maps would remove the step, and is next. Known because a converted OST has now been opened in Outlook for real (see below).
- Where FMap and FPMap pages recur is still unknown. A rebuild works around it instead of answering it — it keeps every slot the four map pages could occupy clear, in every section of the file, which costs 0.8% and cannot be wrong in the direction that destroys data. Settling it properly needs a PST over 125MB written by Outlook.
- Attachment extraction has never seen a real attachment, because none of the three public fixtures has one.
- An HTML body is reduced to text, not rendered. Tables become their cells in order,
images leave only their
alttext, and a link keeps its text and loses its URL. Export to.emland open that in a mail client to see the message as it was sent. - Cyclic encoding has never decoded a real file — no fixture uses it.
- Recovery has only been tested against damage this repo inflicted itself. There is no public corpus of broken PSTs; every route was checked and none exists.
- The Enron corpus does not change any of the above. The CMU release is 517,401 messages of maildir text converted out of Notes and Outlook, with attachments stripped and every message flattened to ASCII — no PST in it, and nothing Outlook wrote. What it can and cannot test, and why no tool can settle the recent argument about its authenticity from that release, is in findings.
The full list, including the places the first reading of the spec was wrong, is in docs/findings.md.
68 tests, against a real PST, a real 2013 OST and a real password-protected PST — the
public fixtures from freepst, fetched by tests\fetch-fixtures.ps1 — plus an ANSI PST
this repo builds itself, because there is no public one to fetch. Test files are never
committed, because real PSTs contain real mail; the tests skip rather than fail when they
are absent.
The check that counts is libpff, the reference implementation nearly every other PST tool wraps. On intact files the two agree exactly — not just on message counts but on 686 properties across 10 messages, id for id. On six damaged files libpff opened none and pstfree opened all six. Details, plus the fuzzer and the one piece of ground truth a PST can offer about its own recovery, in docs/testing.md.
- docs/repair.md — how recovery works, and writing the file back out
- docs/converting.md — OST to PST, and the one thing that makes it hard
- docs/exporting.md —
.eml,.mbox,.msg, and the rules - docs/testing.md — libpff head-to-head, fuzzing, ground truth
- docs/findings.md — what the spec got right, and what it omits
- docs/roadmap.md — milestones, and what is left
- docs/prior-art.md — the survey that justified building this
Rust, and nothing else. One dependency (miniz_oxide, for the zlib-compressed blocks an Outlook 2013 OST uses) plus windows-sys for the Win32 bindings. No build script, no vendored C, no runtime to install.
cargo build --release
cargo test
- Microsoft, for publishing MS-PST openly. This project is a reader written from the
specification; the
mpbbCryptsubstitution table insrc/crypt.rsis the one piece of data taken from it directly, and is validated on the way in. - libpff (Joachim Metz), for being the reference every claim here is checked against.
- freepst (Bob Rudis), for the public PST/OST test fixtures.
- XstReader, java-libpst and libpst, for getting there first.
- miniz_oxide and windows-sys, the only two dependencies, both MIT.
| bulkhead | Block-level backup, recovery and certified secure erase for Windows. |
| futureburn | CD, DVD and Blu-ray burning, ripping and image mounting. |
| opennote | The WordPad Windows removed, plus .docx and fillable PDFs. Its icon generator draws this window's toolbar too, which is why the two look related. |
| vncfree | A VNC client and server with no subscription and no ad-gated download. |
Same method every time: read the published spec, call the OS API that is already there, ship one executable, MIT. Why that is worth doing at all is written down in PHILOSOPHY.md.
pstfree is free and staying that way: no trial, no locked features, no nag screen. If it got your mail back and you'd like to say thanks, you can leave a tip. Pay whatever you like; the suggested amount is just a suggestion. A star or a good bug report helps just as much.
MIT. See LICENSE. Free forever, for everyone. The whole point is that nobody pays for this.
