cosmira/outlook-msg
A PHP library for reading Microsoft Outlook .msg files without Outlook installed. Extract subject, sender, recipients, body, headers, dates, and attachments into structured data for email migration, search indexing, and archival workflows.
.eml-friendly mail and a feature you can put in front of an enterprise Outlook shop, and it's the specific gap that most often turns an ingestion story from "shipped" back into "in progress.".msg is the native format of legal hold, e-discovery, and FOIA-style disclosure workflows. Reading and writing means you can support both sides: ingest a produced .msg set for review, and emit .msg for a counterparty or regulator that insists on Outlook-native files rather than .eml or PDF. RTF body recovery materially improves the review-side story — a produced set with unreadable bodies is a failed ingestion, not a partial one..eml) and treat .msg as an import/export shim, or to model Outlook's property semantics natively. With RTF→HTML recovery in place, the package now covers the dominant body encodings, which keeps the "shim" position genuinely viable and your domain model clean..msg ingestion isn't in the top few customer requests, this is a spike, not a commitment.Consider it when most of the following hold:
.msg requirement — a defined upload flow, an archive-export format, or a migration batch — not a vague "email support" ambition.Look elsewhere when:
.eml/MIME. Use zbateson/mail-mime-parser or PHP's mailparse; adding a proprietary-format dependency for standard mail is unjustified.winmail.dat edge cases. RTF-encapsulated bodies are now handled, but TNEF, exotic charsets, and malformed property streams still deserve a corpus test before you commit; a library this young has not been battle-tested across the long tail of malformed Outlook output.Adoption gate I'd insist on: a one-day spike against 20–50 real .msg files from your actual users — including the ugly ones (rich-text-composed messages, embedded images, winmail.dat, non-Latin charsets, calendar invites, oversized attachments) — plus a wrapper interface so the library is swappable, a pinned version (floor at 1.3.0, since earlier pins leave the RTF body gap open), and a documented fallback. Contract tests over a fixture corpus are non-negotiable for a dependency this young; add at least a handful of RTF-body fixtures specifically, since that code path is brand new.
For executives — the one-paragraph version:
We have a recurring customer-facing gap: people work in Outlook, and Outlook's native file format (.msg) can't be opened by our application. Fixing that normally means either paying per-document fees to a conversion service, buying a commercial SDK license, or standing up a Windows machine running Outlook — all of which add cost, procurement friction, and in the hosted-service case, send customer email content to a third party we don't control. An MIT-licensed PHP library lets us read and write these files inside our own application, on our own servers, at no license cost. The latest release closes the gap that mattered most in practice: it now recovers readable message bodies from Outlook's rich-text format, which is how a large share of enterprise mail is actually composed — previously those messages came through with empty or garbled bodies. I'm recommending a scoped proof of concept against real customer files before we commit it to the roadmap, because the library is young and effectively single-maintainer. The recommendation is adopt with a hedge: build the capability, isolate the dependency behind our own interface, and keep a fallback in reserve.
For engineering — what you're actually getting and what you're signing up for:
Pure PHP, Composer-installable, framework-agnostic but trivial to wire into Laravel (a queued job, a Storage disk, a Rule on upload, an interface in front of it). No ext dependencies on Windows, COM, or Office — that's the whole value proposition and it's a real one. 1.3.0 is a minor, additive release: it adds RTF→HTML body recovery and hardens RTF hex-byte handling, with no breaking changes, so the upgrade is a version bump plus a corpus re-run. That single change retires the edge case we'd otherwise have had to budget custom work for. The trade is that you still inherit the maintenance risk: single-digit stars, no dependents, one primary maintainer, and a format whose edge cases are famously nasty (TNEF attachments, embedded OLE objects, malformed property streams in files produced by third-party exporters). The new RTF path is fresh code — review it rather than trusting it, and note that one of the two PRs came in via Copilot assistance, which is fine but is not a substitute for reading the diff. So: pin at >=1.3.0, wrap it, run it in a sandboxed worker with memory and time limits (the RTF decoder in particular deserves a cap), build a fixture corpus from production files that grows every time something breaks, and prove the fallback path works before you need it. Two first-time outside contributors is a mild positive on bus factor, not a guarantee. If the corpus passes and the interface holds, you've bought a capability for the price of an afternoon's integration work instead of a five-figure license.
Framing for the build-vs-buy conversation: This isn't "should we write an MSG parser" — writing one ourselves is a multi-quarter project and a bad use of the team. It's "do we rent the capability per document, license it per server, or adopt an open-source implementation and absorb the maintenance risk ourselves." At low-to-moderate volume, adopting is clearly the cheapest of the three, and the RTF body work in 1.3.0 removes the most likely reason we'd have had to escalate to a commercial license anyway. The decision flips toward a commercial license if volumes get large, if the workflow becomes revenue-critical and needs an SLA, or if a security review flags the parser as an unacceptable attack surface — which is precisely why we keep it behind an interface.
How can I help you explore Laravel packages today?