Introduction

Aspose.Email FOSS for Python goes beyond basic message creation. The library exposes the full depth of the MAPI property model, letting you read, write, and query individual properties by ID and type. It handles recipients, attachments, and embedded messages as first-class objects, and provides bidirectional conversion between the MSG binary format and Python’s standard email.message.EmailMessage.

At the container level, the CFB reader and writer give you deterministic control over Compound File Binary documents. You can traverse storage hierarchies, extract raw stream data, build new containers from scratch, and serialize them back to bytes. Both CFBError and MsgError provide structured exception handling for malformed input.

This post walks through each capability with verified code examples drawn directly from the library’s own test suite and example scripts.


What’s Included

MAPI Property Access

Every MSG file is built on MAPI properties. MapiMessage exposes set_property() and get_property() to work with properties by their PropertyId enum value. Use iter_properties() to enumerate all properties on a message, or get_property_value() for direct value retrieval with optional type decoding.

from aspose.email_foss import msg

message = msg.MapiMessage.create("Status report", "Weekly update attached.")

message.set_property(msg.PropertyId.SENDER_NAME, "Build Agent")
message.set_property(msg.PropertyId.SENDER_EMAIL_ADDRESS, "build.agent@example.com")
message.set_property(msg.PropertyId.DISPLAY_TO, "Alice Example; Bob Example")
message.set_property(msg.PropertyId.DISPLAY_CC, "Carol Example")
message.set_property(msg.PropertyId.DISPLAY_BCC, "Ops Archive")
message.set_property(
    msg.PropertyId.TRANSPORT_MESSAGE_HEADERS,
    "X-Environment: production\nX-Workflow: weekly-report\n",
)
message.save("report.msg")

To read properties back from an existing file:

from aspose.email_foss import msg

with msg.MapiMessage.from_file("report.msg") as loaded:
    print(f"Subject: {loaded.subject}")
    print(f"Body: {loaded.body}")

    for prop in loaded.iter_properties():
        print(f"tag=0x{prop.property_tag:08X}")

Recipients and Attachments

Add recipients with add_recipient(), specifying display name and recipient type (To, CC, or BCC). Attach files with add_attachment() using raw bytes and a MIME type. For nested messages, add_embedded_message_attachment() embeds a complete MapiMessage as a child object inside the parent.

from aspose.email_foss import msg

message = msg.MapiMessage.create("Team update", "See attached notes.")

message.add_recipient("alice@example.com", display_name="Alice Example")
message.add_recipient(
    "carol@example.com",
    display_name="Carol Example",
    recipient_type=msg.RECIPIENT_TYPE_CC,
)
message.add_recipient(
    "archive@example.com",
    display_name="Ops Archive",
    recipient_type=msg.RECIPIENT_TYPE_BCC,
)

message.add_attachment("notes.txt", b"Meeting notes content\n", mime_type="text/plain")
message.add_attachment("data.bin", b"\x00\x01\x02\x03", mime_type="application/octet-stream")
message.save("team-update.msg")

To inspect attachments on an existing message:

from aspose.email_foss import msg

with msg.MapiMessage.from_file("team-update.msg") as loaded:
    for att in loaded.iter_attachments_info():
        print(f"name={att.filename} mime={att.mime_type} size={len(att.data)}")
        print(f"  embedded={att.is_embedded_message} storage={att.storage_name}")

MSG to EmailMessage Conversion

The library converts in both directions between MSG and Python’s email.message.EmailMessage. Use to_email_message() to produce a standards-compliant MIME object, or from_email_message() to import an existing EmailMessage into the MSG format. Convenience methods to_email_bytes() and to_email_string() serialize directly to bytes or text.

from aspose.email_foss import msg

with msg.MapiMessage.from_file("example.msg") as loaded:
    email_msg = loaded.to_email_message()

    print(f"content_type: {email_msg.get_content_type()}")
    print(f"is_multipart: {email_msg.is_multipart()}")
    print(f"headers: {len(email_msg)}")

    for key, value in email_msg.items():
        print(f"  {key}: {value}")

    body_part = email_msg.get_body(preferencelist=("plain", "html"))
    if body_part is not None:
        print(f"body: {body_part.get_content()[:200]}")

CFB Container Round-Trip

Build and serialize Compound File Binary containers independently of the MSG layer. CFBDocument.from_file() loads an existing container into a mutable document model with CFBStorage and CFBStream nodes. CFBWriter.write_file() serializes the document back to disk deterministically.

from aspose.email_foss.cfb import CFBDocument, CFBReader, CFBWriter

reader = CFBReader.from_file("container.cfb")
document = CFBDocument.from_reader(reader)
reader.close()

output = CFBWriter.to_bytes(document)
print(f"Serialized {len(output)} bytes")

Error Handling

The library raises CFBError for malformed CFB content and MsgError for invalid MSG structure. MapiMessage also exposes a validation_issues property that returns a tuple of warning strings without raising an exception, letting you decide how strictly to handle non-conformant files.

from aspose.email_foss.cfb import CFBReader, CFBError
from aspose.email_foss.msg import MsgReader, MsgError

try:
    reader = CFBReader.from_file("corrupted.cfb")
except CFBError as e:
    print(f"CFB parse error: {e}")

try:
    reader = MsgReader.from_file("malformed.msg")
except MsgError as e:
    print(f"MSG parse error: {e}")

Quick Start

pip install aspose-email-foss>=26.3

Load an existing MSG, read its metadata, and list attachments:

from aspose.email_foss import msg

with msg.MapiMessage.from_file("inbox-message.msg") as message:
    print(f"Subject: {message.subject}")
    print(f"Body preview: {message.body[:200] if message.body else '(empty)'}")

    for att in message.iter_attachments_info():
        print(f"Attachment: {att.filename} ({att.mime_type}, {len(att.data)} bytes)")

    issues = message.validation_issues
    if issues:
        print(f"Warnings: {issues}")

Supported Formats

FormatImportExport
MSGYesYes
CFBYesYes

Open Source & Licensing

Aspose.Email FOSS for Python is released under the MIT License. You may use it in personal, internal, and commercial projects without restriction. The source code is available on GitHub.


Getting Started