onemail
An email library for .NET in pure C#. Read EML, mbox and Outlook MSG, PST and winmail.dat files, convert Outlook mail to EML, and read calendars and contacts, with no Outlook and no native code.
A preview, 0.2.0-preview.2: the API isn’t stable yet. Outlook writing, protocols and cryptography come in later previews.
A quick look
One call parses a message; one opens any file. The format comes from the content, so an mbox, an .msg and a PST store all read the same way.
using RecursiveAI.OneMail; IMailItem message = Mail.Parse(File.ReadAllBytes("message.eml")); Console.WriteLine($"{message.Subject} from {message.From[0].Address}"); using MailContainer pst = Mail.Open("archive.pst"); foreach (IMailItem item in pst.Enumerate()) Console.WriteLine(item.Subject);
What it does
Internet mail
MIME and EML, MHTML, delivery and read reports, mbox in every variant, Maildir, Apple Mail and Outlook Express files. Untouched messages write back byte for byte.
Outlook files, on read
MSG and OFT, PST and OST, winmail.dat and compressed RTF, with no Outlook installed. Large stores are read a message at a time.
MSG and PST to EML
Conversion between Outlook items and MIME follows Microsoft’s published rules, both ways. A loss report names every property that didn’t carry over.
Calendars and contacts
ICS and vCard 2.1 to 4.0, plus their JSON and XML forms. Recurring events expand with exceptions and time zones applied.
Repairs, not exceptions
Broken mail is read anyway. Each repair is a typed defect with its byte offset, and resource limits are on by default.
Every layer public
One-line Mail.Parse and Mail.Open on top; the MIME reader and writer, the stores, the PST layers and the MAPI model underneath.
Compared with other readers, message by message
MIME reading was compared with MimeKit, Python and Go on 517,401 Enron messages and three smaller sets, with no unexplained difference, and every untouched message wrote back byte-identical. Outlook files were compared with extract-msg, libpff and three TNEF readers. Converting 70 Outlook items to MIME and back lost no property silently.
Speed: against MimeKit 4.18.2 on the same bytes in memory, OneMail’s median time is 0.091 of MimeKit’s across 18 MIME rows (geometric mean, x64; 0.093 on arm64). The parse and write rows reward OneMail’s lazy design; the like-for-like body-decoding rows range from 0.104 to 0.479 on x64.
The packages
- OneMail
RecursiveAI.OneMail: the mail formats, the read view and conversion. Preview, 0.2.0-preview.2. - Calendar
RecursiveAI.OneMail.Calendar: ICS and vCard, jCal, jCard, xCal and xCard, recurrence and time zones. Depends only on .NET. Preview, 0.2.0-preview.2. - Cli
RecursiveAI.OneMail.Cli: theonemailtool,onemail inspectlists the messages, attachments and defects of any file it reads. Preview, 0.2.0-preview.2. - Not yet
Writing MSG and PST; SMTP, IMAP and POP3; DKIM, S/MIME and OpenPGP; rendering a message to PDF; OLM; Outlook calendar and task items.
- .NET
.NET 10, pure C#. NativeAOT, trimming and browser WebAssembly are supported targets. MIT or Apache-2.0.
Known gaps
As the project’s fidelity table states them for 0.2.0-preview.2. No Outlook has been run yet: the Outlook formats are checked against public files and other readers.
The full table- MSG / OFT
“two fuzz-minimised files from the corpus are refused by the compound file reader (typed defect); writing comes later”
- PST, OST
“no public ANSI or 512-byte-page Unicode PST from Outlook exists; those layouts and 4 KiB multi-map stores are checked only on files we generate. libpff cannot read 4 KiB tables whose rows sit in a data tree, so those have no differential yet. Associated (hidden) items are read but libpff does not export them”
- TNEF
“no TNEF-in-MIME message in the public corpora; checked on generated wrappers (64 messages)”
- RTF
Compressed RTF: “
\objattphattachment positions not applied”. HTML and text from RTF: “native RTF to HTML (non-encapsulated bodies) comes later” - MAPI to MIME
“EX addresses with no SMTP form in the item are left out and reported (30
AddressUnresolvedentries over the 70 items); Bcc is not written by default”; “PidTagTransportMessageHeadersis rewritten (reported)”; the view: “no directory lookup” - MIME to MAPI
“Bcc dropped on the way out (reported); display-name spelling of a kept received header”
- MIME / EML
“ambiguity resolutions are provisional until mail clients are observed”. Reports: “no real-world reports in the corpora; checked on generated and RFC-derived fixtures”. “
Received-SPFhas no oracle” - Mailboxes
mbox: “MMDF not supported”. Maildir: “Courier keyword file line format unverified against a real store; one directory listing held in memory”. EMLX: “flag bits unverified against a real Apple Mail store”. DBX: “one real store (a Windows XP laptop image, 28 files); OE4 files and deleted messages are not read”
- Contacts
“no Outlook-produced contact PST or MSG with the full property set, and no Outlook import/export of vCards to compare against”. “The slot order of telephone numbers and email addresses is approximated by a vCard and reported”
- In progress
Outlook calendar and task items; OLM.
Go further
This project is unaffiliated with other products named OneMail.