# PST Email Extractor A command-line tool that scans a directory for Outlook PST files and extracts the metadata of every email — subject, sender, recipients, date, size, attachments count, and message class — into individual CSV files. --- ## Table of Contents 1. [Features](#features) 2. [Requirements](#requirements) 3. [Installation](#installation) 4. [Usage](#usage) 5. [Output Format](#output-format) 6. [How It Works](#how-it-works) 7. [Performance Notes](#performance-notes) 8. [Troubleshooting](#troubleshooting) 9. [Platform-specific pypff Installation](#platform-specific-pypff-installation) 10. [Project Structure](#project-structure) 11. [FAQ](#faq) --- ## Features - **Batch processing** – drop any number of `.pst` files in a folder and run once - **Resilient extraction** – corrupt messages are skipped gracefully; processing continues - **Rich metadata** – exports 8 fields per message including attachment count and message class - **Progress bars** – real-time per-file progress via `tqdm` - **UTF-8 output** – fully compatible with Excel, Google Sheets, and any modern CSV tool - **Iterative folder traversal** – avoids Python recursion limits on deeply nested PST archives - **Human-friendly summaries** – per-run statistics on success / failure counts --- ## Requirements | Dependency | Version | Purpose | |---|---|---| | Python | ≥ 3.8 | Runtime | | `tqdm` | ≥ 4.66 | Progress bars | | `pypff` / `libpff-python` | any | PST file reading | > **Note:** `pypff` wraps the native C library **libpff**. Installation varies by platform — see [Platform-specific pypff Installation](#platform-specific-pypff-installation). --- ## Installation ### Step 1 – Clone or download the project Place `Extract.py` and `install_dependencies.py` in the same directory. ### Step 2 – Run the dependency installer ```bash python install_dependencies.py ``` This script will: 1. Upgrade `pip`, `setuptools`, and `wheel`. 2. Install `tqdm` via pip. 3. Attempt to install `libpff-python` / `pypff` via pip. 4. Print platform-specific instructions if the automatic install fails. ### Step 3 – Verify ```bash python -c "import pypff; import tqdm; print('All good!')" ``` --- ## Usage ### Basic usage (process PST files in the script's own directory) ```bash python Extract.py ``` ### Specify a directory ```bash python Extract.py /path/to/pst/folder ``` ```powershell # Windows PowerShell python Extract.py "C:\Users\You\Desktop\PST_Files" ``` ### Example output ``` 📂 Working directory: /data/pst_files ================================================================================ 🔍 SEARCHING FOR PST FILES ================================================================================ ✓ Found 3 PST file(s) 📁 PST Files: 1. archive_2021.pst (1,204.3 MB) 2. archive_2022.pst (876.1 MB) 3. personal.pst (312.7 MB) ================================================================================ 🚀 PROCESSING ================================================================================ ──────────────────────────────────────────────────────────────────────────────── 📊 1/3 | ✓ Done: 0 | ❌ Failed: 0 | ⏳ Remaining: 2 🔄 archive_2021.pst 📊 Counting messages in archive_2021.pst … ✓ 42,817 messages found Processing archive_2021.pst: 100%|████████| 42817/42817 [02:14<00:00] ✓ Written 42,817 rows | Errors skipped: 3 ✅ Saved → archive_2021_email_list.csv (42,817 rows) ``` --- ## Output Format For each input file `.pst`, a corresponding `_email_list.csv` is created in the **same directory**. ### CSV columns | Column | Description | Max Length | |---|---|---| | `Folder` | Full folder path inside the PST (e.g. `Inbox\Projects\2022`) | 200 chars | | `Subject` | Email subject line | 500 chars | | `From` | Sender name and/or email address | 200 chars | | `To` | Semicolon-separated recipient list | 1000 chars | | `Date` | Delivery or submit time in `YYYY-MM-DD HH:MM:SS UTC` | — | | `Size` | Estimated message size in bytes (sum of body and headers) | — | | `Attachments` | Number of attachments | — | | `MessageClass` | MAPI message class (e.g. `IPM.Note`, `IPM.Appointment`) | 100 chars | ### Example rows ```csv Folder,Subject,From,To,Date,Size,Attachments,MessageClass Inbox,Q3 Budget Review,Alice Smith ,bob@example.com,2023-09-01 14:22:10 UTC,18432,2,IPM.Note Sent Items,Re: Proposal,Bob Jones ,alice@example.com,2023-09-02 09:05:44 UTC,4210,0,IPM.Note Calendar,,Alice Smith ,,2023-10-10 09:00:00 UTC,1024,0,IPM.Appointment ``` --- ## How It Works 1. **Discovery** – `find_pst_files()` uses `glob` to locate all `.pst` files in the given directory. 2. **Counting** – Before extraction, `count_total_messages()` recursively counts all messages so `tqdm` can show an accurate progress bar. 3. **Traversal** – `process_folder()` uses an **iterative stack** (not Python recursion) to walk the full folder tree, guarding against deep nesting and corrupt nodes. 4. **Extraction** – `extract_email_info()` wraps every individual attribute access in a `try/except` so one corrupt property never aborts the whole message. 5. **Writing** – Results are streamed directly to a UTF-8 CSV file via `csv.writer`, keeping memory usage flat regardless of PST size. 6. **Error recovery** – Failed messages are counted and reported in the summary but do not interrupt processing. --- ## Performance Notes - **Memory** – The extractor streams rows directly to disk, so even a 50 GB PST file won't exhaust RAM. - **Speed** – Processing speed depends on your disk I/O. SSDs can process ~5,000–15,000 messages/min; spinning disks are 3–5× slower. - **Large recipient lists** – Recipient lists are capped at 100 entries and 1,000 characters to avoid giant rows. - **Iterative traversal** – The folder walker uses an explicit stack instead of recursion, making it safe for PST archives with hundreds of nested folders. --- ## Troubleshooting ### `ModuleNotFoundError: No module named 'pypff'` Run `python install_dependencies.py`. If the automatic install fails, see [Platform-specific pypff Installation](#platform-specific-pypff-installation). ### `Failed to open PST file` - The file may be in use by Outlook. Close Outlook completely and try again. - The file may be corrupted. Try running the Outlook Inbox Repair Tool (`scanpst.exe` on Windows). ### Progress bar reaches 100% but fewer rows are written than expected This is normal. Some items in a PST folder hierarchy are not email messages (calendar events, contacts, tasks). They are counted in the total but may fail extraction silently. The `Errors skipped` count in the summary reflects this. ### CSV opens with garbled characters in Excel The CSV is UTF-8. In Excel, use **Data → From Text/CSV** and choose **UTF-8** encoding, or open via `File → Open` and select the encoding in the import wizard. ### Very slow processing on large PST files Ensure the PST file is on a local drive, not a network share or cloud-synced folder. Network latency multiplies enormously across hundreds of thousands of small reads. --- ## Platform-specific pypff Installation ### Linux (Debian / Ubuntu) ```bash sudo apt-get install python3-libpff # or pip install libpff-python ``` ### Linux (Fedora / RHEL) ```bash sudo dnf install libpff-devel python3-libpff ``` ### macOS (Homebrew) ```bash brew install libpff pip install libpff-python ``` ### Windows Automatic pip installation may fail because libpff requires compilation. **Option 1 – Pre-built wheel** (if available for your Python version): ```powershell pip install libpff-python ``` **Option 2 – Build from source** – follow the official guide: https://github.com/libyal/libpff/blob/main/documentation/Building.md **Option 3 – WSL (recommended)** – Install Windows Subsystem for Linux, then follow the Ubuntu steps above. This is the easiest path for most Windows users. --- ## Project Structure ``` . ├── Extract.py # Main extractor – run this ├── install_dependencies.py # One-time dependency installer └── README.md # This file ``` Outputs are placed alongside the input PST files: ``` /your/pst/folder/ ├── archive_2021.pst ├── archive_2021_email_list.csv ← generated ├── archive_2022.pst └── archive_2022_email_list.csv ← generated ``` --- ## FAQ **Does the tool modify the PST files?** No. PST files are opened read-only. The tool never writes to them. **Can I run it on a single PST file instead of a whole directory?** Put the PST file in its own folder and pass that folder path. Alternatively, the function `export_pst_to_csv(pst_path, output_csv_path)` can be imported and called directly from your own script. **What happens if I run it twice on the same directory?** Existing CSV files are overwritten without warning. If you want to preserve previous results, move or rename them first. **Does it export email bodies or attachments?** No — only metadata is exported. This keeps the output small and avoids legal / privacy issues associated with exporting full message content. **What message types are included?** All MAPI message objects found in the PST: emails (`IPM.Note`), meeting requests (`IPM.Schedule.*`), appointments (`IPM.Appointment`), contacts (`IPM.Contact`), tasks (`IPM.Task`), etc. The `MessageClass` column lets you filter by type in your spreadsheet. **Will it work with OST files?** libpff has partial OST support. Rename the file to `.pst` and try — results may vary depending on the OST version and whether the file is currently synced. --- *For bug reports and feature requests, open an issue in your project repository.*