---
name: msg
displayName: MSG Outlook Email Reader & Converter
description: Reads and converts Outlook .msg files (OLE/CFB binary format) to
  text, JSON, or CSV. Use when opening .msg email files, extracting message
  content, headers, or attachment metadata.
tags:
  - msg
  - outlook
  - email
  - ole
  - cfb
  - document
  - converter
  - mapi
capabilities:
  - ReadMsg
  - ConvertToJson
  - ConvertToCsv
  - ConvertToText
  - ExtractHeaders
  - ExtractAttachmentMetadata
representativeQueries:
  - Read a .msg file and show me the email content
  - Convert an Outlook msg file to JSON or CSV
  - Extract headers and body from a .msg email
  - What attachments are in this Outlook message file?
  - Parse an Outlook .msg file and get the sender and subject
version: 0.1.0
tier: curated
---

# MSG Outlook Email Reader & Converter

Reads Outlook `.msg` files — binary OLE/CFB Compound Documents storing MAPI email data — and converts their content to plain text, JSON, or CSV. Unlike `.eml`, `.msg` files are not plain text and require a dedicated library (`extract-msg`) to decode the MAPI property streams inside the OLE container.

## When to use

- Opening or previewing a `.msg` file saved from Microsoft Outlook.
- Extracting structured email data (headers, body, attachments metadata) for archival, search, or summarization.
- Converting batches of `.msg` files to JSON or CSV for analysis pipelines.
- Pulling specific MAPI fields (sender, subject, date, recipients) without manually decoding binary structures.
- Inventorying attachments inside an Outlook message without extracting binary content.

## Steps

1. **Detect format** — check the file has a `.msg` extension. Unlike `.eml`, `.msg` files are binary (OLE magic bytes `D0 CF 11 E0`), not plain text. A warning is printed for non-`.msg` extensions but processing continues (the OLE parser will fail fast if the file is not a valid MSG file).
2. **Check library** — the script requires `extract-msg`; if missing it prints a one-line install hint and exits non-zero.
3. **Route by task** — choose output mode: `text` (default, human-readable body), `json` (all fields + attachments list), or `csv` (one row with key fields).
4. **Run the bundled script** — `python3 scripts/msg_converter.py <file.msg> [--format text|json|csv]`. Output goes to stdout.
5. **Present output** — for `text`, display or summarize the email body; for `json`/`csv`, pass the structured data to the next workflow step.

## Operations

| Capability | CRUD | Resource | Tool |
|---|---|---|---|
| `ReadMsg` | READ | MSG file (MAPI properties + body) | `scripts/msg_converter.py` |
| `ConvertToText` | READ | Plain-text email body with header summary | `scripts/msg_converter.py --format text` |
| `ConvertToJson` | READ | JSON with headers, body, HTML body, attachments | `scripts/msg_converter.py --format json` |
| `ConvertToCsv` | READ | CSV row with key header fields + body | `scripts/msg_converter.py --format csv` |
| `ExtractHeaders` | READ | MAPI fields: from, to, cc, subject, date | `scripts/msg_converter.py --format json` (headers block) |
| `ExtractAttachmentMetadata` | READ | Attachment filename, MIME type, size | `scripts/msg_converter.py --format json` (attachments block) |

## Output

- **text** — Decoded message body (plain text preferred, HTML body stripped of tags as fallback), preceded by a summary header block (From, To, Subject, Date).
- **json** — `{ "headers": { from, to, cc, bcc, subject, date, message_id, message_class }, "body_text": "...", "body_html": "...", "attachments": [ { "filename", "mime_type", "size_bytes" } ] }`. Note: `bcc` is always empty in delivered messages — Outlook strips it before saving; it is only present in draft `.msg` files.
- **csv** — Columns: `from`, `to`, `cc`, `subject`, `date`, `message_id`, `body_text`, `attachment_count` (one row per file).

## Notes

- Requires `extract-msg` (`pip install extract-msg`). The script checks for the library on startup and prints a clear install hint if absent.
- `.msg` files are OLE binary — do NOT try to open them with `email.message_from_file()` or a text editor.
- MAPI dates are UTC; the script formats them as ISO 8601 strings.
- Attachment binary payloads are NOT extracted; only metadata is reported (filename, MIME type, size). Size is read from the MAPI `PR_ATTACH_SIZE` property via `att.getPropertyVal('0E200003')`; falls back to `len(att.data)` if the property is absent, or 0 if data is also unavailable. Extend with `att.data` to write files.
- Meeting requests and calendar items (`IPM.Schedule.*`) are supported — body text and headers are extracted the same way, but calendar-specific fields (start time, location) are not yet surfaced.
- For nested `.msg` attachments (forwarded messages embedded as files), the outer attachment metadata is listed; recursive extraction is a planned expansion.

<!-- runner-fallback -->
## Remote runner (MCP)
Can't run this locally (no setup, missing dependency)? The StealthStack runner exposes the **same code** as server-side MCP tools — no local install needed: `msg_to_text`, `msg_to_json`, `msg_to_csv`. Call the `application/mcp` catalog twin of this skill (its `runnerTwin`).
