Introduction

Aspose.Email FOSS for Python (aspose-email-foss) is a MIT-licensed Python library for working with Outlook MSG files, RFC-5322 EML messages, and Compound File Binary (CFB) storage structures. The library requires no native extensions and installs directly from PyPI.

The library addresses a common Python development gap: reading and writing Outlook .msg files without requiring a running Outlook installation or proprietary SDK. It also exposes the full CFB container format that underlies .msg files, making it suitable for tasks ranging from message migration to storage inspection.

The library ships with a typed API surface covering MAPI message construction, recipient and attachment management, property serialization, and CFB document round-trips.


Key Features

Creating and Serializing MSG Files

MapiMessage.create() constructs a new MAPI message from a subject and body string. From there you can add typed properties, recipients, and binary attachments, then serialize the result to bytes using to_bytes().

import datetime
from aspose.email_foss.msg.mapi_message import MapiMessage, PropertyId

message = MapiMessage.create("Quarterly Report", "Please review the attached report.")
message.set_property(PropertyId.SENDER_NAME, "Alice")
message.set_property(PropertyId.SENDER_EMAIL_ADDRESS, "alice@example.com")
message.set_property(
    PropertyId.MESSAGE_DELIVERY_TIME,
    datetime.datetime(2026, 3, 15, 10, 30, tzinfo=datetime.timezone.utc),
)
message.add_recipient("bob@example.com", display_name="Bob")
message.add_attachment("report.pdf", b"%PDF-1.4 ...", mime_type="application/pdf")

raw_bytes = message.to_bytes()

Reading Existing MSG Files

MapiMessage.from_file() reads an existing .msg file from disk. You can also reconstruct a message from raw bytes by passing a CFBReader through MsgReader and MsgDocument.

from aspose.email_foss.msg.mapi_message import MapiMessage
from aspose.email_foss.msg.reader import MsgReader, MsgDocument
from aspose.email_foss.cfb.reader import CFBReader

# Read from file path
msg = MapiMessage.from_file("message.msg")
print(msg.subject)

# Or reconstruct from bytes
msg2 = MapiMessage.from_msg_document(
    MsgDocument.from_reader(MsgReader(CFBReader(raw_bytes)))
)
print(msg2.subject)
for att in msg2.attachments:
    print(att.filename, len(att.data), "bytes")

Converting Between MAPI and RFC-5322 EML

MapiMessage.from_email_message() converts a standard Python email.message.EmailMessage object into a MAPI message, preserving subject, recipients, body, and attachments. The reverse conversion uses to_email_message().

from email.message import EmailMessage
from aspose.email_foss.msg.mapi_message import MapiMessage

# Build a standard Python email
eml = EmailMessage()
eml["Subject"] = "Meeting notes"
eml["From"] = "alice@example.com"
eml["To"] = "bob@example.com"
eml.set_content("Notes from today's meeting.")

# Convert to MAPI and serialize as .msg
mapi = MapiMessage.from_email_message(eml)
with open("meeting-notes.msg", "wb") as f:
    f.write(mapi.to_bytes())

# Round-trip back to EML
recovered = mapi.to_email_message()
print(recovered["Subject"])

Compound File Binary (CFB) Storage

The library includes a standalone CFB layer (CFBReader, CFBWriter, CFBDocument, CFBStorage, CFBStream) for reading and writing the Compound File Binary format independently of MAPI. This is useful for inspecting the raw storage structure of .msg files or for building custom compound file containers.

from aspose.email_foss.cfb.writer import CFBWriter, CFBDocument, CFBStorage, CFBStream
from aspose.email_foss.cfb.reader import CFBReader

# Build a CFB document with nested storage
root = CFBStorage("Root Entry")
root.add_stream(CFBStream("Metadata", b"meta-payload"))
nested = root.add_storage(CFBStorage("Attachments"))
nested.add_stream(CFBStream("Attachment1", b"binary-content"))

doc = CFBDocument(root=root, major_version=3)
data = CFBWriter.to_bytes(doc)

# Read it back
reader = CFBReader(data)
entry = reader.resolve_path(["Attachments", "Attachment1"])
print(reader.get_stream_data(entry.stream_id))

MAPI Property Access

iter_properties() returns all MAPI properties on a message as MapiProperty objects. Named properties (PidLidTag and PidNameTag) are accessible via MapiNamedProperty. MapiPropertyCollection provides dict-like property access.

from aspose.email_foss.msg.mapi_message import MapiMessage

msg = MapiMessage.from_file("message.msg")
for prop in msg.iter_properties():
    print(hex(prop.property_id), prop.property_type, repr(prop.value)[:60])

Quick Start

pip install aspose-email-foss
import datetime
from aspose.email_foss.msg.mapi_message import MapiMessage, PropertyId
from aspose.email_foss.msg.reader import MsgReader, MsgDocument
from aspose.email_foss.cfb.reader import CFBReader

# Create a message
message = MapiMessage.create("Hello", "This is the body.")
message.set_property(PropertyId.SENDER_NAME, "Sender")
message.set_property(PropertyId.SENDER_EMAIL_ADDRESS, "sender@example.com")
message.add_recipient("recipient@example.com", display_name="Recipient")
message.add_attachment("note.txt", b"attachment content", mime_type="text/plain")

# Serialize and reload
raw = message.to_bytes()
reloaded = MapiMessage.from_msg_document(
    MsgDocument.from_reader(MsgReader(CFBReader(raw)))
)
email = reloaded.to_email_message()
print("Subject:", email["Subject"])
print("From:", email["From"])

Supported Formats

FormatExtensionReadWrite
Msg.msg
CFB.cfb
eml.eml

MSG files are read via MapiMessage.from_file() and MsgReader. EML is accessed through the from_email_message() / to_email_message() conversion bridge. CFB containers are handled directly by CFBReader and CFBWriter.


Open Source & Licensing

Aspose.Email FOSS for Python is released under the MIT License. The source is available on GitHub and the package is distributed via PyPI under the name aspose-email-foss. MIT licensing permits use in commercial applications without royalty or attribution requirements beyond license inclusion.


Getting Started