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

FormatExtensionReadWrite
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.


Getting Started