zemail-core is in active development. The figures on this page are derived from the crate source as it stands today (Cargo.toml, src/commands.rs, src/ffi.rs): version, crate-types, the dotted commands in the COMMANDS table (kept in lockstep with Engine::invoke's match arms by a drift-guard test), and the exported C symbols. The "planned" column lists work that is not yet implemented — it is a roadmap, not a claim of coverage.
Module map
| module | role today | planned |
|---|---|---|
| lib (Engine) | one dotted command surface via Engine::invoke; event sink; folder seeding | more dispatch coverage as modules grow |
| model | account · identity · server config · folder · message · contact · filter types | richer flags, threading model |
| store | profile load/save; persisted message store (messages.json); import eml · mbox · maildir; mbox export | — |
| mime | RFC 5322 / MIME parsing via mail-parser | — |
| encoding | outbound MIME: RFC 5322 builder (message.build_rfc5322), RFC 2047 header encode, quoted-printable, format=flowed (RFC 3676) | — |
| search | in-memory query over messages + persisted named queries (saved searches) | — |
| gloda | global relevance-ranked search over an inverted TF-IDF index of the whole store (Thunderbird Gloda analogue); dependency-free | persistent index, phrase queries |
| filters | conditions + actions (mark · star · label · move · delete) | scheduled runs, more conditions |
| junk | adaptive junk filter — multinomial naive-Bayes over message tokens; trained counts persist in the profile | header features, per-account models |
| mailapps | cross-app pure logic: categorize · unsubscribe extraction and the stateful surface for snooze · send-later · mute · VIP · pin · scheduled send · self-destruct · Screener · templates · follow-up (Gmail, Apple Mail, Outlook, ProtonMail, Hey, Spark/Superhuman, RFC 8058) | richer rules, server-side sync |
| threading | JWZ conversation threading (References / In-Reply-To reply tree) + list-aware canonical-subject normalization | — |
| thread_reconstruct | ⭐ rebuild a who-wrote-what timeline from one message's quote nesting (>-depth + On … wrote: / Outlook blocks) | — |
| quote_audit | ⭐ Quote Integrity Audit — verify a reply's quoted text against the original it claims to quote; flag altered wording, changed figures, flipped negations, fabricated lines | — |
| roster_audit | ⭐ Conversation Roster Audit — diff the To/Cc roster across a whole thread; flag who was silently CC'd in, silently dropped, or quietly demoted To→Cc | — |
| sender_identity | ⭐ Sender Identity Firewall — per-sender behavioural baselines (DKIM selectors, envelope sources, header field-order, MIME structure, send-hour histogram, writing-style sketch) + offline impersonation / account-takeover scoring | — |
| provenance | ⭐ Document Revision Ledger — BLAKE3-address every attachment across the archive (rayon-parallel, incremental), group revisions into rename-stable document families, and report stale holders / forks / resurrections / domain crossings; persists to its own ledger.json | — |
| revision_diff | ⭐ Revision Delta Ledger — extract each revision's text (plain text + HTML in-crate, richer formats via host-registered backends), align consecutive revisions with quote_audit's line matcher, and join material-drift / silent-revert / stale-on-a-moved-term findings onto the holder graph | — |
| doc_attest | Body-to-attachment quote attestation — check prose in a mail body against the named attachment it claims to quote, before sending (compose.doc_attest) or after the fact (message.doc_attest) | — |
| exposure | ⭐ Knowledge Exposure Ledger — when each person was told a fact versus when they were merely copied on it (exposure.trace · exposure.room) | — |
| fork_ledger | ⭐ Conversation Fork Ledger — where one conversation split into two and whether the branches ended up disagreeing (fork.scan · fork.thread) | — |
| reading | ⭐ Divergent Reading Ledger — which recipients of a draft or a sent message hold a different reading of the values it states (reading.draft · reading.message) | — |
| phishing | ⭐ explainable phishing risk score — auth failures, display-name spoofing, brand impersonation, punycode/homoglyph domains, urgency language, link-text↔href mismatch, each with its own reason | — |
| headers | Authentication-Results (RFC 8601) + DKIM-Signature (RFC 6376) analysis | — |
| sieve | Sieve (RFC 5228) script parsing + filter → Sieve export | — |
| calendar | iCalendar (RFC 5545) meeting-invite parsing + METHOD:REPLY RSVP generation (Thunderbird/Lightning, Outlook, Apple Mail); VTODO · VJOURNAL · VALARM · VTIMEZONE parsing; free/busy merge; pure string handling | — |
| recurrence | RRULE expansion (FREQ/INTERVAL/COUNT/UNTIL/BYDAY) over self-contained proleptic-Gregorian date math — no chrono | — |
| addressbook | vCard 3.0 ↔ 4.0 import/export; contacts; KIND:group cards; duplicate detection + merge | — |
carddav (feature carddav) | CardDAV address-book pull/push of vCards over WebDAV (ureq native-tls + quick_xml), reusing the addressbook parser | incremental sync, ctag/etag |
net (feature net) | IMAP sync · SMTP send over one native-tls stack: UID-delta incremental fetch, folder discovery, server-side SEARCH, flag write-back, RFC 2177 IDLE, POP3 download, XOAUTH2 for IMAP + SMTP, and a stateless smtp_send_one for transactional mail | — |
openpgp (feature openpgp) | OpenPGP crypto via rPGP (pure-Rust): keygen, detached sign/verify, encrypt/decrypt over ASCII armor | key discovery, subkey management |
smime (feature smime) | S/MIME crypto — CMS (RFC 5652) over X.509 + RSA via RustCrypto: gen cert, sign/verify, encrypt/decrypt (PEM / base64 DER) | cert chain validation, AES-GCM |
| error | engine Result + Error with stable machine tags for a {error:{tag,message}} FFI envelope | more granular tags |
| util | dependency-free helpers — a standard Base64 (RFC 4648) codec for the JSON/FFI boundary | — |
| ffi | C ABI: zml_init · zml_invoke · zml_set_event_callback · zml_string_free | header generation, richer event payloads |
tauri_plugin (feature tauri) | Tauri v2 plugin glue for GUI hosts; the mountable view ships beside it as frontend/zemail.js (mountZemail(root)) | — |
| commands | the COMMANDS table — every dotted command Engine::invoke accepts, for automation-bus discovery; a drift-guard test fails if it falls behind invoke | — |
The crate carries 52 source modules; the map above lists the principal ones. The remainder cover the protocol and analysis surfaces reached only through invoke — imap_parse, jmap, dsn, tnef, sniff, tracking, policy, priority, schedule, querylang, quoting, listmgmt, mailmerge, mailto, forward, digest, html, addr_validate, contactphoto and crypto_mime.
Build surfaces
The crate declares crate-type = ["rlib", "staticlib", "cdylib"]. The rlib links natively into Rust/Tauri hosts; the staticlib/cdylib expose the C ABI for non-Rust hosts. The default net feature pulls in imap, native-tls and lettre; building --no-default-features yields a pure core with zero TLS/network deps that compiles in headless CI. The optional tauri feature adds the GUI plugin layer.
Verification
The crate carries 202 in-source unit tests plus 55 integration tests (tests/integration.rs) — 257 in all — across the engine and its modules: the command surface (version reporting, default-folder seeding, account add/list/remove, an import-then-filter flow, unknown-command error tagging, and a drift guard asserting COMMANDS covers every invoke arm), plus module-level tests in store, mime, search, filters, addressbook, util, gloda, junk, mailapps, threading, thread_reconstruct, quote_audit, roster_audit, sender_identity, provenance, revision_diff, tnef and tracking. Those counts are the default feature set; the carddav, openpgp and smime modules carry their own tests behind their feature flags. Tests for the pure core run without network access and are intended to pass identically in a headless Linux CI; the net module's transport is feature-gated so the default test path needs no live mail server.