MSGReader: reading Outlook MSG and EML files without Outlook
C# Outlook MSG file reader without the need for Outlook
At a glance
- What is it?
- MSGReader is a C# library that opens Outlook MSG files and Mime EML files directly, with no Outlook or Exchange server involved. It reads the common Outlook object types, handles the RTF-encapsulated HTML that trips up naive parsers, and offers one write operation: stripping attachments and saving a new file.
- Who is it for?
- Adopt MSGReader if your .NET application has to open Outlook MSG files or EML mail on a server or in a pipeline where Outlook is not installed, and you need the message objects, not just a text dump. Do not adopt it to create mail, since the writer side lives in the separate MsgKit project, and do not expect a general-purpose mail client, since this is a parser library.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Outlook files read as data, not as a mail client
MSGReader is a C# assembly for reading Outlook MSG and EML (Mime 1.0) files, targeting .NET 4.6.2, .NET Standard 2.0 and .NET Standard 2.1. The point of the library is the absence of Outlook. An MSG file is the on-disk format Outlook saves a message in, and reading one normally means either automating Outlook on a desktop or writing a parser yourself. This library is the parser.
The supported object types cover most of what a person finds in an Outlook mailbox. The README lists e-mail, appointment, task, contact card and sticky note, and the body formats are covered too: plain text, HTML, HTML embedded into RTF, and RTF on its own.
The audience is a developer building a service that has to process mail archives, a migration tool moving stored messages into another system, a reporting job over a mailbox export, or a test fixture generator that needs real message files. None of those situations has a logged-in Outlook installation available, and that constraint is the entire reason the library exists.
The repository layout backs this up. Besides the MsgReader project itself there are MsgReaderTests, a MsgMapper project, a Converter, a MsgViewer application, Utilities and Assemblies directories. The last one is a tool for people who just want to open a file and look at it, which tells you how much of the audience is non-developer.
Reading properties off a Message object
The core API is a Message class you open against a file path, and the properties you pull off it. The README example is short enough to read as the whole surface:
using (var msg = new MsgReader.Outlook.Storage.Message("d:\\testfile.msg"))
{
var from = msg.Sender;
var sentOn = msg.SentOn;
var recipientsTo = msg.GetEmailRecipients(MsgReader.Outlook.RecipientType.To, false, false);
var recipientsCc = msg.GetEmailRecipients(MsgReader.Outlook.RecipientType.Cc, false, false);
var subject = msg.Subject;
var htmlBody = msg.BodyHtml;
// etc...
}Two details carry the design. The message is opened inside a using block, which means the underlying file handle is released deterministically rather than left to a finalizer, and that matters when you loop over a directory of messages. And recipients are fetched through a method that takes a RecipientType plus two booleans, so you ask for the To list, the Cc list or the Bcc list explicitly and decide yourself how the secondary address types are resolved.
The two booleans are not explained in the README, and that is a real gap for anyone building on this. When you need to know exactly what those flags do, the answer is in the MsgReader source or the API documentation, not in the readme.
For the EML side, the entry point is different, a Mime message loaded from a FileInfo, with headers and bodies split apart:
var fileInfo = new FileInfo("d:\\testfile.eml");
var eml = MsgReader.Mime.Message.Load(fileInfo);
if (eml.Headers != null)
{
if (eml.Headers.To != null)
{
foreach (var recipient in eml.Headers.To)
{
var to = recipient.Address;
}
}
}Note the null checks around headers and around each body. A malformed or partial message is treated as an expected case by the API shape rather than an exception.
RTF-encapsulated HTML and the charset confidence level
The hardest part of parsing real Outlook mail is the body, and MSGReader documents that problem in detail rather than hiding it.
When an HTML body is used in an MSG file, that HTML is usually encapsulated into RTF. When the HTML contains characters outside the default extended ASCII range, those characters are encoded. With a single language this is usually fine. The trouble starts when several languages appear in the same message, because the RTF is often not built in a way that lets the parser work out which encoding to use for the encoded characters.
The library handles this with the UTF.Unknown NuGet package, which attempts to detect the encoding of a character, and with a confidence threshold set to 0.90. When the detection score passes that value, the character is treated as valid. The threshold is exposed as a property, CharsetDetectionEncodingConfidenceLevel, on both the Reader and the Message class, and the documentation comment on the property explains the trade-off directly:
public float CharsetDetectionEncodingConfidenceLevel { get; set; } = 0.90f;The accompanying remarks note that any value lower than 0.70 probably gives bad results. So there is a real tuning knob here, and the honest reading is that below 0.70 the detection is guesswork. If your documents are multilingual and the output looks wrong, raising or lowering this value on the Message instance is the first lever to try, not a change of library.
This is also the place where the README's own advice is most useful, because it names the failure mode instead of leaving you to discover it.
One write operation, and it is only about attachments
The README is explicit about the boundary of the write side. MSGReader has only a few options to manipulate an MSG file, and the only option is that you can remove attachments and then save the file to a new one. The example deletes the first attachment:
var outlook = new Storage.Message(fileName, FileAccess.ReadWrite);
outlook.DeleteAttachment(outlook.Attachments[0]);
outlook.Save("d:\\deleted.msg");This is worth pausing on, because it is the operation a compliance workflow usually needs. Redacting a message by removing its attachments, then writing a copy, is exactly the shape of an email sanitiser, and the file is opened with FileAccess.ReadWrite for that reason. Saving to a new path rather than in place also means the original stays untouched, which is the behaviour you want in a pipeline that has to be repeatable and auditable.
For anything beyond that, the author points you elsewhere. If you want to write MSG files, the README directs you to the MsgKit project on GitHub, so the writing capability exists but lives in a separate repository with its own release cycle. The same split shows up in the repository layout, where a Converter directory and a MsgMapper project exist alongside the reader.
One more limitation to note: nothing in the README describes how a save round trip preserves headers, body encoding or other metadata. For a redaction workflow that is acceptable, for a tool that rewrites messages it is a question to answer before you rely on it.
Reading MSG files from VBScript and VB6
There is a second way in that the README calls a side note, and it is the one that separates this library from a purely managed-code tool. The project can be used from a COM based language such as VBScript or VB6.
The process is to compile the code and register the COM visible assembly:
Regasm.exe /codebase MsgReader.dllAfter that the reader is available as a COM object, and the usage is a plain CreateObject call with an extraction method:
dim msgreader
set msgreader = createobject("MsgReader.Reader")
msgreader.ExtractToFolderFromCom "the msg file to read", "the folder where to place the extracted files"The ExtractToFolderFromCom method takes the source message and a destination folder, and places the extracted files there. For an organisation with a large installed base of VB6 or VBScript line-of-business scripts, this is a pragmatic route to reading stored Outlook messages without a managed-code migration project. It also makes the library a realistic choice when the calling system is old but the mail archive is modern.
The cost of that route is that you are running a script host outside the .NET runtime, which means you are on .NET Framework rather than the modern .NET Standard targets the library also supports, and the registration step has to happen on every machine that uses it. It is a supported path, not a hack, but it is a path with operational weight.
NuGet install, a viewer binary and a mature release line
Installation is through NuGet, which the README calls the easiest way to install MSGReader. In Visual Studio's Package Manager Console the command is:
Install-Package MSGReaderFor people who do not want to write code at all, a very basic Outlook MSG file viewer is published as a release download, MSGViewer.zip, and it needs the .NET Desktop Runtime. The repository homepage points at the project pages under the sicos1977.github.io address.
The release record is steady and recent. Versions 6.2.0, 6.1.4 and 6.1.3 shipped on 2026-10-12, 2026-10-08 and 2026-10-04, and the last push was on 2026-10-19. A library sitting at version 6 after a decade of releases, with several point releases inside a single week, is a project in routine maintenance rather than one in crisis, which for a parser of a stable Microsoft file format is what you want.
The licence is MIT, with the copyright held by Magic-Sessions and dated 2013-2025. MIT is about as permissive as it gets for commercial use, with the only real obligation being that the copyright notice and permission text travel with the software.
The library is also translated, which tells you something about the user base. English and Dutch come from the maintainer, with German, French and Simplified Chinese contributed by others, and those translations cover the exception messages and the reader's own interface rather than the format handling.
The core team is listed as Sicos1977, whose real name the README gives as Kees van Spelde, who also handles the English and Dutch translations.
Editorial conclusion
Adopt MSGReader if your .NET application has to open Outlook MSG files or EML mail on a server or in a pipeline where Outlook is not installed, and you need the message objects, not just a text dump. Do not adopt it to create mail, since the writer side lives in the separate MsgKit project, and do not expect a general-purpose mail client, since this is a parser library. Verify first that the body type you care about survives the round trip, particularly HTML wrapped in RTF with mixed-language encoding, and that the charset detection confidence level of 0.90 matches the documents you need to read.
Frequently asked questions
How do I read an Outlook MSG file in C# without Outlook?
Open it with MsgReader.Outlook.Storage.Message and read the properties you need, such as Sender, SentOn, Subject and BodyHtml, using the recipient lists through GetEmailRecipients. The README notes that you can remove attachments and save to a new file, and for creating MSG files it points to the separate MsgKit project.
Can MSGReader read EML files as well as MSG?
Yes, EML (Mime 1.0) files are supported through MsgReader.Mime.Message.Load, which takes a FileInfo and exposes headers plus text and HTML bodies. The project targets .NET 4.6.2, .NET Standard 2.0 and .NET Standard 2.1.
Why is text from my MSG file garbled when the message mixes languages?
HTML bodies in MSG files are usually encapsulated into RTF, and characters outside the default extended ASCII range get encoded, which is hard to decode when several languages are present. MSGReader uses the UTF.Unknown package with a confidence threshold of 0.90, and you can change that with the CharsetDetectionEncodingConfidenceLevel property on the Reader or Message class, where values below 0.70 probably give bad results.
How do I install MSGReader?
The easiest way is via NuGet. In Visual Studio's Package Manager Console run Install-Package MSGReader. A basic MSG file viewer is also published as a release download, MSGViewer.zip, which requires the .NET Desktop Runtime.
Can MSGReader be used from VBScript or VB6?
Yes. The project can be used from a COM based language after compiling it and registering the COM visible assembly with Regasm.exe /codebase MsgReader.dll. You then create the object with createobject and call ExtractToFolderFromCom with the message path and a destination folder.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/sicos1977-msgreader)Was this useful?