Skip to content

Mail.app Envelope Index Schema

Query run against: /Users/chrispatten/Library/Mail/V10/MailData/Envelope Index

CREATE TABLE Statement

CREATE TABLE messages (
    ROWID INTEGER PRIMARY KEY AUTOINCREMENT,
    message_id INTEGER NOT NULL DEFAULT 0,
    global_message_id INTEGER NOT NULL,
    remote_id INTEGER,
    document_id TEXT COLLATE BINARY,
    sender INTEGER,
    subject_prefix TEXT COLLATE BINARY,
    subject INTEGER NOT NULL,
    summary INTEGER,
    date_sent INTEGER,
    date_received INTEGER,
    mailbox INTEGER NOT NULL,
    remote_mailbox INTEGER,
    flags INTEGER NOT NULL DEFAULT 0,
    read INTEGER NOT NULL DEFAULT 0,
    flagged INTEGER NOT NULL DEFAULT 0,
    deleted INTEGER NOT NULL DEFAULT 0,
    size INTEGER NOT NULL DEFAULT 0,
    conversation_id INTEGER NOT NULL DEFAULT 0,
    date_last_viewed INTEGER,
    list_id_hash INTEGER,
    unsubscribe_type INTEGER,
    searchable_message INTEGER,
    brand_indicator INTEGER,
    display_date INTEGER,
    color TEXT COLLATE BINARY,
    type INTEGER,
    fuzzy_ancestor INTEGER,
    automated_conversation INTEGER DEFAULT 0,
    root_status INTEGER DEFAULT -1,
    flag_color INTEGER,
    is_urgent INTEGER NOT NULL DEFAULT 0
)

Column List (PRAGMA table_info)

cid name type notnull dflt_value pk
0 ROWID INTEGER 0 1
1 message_id INTEGER 1 0 0
2 global_message_id INTEGER 1 0
3 remote_id INTEGER 0 0
4 document_id TEXT 0 0
5 sender INTEGER 0 0
6 subject_prefix TEXT 0 0
7 subject INTEGER 1 0
8 summary INTEGER 0 0
9 date_sent INTEGER 0 0
10 date_received INTEGER 0 0
11 mailbox INTEGER 1 0
12 remote_mailbox INTEGER 0 0
13 flags INTEGER 1 0 0
14 read INTEGER 1 0 0
15 flagged INTEGER 1 0 0
16 deleted INTEGER 1 0 0
17 size INTEGER 1 0 0
18 conversation_id INTEGER 1 0 0
19 date_last_viewed INTEGER 0 0
20 list_id_hash INTEGER 0 0
21 unsubscribe_type INTEGER 0 0
22 searchable_message INTEGER 0 0
23 brand_indicator INTEGER 0 0
24 display_date INTEGER 0 0
25 color TEXT 0 0
26 type INTEGER 0 0
27 fuzzy_ancestor INTEGER 0 0
28 automated_conversation INTEGER 0 0 0
29 root_status INTEGER 0 -1 0
30 flag_color INTEGER 0 0
31 is_urgent INTEGER 1 0 0

Sample Data (First 5 Rows)

ROWID message_id global_message_id remote_id sender subject date_sent date_received mailbox flags read conversation_id
1 4773312084381739807 1 9507 1 1 1677098044 1677098108 2 8590195840 0 31
2 -8870798389135542176 2 9506 3 2 1677078053 1677078055 2 8590195840 0 30
3 378390787877563686 3 9505 4 3 1677029074 1677029121 2 25770065025 1 29
4 8326054568977240875 4 9504 5 4 1677007502 1677007509 2 8590132353 1 636
5 -1223034532183719061 5 9503 7 5 1677003409 1677003411 2 8590195840 0 28

Notes

  • No guid column: The real Mail.app Envelope Index does NOT contain a guid column
  • mailboxes table: Only contains url column (plus counters), no name, displayName, or type columns
  • Mailbox names must be derived from the URL path (e.g., imap://account-id/INBOXINBOX)
  • Mailbox types (Trash, Junk, etc.) must be inferred from the mailbox name in the URL
  • recipients table: Email recipients (To/Cc/Bcc) are stored in a separate recipients table:
  • Structure: ROWID, message (foreign key to messages.ROWID), address (foreign key to addresses.ROWID), type, position
  • type: 0 = To, 1 = Cc, 2 = Bcc
  • Must join recipients → addresses to get actual email addresses
  • message_global_data table: Does NOT contain to_list, cc_list, or bcc_list columns
  • Contains: message_id, follow_up_start_date, follow_up_end_date, download_state, read_later_date, send_later_date, validation_state, generated_summary, urgent, model_analytics, model_category, category_model_version, model_subcategory, model_high_impact, category_is_temporary
  • Foreign keys: sender, subject, summary reference other tables (addresses, subjects, summaries)
  • Timestamps: date_sent, date_received, date_last_viewed, display_date use Apple epoch (seconds since 2001-01-01)
  • The remote_id matches the .emlx filename in the mailbox directory structure

Additional Important Tables

recipients Table

CREATE TABLE recipients (
    ROWID INTEGER PRIMARY KEY,
    message INTEGER NOT NULL,     -- Foreign key to messages.ROWID
    address INTEGER NOT NULL,     -- Foreign key to addresses.ROWID
    type INTEGER,                 -- 0=To, 1=Cc, 2=Bcc
    position INTEGER              -- Order in recipient list
);

subjects Table

CREATE TABLE subjects (
    ROWID INTEGER PRIMARY KEY,
    subject TEXT NOT NULL
);

addresses Table

CREATE TABLE addresses (
    ROWID INTEGER PRIMARY KEY,
    address TEXT NOT NULL,
    comment TEXT NOT NULL         -- Display name
);

mailboxes Table (Complete Structure)

CREATE TABLE mailboxes (
    ROWID INTEGER PRIMARY KEY,
    url TEXT NOT NULL,
    total_count INTEGER NOT NULL DEFAULT 0,
    unread_count INTEGER NOT NULL DEFAULT 0,
    deleted_count INTEGER NOT NULL DEFAULT 0,
    unseen_count INTEGER NOT NULL DEFAULT 0,
    unread_count_adjusted_for_duplicates INTEGER NOT NULL DEFAULT 0,
    change_identifier TEXT,
    source INTEGER,
    alleged_change_identifier TEXT
);