Sample code for 30+ languages & platforms
Zig Requires Chilkat v11.0.0+

Load .eml and Examine the Structure, Attachments, and Related Items

See more Email Object Examples

Demonstrates how to load examine the MIME structure of a .eml, and also examine the attachment and related item filenames, attached messages, and multipart/report and DSN information.

Chilkat Zig Downloads

Zig
const std = @import("std");
const chilkat = @import("chilkat");

pub fn main(init: std.process.Init) !void {
    const alloc = init.arena.allocator();

    // This example requires the Chilkat API to have been previously unlocked.
    // See Global Unlock Sample for sample code.

    const eml_path = "C:/AAWorkarea/beatrix/roesner.eml";

    const mime = try chilkat.Mime.init();
    defer mime.deinit();

    mime.loadMimeFile(eml_path) catch {
        std.debug.print("{s}\n", .{try mime.getLastErrorText(alloc)});
        return;
    };

    std.debug.print("---- MIME structure ----\n", .{});
    std.debug.print("{s}\n", .{try mime.getStructure(alloc, "text")});
    std.debug.print("------------------------\n", .{});

    const email = try chilkat.Email.init();
    defer email.deinit();
    try email.loadEml(eml_path);

    // Was this a signed and/or encrypted email?
    // If so, then loading the .eml automatically unwraps
    // (i.e. verifies signatures and decrypts) and the resultant
    // email is what existed prior to signing/encrypting.
    std.debug.print("Email was Signed: {}\n", .{email.getReceivedSigned()});
    std.debug.print("Email was Encrypted: {}\n", .{email.getReceivedEncrypted()});
    if (email.getReceivedSigned()) {
        std.debug.print("Signature(s) valid = {}\n", .{email.getSignaturesValid()});
    }

    if (email.getReceivedEncrypted()) {
        std.debug.print("Decrypted successfully = {}\n", .{email.getDecrypted()});
    }

    var i: i32 = 0;
    const num_attach = email.getNumAttachments();
    std.debug.print("Number of attachments = {d}\n", .{num_attach});

    while (i < num_attach) {
        std.debug.print("---- Attachment {d}\n", .{i});

        // Examine the filename (if any)
        std.debug.print("filename: {s}\n", .{try email.getAttachmentFilename(alloc, i)});
        // Examine the content-ID (if any)
        std.debug.print("Content-ID: {s}\n", .{try email.getAttachmentContentID(alloc, i)});
        // Examine the content-type
        std.debug.print("Content-Type: {s}\n", .{try email.getAttachmentContentType(alloc, i)});
        // Examine the content-disposition
        std.debug.print("Content-Disposition{s}\n", .{try email.getAttachmentHeader(alloc, i, "content-disposition")});
        // Examine the attachment size:
        std.debug.print("Size (in bytes) of the attachment: {d}\n", .{email.getAttachmentSize(i)});

        i = i + 1;
    }

    std.debug.print("--\n", .{});

    // Now for the related items.

    // Note: A MIME sub-part can potentially be both a related item AND an attachment.
    // The typical case is when the item is contained under the multipart/related enclosure and
    // the item also has a "Content-Disposition" header indicating "attachment".
    // The location within multipart/related makes it a "related item", yet the Content-Disposition can also make it semantically an attachment.
    // Related items and attachments are not necessarily mutually exclusive.

    const num_related = email.getNumRelatedItems();
    std.debug.print("Number of related items = {d}\n", .{num_related});
    i = 0;
    while (i < num_related) {
        std.debug.print("---- Related Item {d}\n", .{i});

        // Examine the filename (if any)
        std.debug.print("filename: {s}\n", .{try email.getRelatedFilename(alloc, i)});
        // Examine the content-ID (if any)
        std.debug.print("Content-ID: {s}\n", .{try email.getRelatedContentID(alloc, i)});
        // Examine the content-type
        std.debug.print("Content-Type: {s}\n", .{try email.getRelatedContentType(alloc, i)});
        // Examine the content-location (if any)
        std.debug.print("Content-Location{s}\n", .{try email.getRelatedContentLocation(alloc, i)});

        i = i + 1;
    }

    // The email could also have attached messages.
    // An attached message is another email that was attached to this email.
    const em = try chilkat.Email.init();
    defer em.deinit();
    const num_attached_messages = email.getNumAttachedMessages();
    std.debug.print("Number of attached messages = {d}\n", .{num_attached_messages});
    i = 0;
    while (i < num_attached_messages) {
        std.debug.print("---- Attached message {d}\n", .{i});

        // Examine the attached email
        email.getAttachedEmail(i, em) catch {};
        std.debug.print("from: {s}\n", .{try em.getFrom(alloc)});
        std.debug.print("subject: {s}\n", .{try em.getSubject(alloc)});
        i = i + 1;
    }

    // An email could also be a multipart/report email.
    // This is a DSN (Delivery Status Notification)
    // The NumReports property indicates how many "reports" exist.
    const num_reports = email.getNumReports();
    std.debug.print("Number of reports = {d}\n", .{num_reports});
    i = 0;
    while (i < num_reports) {
        std.debug.print("---- Report {d}\n", .{i});
        // Get the raw report data...
        std.debug.print("{s}\n", .{try email.getReport(alloc, i)});
        i = i + 1;
    }

    // If the email is a multipart/report, then the information
    // from the message/delivery-status part of the email can be retrieved:
    if (email.isMultipartReport()) {
        std.debug.print("--- Delivery Status Information:\n", .{});
        std.debug.print("Status: {s}\n", .{try email.getDeliveryStatusInfo(alloc, "Status")});
        std.debug.print("Action: {s}\n", .{try email.getDeliveryStatusInfo(alloc, "Action")});
        std.debug.print("Reporting-MTA: {s}\n", .{try email.getDeliveryStatusInfo(alloc, "Reporting-MTA")});

        const json_dsn_info = try chilkat.JsonObject.init();
        defer json_dsn_info.deinit();
        email.getDsnInfo(json_dsn_info) catch {};
        json_dsn_info.setEmitCompact(false);
        std.debug.print("{s}\n", .{try json_dsn_info.emit(alloc)});
    }
}