Introduction
Aspose.Email FOSS for .NET is a MIT-licensed, dependency-free C# library for working with Outlook MSG files, Compound File Binary (CFB) containers, and EML messages. This post walks through each major feature area with working code examples drawn directly from the library’s test suite — every class name and method signature shown here is verified against the source repository.
Install with a single command — no Microsoft Outlook, no COM interop, no native libraries:
dotnet add package Aspose.Email.Foss
Key Features
Read and Inspect MSG Files
MapiMessage.FromStream() and MapiMessage.FromFile() open any Outlook .msg file and
expose its full contents: subject, plain-text body, HTML body, sender name, sender email
address, delivery time, internet message ID, recipients, and attachments. No Outlook
installation is required — the entire MSG and CFB layer is implemented in managed C#.
using System.IO;
using Aspose.Email.Foss.Msg;
using var stream = File.OpenRead("sample.msg");
var message = MapiMessage.FromStream(stream);
Console.WriteLine(message.Subject);
Console.WriteLine(message.SenderEmailAddress);
Console.WriteLine(message.Body);
foreach (var recipient in message.Recipients)
Console.WriteLine($"To: {recipient.EmailAddress}");
foreach (var attachment in message.Attachments)
Console.WriteLine($"Attachment: {attachment.Filename} ({attachment.MimeType})");
Create MSG Files from Scratch
MapiMessage.Create() builds a complete email in memory. Set SenderName,
SenderEmailAddress, HtmlBody, InternetMessageId, and MessageDeliveryTime as
properties after creation, then add recipients with AddRecipient() and file or stream
attachments with AddAttachment(). Serialize with message.Save() — returns a byte[]
or writes directly to a path or Stream.
using System.IO;
using Aspose.Email.Foss.Msg;
var message = MapiMessage.Create("Hello", "Body");
message.SenderName = "Alice";
message.SenderEmailAddress = "alice@example.com";
message.HtmlBody = "<p>Body</p>";
message.InternetMessageId = "<hello@example.com>";
message.MessageDeliveryTime = new DateTime(2024, 1, 2, 3, 4, 5, DateTimeKind.Utc);
message.AddRecipient("bob@example.com", "Bob");
message.AddAttachment("note.txt", "abc"u8.ToArray(), "text/plain");
using var output = File.Create("hello.msg");
message.Save(output);
Convert EML to MSG (and Back)
MapiMessage.LoadFromEml() accepts a file path, a Stream, or a byte[] containing a
standard RFC 5322 / MIME message. The built-in MIME parser preserves subject, plain-text
body, HTML body, sender, recipients, and all attachments — including inline images with
Content-ID headers. SaveToEml() serializes back to MIME for full EML ↔ MSG round-trips
without any external MIME library.
using System.IO;
using Aspose.Email.Foss.Msg;
using var input = File.OpenRead("message.eml");
var message = MapiMessage.LoadFromEml(input);
// Inspect fields parsed from MIME headers
Console.WriteLine(message.Subject);
Console.WriteLine(message.SenderEmailAddress);
Console.WriteLine(message.HtmlBody);
// Save as MSG for Outlook-compatible storage
using var msgOutput = File.Create("message.msg");
message.Save(msgOutput);
// Round-trip back to EML
using var emlOutput = File.Create("roundtrip.eml");
message.SaveToEml(emlOutput);
Embedded Message Attachments
An MSG file can contain another MSG file as an attachment — a common pattern in forwarded
email chains. AddEmbeddedMessageAttachment() attaches a MapiMessage object as a nested
.msg attachment. When reading, MapiAttachment.IsEmbeddedMessage signals the embedded
type and EmbeddedMessage exposes the nested MapiMessage directly.
using System.IO;
using Aspose.Email.Foss.Msg;
var parent = MapiMessage.Create("Outer", "Parent body");
var child = MapiMessage.Create("Inner", "Child body");
child.SenderEmailAddress = "inner@example.com";
parent.AddEmbeddedMessageAttachment(child, "inner.msg");
parent.Save("outer.msg");
var loaded = MapiMessage.FromFile("outer.msg");
var attachment = loaded.Attachments[0];
if (attachment.IsEmbeddedMessage)
Console.WriteLine($"Embedded subject: {attachment.EmbeddedMessage!.Subject}");
CFB Container Read and Write
Outlook MSG files are built on the Compound File Binary (CFB) format — a hierarchical binary
container similar to a FAT filesystem. CfbReader exposes the full directory tree: iterate
storages and streams with IterChildren(), navigate to specific entries by path chain with
ResolvePath(), and read raw stream bytes with GetStreamData(). CfbWriter.ToBytes()
serializes a CfbDocument to bytes — useful for constructing custom CFB documents or
verifying lossless round-trips.
using System.Text;
using Aspose.Email.Foss.Cfb;
// Build a CFB document from scratch
var document = new CfbDocument();
document.Root.AddStream(new CfbStream("ReadMe", Encoding.UTF8.GetBytes("hello")));
var storage = document.Root.AddStorage(new CfbStorage("DataStore"));
storage.AddStream(new CfbStream("Payload", Encoding.UTF8.GetBytes("content")));
byte[] bytes = CfbWriter.ToBytes(document);
// Read it back
using var reader = new CfbReader(bytes);
var entry = reader.ResolvePath(["DataStore", "Payload"]);
if (entry is not null)
{
var data = reader.GetStreamData(entry.StreamId);
Console.WriteLine(Encoding.UTF8.GetString(data)); // "content"
}
Typed MAPI Property Access
MapiPropertyCollection provides typed MAPI property access for any MSG or storage object.
The CommonMessagePropertyId enum covers all standard MAPI property identifiers — Subject,
Body, BodyHtml, SenderName, SenderEmailAddress, MessageDeliveryTime,
InternetMessageId, and attachment properties including AttachFilename, AttachMimeTag,
and AttachContentId. Use SetProperty() and GetPropertyValue() to read and write
arbitrary properties beyond the named convenience fields on MapiMessage.
using Aspose.Email.Foss.Msg;
var message = MapiMessage.FromFile("sample.msg");
// Typed convenience properties
Console.WriteLine(message.Subject);
Console.WriteLine(message.SenderName);
Console.WriteLine(message.MessageDeliveryTime);
// Iterate all MAPI property keys
foreach (var key in message.IterPropertyKeys())
Console.WriteLine($"0x{(ushort)key.PropertyId:X4} / {key.PropertyType}");
Quick Start
dotnet add package Aspose.Email.Foss
using System.IO;
using Aspose.Email.Foss.Msg;
// Read an MSG file
using var stream = File.OpenRead("sample.msg");
var message = MapiMessage.FromStream(stream);
Console.WriteLine(message.Subject);
Console.WriteLine(message.SenderEmailAddress);
foreach (var recipient in message.Recipients)
Console.WriteLine($"To: {recipient.EmailAddress}");
foreach (var attachment in message.Attachments)
Console.WriteLine($"Attachment: {attachment.Filename} ({attachment.MimeType})");
Supported Formats
| Format | Extension | Read | Write |
|---|---|---|---|
| Compound File Binary | .cfb | ✓ | ✓ |
| Outlook Message | .msg | ✓ | ✓ |
| MIME / EML | .eml | ✓ | ✓ |
Open Source & Licensing
Aspose.Email FOSS for .NET is released under the MIT license. Use it freely in personal, commercial, and open-source projects with no usage restrictions. The source code is available at github.com/aspose-email-foss/Aspose.Email-FOSS-for-.Net.