Introduction

Aspose.Email FOSS for C++ is a new open-source library for reading, creating, and converting Outlook MSG files, RFC 5322 EML messages, and the Compound File Binary (CFB) containers that the MSG format is built on. It is written in C++17, has no external runtime dependencies, and builds on Linux, macOS, and Windows through CMake — there is no COM dependency and no platform-specific code path.

Outlook MSG files show up constantly in enterprise integration work — archival pipelines, migration tools, compliance exports — but reading them without Outlook itself has usually meant COM automation on Windows or a commercial library. Aspose.Email FOSS for C++ gives you a portable alternative: a high-level mapi_message class for everyday message reading and creation, plus lower-level msg_reader, msg_document, and cfb_reader classes for direct access to the underlying container format when you need it.

The library is distributed as C++17 source under the MIT license and added to a project as a CMake subdirectory, exposing the AsposeEmailFoss target — no package manager registration and no prebuilt binaries are required.


Key Features

Read Outlook MSG Files

Open a .msg file with msg_reader::from_file() or msg_reader::from_stream(). To access a message’s storages and streams directly, wrap the reader in a msg_document with msg_document::from_reader().

#include "aspose/email/foss/msg/msg_reader.hpp"
#include "aspose/email/foss/msg/msg_document.hpp"
#include <filesystem>

namespace aef = aspose::email::foss;

auto reader = aef::msg::msg_reader::from_file(
    std::filesystem::path("message.msg"), /*strict=*/false);
auto document = aef::msg::msg_document::from_reader(reader);

Create Messages Programmatically

mapi_message::create() builds a new in-memory message from a subject and body. Set the sender, add recipients, and attach binary or text payloads before saving with save().

#include "aspose/email/foss/msg/mapi_message.hpp"
#include <filesystem>

namespace aef = aspose::email::foss;

auto message = aef::msg::mapi_message::create(
    "Quarterly status update", "Hello team,\n\nRollout summary attached.");
message.set_sender_name("Build Agent");
message.set_sender_email_address("build.agent@example.com");
message.add_recipient("alice@example.com", "Alice Example");
message.add_recipient("carol@example.com", "Carol Example",
    aef::msg::mapi_message::recipient_type_cc);
message.add_attachment("report.txt", std::vector<std::uint8_t>{'o', 'k'}, "text/plain");
message.save(std::filesystem::path("output.msg"));

Convert Between MSG and EML

mapi_message::save_to_eml() writes the current message as an RFC 5322 EML file, and mapi_message::load_from_eml() reads one back. Both directions preserve the subject, sender, recipients, and attachments, so a message can move between MSG and EML without Outlook.

auto message = aef::msg::mapi_message::from_file(
    std::filesystem::path("message.msg"), /*strict=*/false);
message.save_to_eml(std::filesystem::path("message.eml"));

auto restored = aef::msg::mapi_message::load_from_eml(std::filesystem::path("message.eml"));
restored.save(std::filesystem::path("restored.msg"));

Inspect Message Properties and Attachments

A loaded mapi_message exposes its standard header fields directly — subject(), sender_name(), sender_email_address(), message_class(), and internet_message_id() — along with recipients() and attachments() as vectors of mapi_recipient and mapi_attachment. For MAPI fields with no dedicated accessor, get_property_value() reads any property by its common_message_property_id and property_type_code.

#include "aspose/email/foss/msg/mapi_message.hpp"
#include "aspose/email/foss/msg/common_message_property_id.hpp"
#include "aspose/email/foss/msg/property_type_code.hpp"
#include <iostream>

namespace aef = aspose::email::foss;

template <typename E>
constexpr auto to_underlying(E value) noexcept {
    return static_cast<std::underlying_type_t<E>>(value);
}

auto message = aef::msg::mapi_message::from_file(
    std::filesystem::path("message.msg"), /*strict=*/false);

std::cout << "Subject: " << message.subject() << '\n';
std::cout << "From: " << message.sender_name()
           << " <" << message.sender_email_address() << ">\n";
std::cout << "Recipients: " << message.recipients().size() << '\n';

for (const auto& attachment : message.attachments()) {
    std::cout << "- " << attachment.filename
               << " (" << attachment.mime_type << ", "
               << attachment.data.size() << " bytes)\n";
}

const auto display_cc = message.get_property_value(
    to_underlying(aef::msg::common_message_property_id::display_cc),
    to_underlying(aef::msg::property_type_code::ptyp_string));

Low-Level CFB Container Access

MSG files are stored inside a Compound File Binary (CFB) container — the structured-storage format also used by legacy Office binary formats. cfb_reader opens the raw container and exposes its directory tree directly: storage_ids() and stream_ids() list every entry, directory_entry_count() reports the total, and header() returns the container’s sector layout. This is useful when you need MAPI data that the mapi_message API does not surface.

#include "aspose/email/foss/cfb/cfb_reader.hpp"
#include <iostream>

namespace aef = aspose::email::foss;

auto cfb = aef::cfb::cfb_reader::from_file(std::filesystem::path("message.msg"));
std::cout << "Directory entries: " << cfb.directory_entry_count() << '\n';
std::cout << "Storages: " << cfb.storage_ids().size() << '\n';
std::cout << "Streams: " << cfb.stream_ids().size() << '\n';

Quick Start

Add the library to your project:

git clone https://github.com/aspose-email-foss/Aspose.Email-FOSS-for-Cpp.git
# CMakeLists.txt
add_subdirectory(Aspose.Email-FOSS-for-Cpp)
target_link_libraries(your_target PRIVATE AsposeEmailFoss::AsposeEmailFoss)

Then create a message, save it as MSG, and round-trip it to EML:

#include "aspose/email/foss/msg/mapi_message.hpp"
#include <filesystem>
#include <vector>
#include <cstdint>

namespace aef = aspose::email::foss;

int main() {
    auto message = aef::msg::mapi_message::create("Hello from C++", "Body text here");
    message.set_sender_name("Alice");
    message.set_sender_email_address("alice@example.com");
    message.add_recipient("bob@example.com", "Bob");
    message.add_attachment("note.txt", std::vector<std::uint8_t>{'a', 'b', 'c'}, "text/plain");
    message.save(std::filesystem::path("hello.msg"));

    auto loaded = aef::msg::mapi_message::from_file(
        std::filesystem::path("hello.msg"), /*strict=*/false);
    loaded.save_to_eml(std::filesystem::path("hello.eml"));

    return 0;
}

Supported Formats

FormatExtensionReadWrite
Outlook Message (MSG).msg
EML (RFC 5322 / MIME).eml
Compound File Binary (CFB).cfb

Open Source & Licensing

Aspose.Email FOSS for C++ is released under the MIT license. The full source is available at aspose-email-foss/Aspose.Email-FOSS-for-Cpp, and commercial use is permitted without royalties. The library has no runtime dependencies beyond a C++17 compiler and CMake 3.26 or later.


Getting Started