OfficeIMO.Email
3.6.1
Prefix Reserved
dotnet add package OfficeIMO.Email --version 3.6.1
NuGet\Install-Package OfficeIMO.Email -Version 3.6.1
<PackageReference Include="OfficeIMO.Email" Version="3.6.1" />
<PackageVersion Include="OfficeIMO.Email" Version="3.6.1" />
<PackageReference Include="OfficeIMO.Email" />
paket add OfficeIMO.Email --version 3.6.1
#r "nuget: OfficeIMO.Email, 3.6.1"
#:package OfficeIMO.Email@3.6.1
#addin nuget:?package=OfficeIMO.Email&version=3.6.1
#tool nuget:?package=OfficeIMO.Email&version=3.6.1
OfficeIMO.Email
Read local messages without retaining source handles
EmailMessageReader provides a body and attachment metadata view over local email files and offline archives:
using OfficeIMO.Email;
EmailMessageReadResult result = EmailMessageReader.Read("Archive.pst",
new EmailMessageQuery { SubjectContains = "invoice", First = 25 });
foreach (OfficeIMO.Email.EmailMessage message in result.Messages) {
Console.WriteLine(message.TextBody);
EmailAttachmentExtractionResult files = message.SaveAttachments("attachments/" + message.ExportName,
message.Attachments.Where(a => a.FileName?.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase) == true)
.Select(a => a.Index));
message.Save("copies/" + message.ExportName + ".eml",
options: new EmailWriterOptions(EmailConversionLossPolicy.Warn));
}
The reader closes before returning. Payload operations reopen the unchanged source for their duration and remain cancellable through serialization or extraction. Keep the source file available and unchanged; views are local locators, not persisted checkpoints. Raw HTML bodies remain untrusted; the optional HTML bridge supplies sanitized local copies. ContentAvailability reports offline store cache limitations.
Folder accepts an exact path or unique folder name, Recurse includes descendants, and date bounds use received date with sent-date fallback. First defaults to 1,000 matches in source order; StoppedAtScanLimit explicitly reports a bounded search. Use EmailMessageStore.Open(path) in a using scope to reuse one reader for several queries; returned views remain usable after that scope closes. Directory-backed stores remain available through the lower-level data APIs.
Attachment extraction and draft composition
Extract decoded attachments into a directory controlled by the application:
EmailAttachmentExtractionResult extraction = EmailAttachmentExtractor.Extract(message, "attachments",
new EmailAttachmentExtractionOptions(recurseEmbeddedMessages: true));
foreach (EmailAttachmentExtractionEntry entry in extraction.Entries) {
Console.WriteLine($"{entry.SourcePath}: {entry.OutputPath} {entry.Sha256}");
}
The result is a hash and provenance manifest. Each entry keeps its original filename, logical attachment
indexes, committed path, byte count, and diagnostics. Portable filenames include a deterministic index
and source-path hash. Existing files are never overwritten. Embedded messages are exported as EML through
the regular writer, so their conversion and signature policies still apply. Linked attachment paths are
never opened, hidden attachments are excluded by default, and inline attachments can be excluded explicitly.
The defaults visit at most 1,000 entries, allow 64 MiB per file and 256 MiB per operation, and permit four
levels of nested attachment traversal when enabled. A rejected streaming payload may consume one sentinel
byte beyond its limit. The aggregate budget counts decoded source reads, including failed attempts, and
generated embedded EML bytes. Embedded source content is staged once through the shared writer staging
owner; it is not reopened during serialization. ExtractAsync stages and copies source streams asynchronously.
Earlier committed files remain available if a later attachment fails or the operation
is cancelled. Keep the destination directory under application control while extraction runs.
Create reply and forward artifacts without sending them:
var composition = new EmailCompositionOptions();
composition.OwnAddresses.Add("alias@example.com");
EmailCompositionResult reply = EmailComposer.ReplyAll(message,
new EmailAddress("me@example.com", "Example User"), "Thanks for the update.", composition);
reply.Document.Save("reply.eml");
Reply prefers Reply-To over From. ReplyAll also selects the original To/Cc recipients, excludes the
composing address and configured aliases, and deduplicates addresses. Bcc is never copied. Exchange
directory addresses that need resolution produce diagnostics. The new draft receives References and
In-Reply-To, bounded to the most recent 100 identifiers by default. Source transport headers, signatures,
MAPI metadata, attachments, and the original Message-ID are not inherited.
Forward starts with no recipients or attachments; add the intended recipients and attachments explicitly.
These builders quote the plain-text alternative, with a 256 KiB character limit and Unicode-safe truncation.
HTML-only messages return a missing-plain-body diagnostic. Inspect the result before handing a draft to a
transport such as Mailozaurr.
Create a field-selected share copy
Create an independent EML model with a reviewed plain-text body:
EmailShareCopyResult share = EmailShareCopy.Create(message, new EmailShareCopyOptions {
ReplacementSubject = "Shared discussion",
ReplacementBodyText = "Text reviewed for sharing"
});
share.Document.Save("share.eml");
The default copies the original plain-text body and omits the original envelope, Bcc, threading,
extra headers, attachments, HTML/RTF, raw source, MAPI/TNEF metadata and protected wrappers.
RetainedFields selects subject, author, To/Cc or date. AddressReplacements replaces selected
addresses or omits them with a null replacement; display names require KeepDisplayNames.
RetainedHeaderNames selects extra headers, while envelope (including Resent-*), MIME and integrity headers remain
owned by the new artifact. Changes records copied, replaced and omitted field paths without
original values. Diagnostics explain removed integrity evidence and unavailable plain bodies.
Select ordinary attachment indexes explicitly through AttachmentIndexes. Selected payload bytes
are copied independently and remain unchanged; generic filenames are used unless explicitly retained
or replaced through AttachmentNames. Linked paths are never opened, and embedded messages require
separate field-selected copies. Defaults allow 100 selected attachments, 64 MiB per payload, 256 MiB
total, and 2 Mi characters per retained text field. The source document is unchanged.
Review retained body text, selected extra headers and opaque attachment content before sharing. Field selection does not anonymize their contents or preserve the original signature assurance. The optional HTML bridge supplies bounded text projection and selected concealed-content cleanup.
OfficeIMO.Email provides a first-party engine for persisted email and Outlook artifacts without a third-party message, compound-file, MIME, RTF, or platform-UI runtime.
dotnet add package OfficeIMO.Email
S/MIME structure detection and unchanged protected-message pass-through are included without a cryptographic package. Install the provider only when the application signs, encrypts, verifies, or decrypts S/MIME:
dotnet add package OfficeIMO.Security
Email reads expose an aggregate ProcessingBudget snapshot. MIME, MSG, embedded TNEF, and streaming payload paths share one operation ledger, so nested parsers do not receive fresh attachment, property, or structural allowances. EmailLimitExceededException.Diagnostic carries a stable actionable non-sensitive diagnostic automatically; store limits expose the equivalent through EmailStoreDiagnostic.FromLimit.
Store table, content-search, and OAB search checkpoints are versioned persistence values bound to a complete-source SHA-256 and exact query signature. Persist the checkpoint's Value, parse it after restart, and expect resume to fail closed if the source bytes or query changed. Creating a durable checkpoint intentionally reads the complete selected source to establish that identity.
EmailStoreSession.SearchWithReport adds scan/result completion evidence to lightweight metadata
search. SearchContent supplies semantic field matches, snippets and durable batch continuation.
Each content match also exposes ResumeAfter, a checkpoint immediately after that item; consumers
returning only a prefix of a batch can resume there without losing the remaining matches.
For repeated queries over one store file, use EmailStoreSession.OpenSnapshot(path) or its stream overload.
The session makes a bounded private copy and hashes it while copying, then reuses the complete-source SHA-256
for queries and checkpoints. Caller-side changes after opening cannot change the snapshot's results.
Keep the original source stable while it is copied and dispose the session to remove its temporary file.
Opening a new snapshot still validates checkpoints against the newly copied bytes; ordinary sessions continue
to check the source before and after durable queries. Directory sessions are live catalogs: durable queries verify file membership, logical folders, and source content before and after scanning. A changed catalog requires reopening; directory snapshots are not implemented.
EmailStoreSession.PlanMaintenance is read-only and source-bound. It returns CompleteInspection rather than None whenever item, recovery, structural page, block, or byte bounds leave evidence incomplete, or when requested structural verification is unsupported for the source format. Executable repair remains a separate operation through recovery export, PST compaction, or PST split planning; OfficeIMO never repairs the opened source in place and rewrite paths require semantic post-verification.
The package supports:
- EML and MIME messages, including multipart bodies, encoded headers, inline resources, attachments, and embedded messages
- Outlook MSG and OFT files with standard and named MAPI properties, legacy code pages, recipients, embedded messages, linked attachments, and OLE/custom-storage attachments
- MS-OXRTFCP compressed and uncompressed RTF bodies, including bounded expansion and checksum validation
- Outlook messages, appointments, contacts, tasks, journals, and sticky notes with typed read/write models
- standalone iCalendar (
.ics) and vCard (.vcf/.vcard) documents with ordered, lossless content-line mutation, validation, bounded I/O, and standards-based EML projection - TNEF payloads such as
winmail.dat - mboxo and mboxrd mailbox archives
- PST, OST, Outlook for Mac OLM, EMLX, Apple Mail, Maildir, and mailbox-directory stores
- Outlook Offline Address Book discovery, v4 entry decoding, search, validation, and offline identity resolution
- one mixed-artifact discovery API for individual messages, calendars, contacts, stores, and OAB files
- reopenable attachment content, file-backed streaming reads, and per-message mbox streaming for large or store-backed workflows
- bounded synchronous and genuinely asynchronous source/destination I/O, immutable reader configuration, cancellation, and structured diagnostics
- deterministic EML, MSG, OFT, TNEF, and mbox writing with explicit conversion-loss policy
- versioned semantic fingerprints and value-free comparison reports for migration verification and deduplication
MSG output includes the root storage identity, complete named-property forward and reverse mappings, and the compatibility metadata required by native Outlook. A document without an explicit date receives a deterministic creation-time fallback; set Date or MessageMetadata.CreatedDate when the real timestamp matters.
The package depends on OfficeIMO.Rtf, which owns RTF syntax and semantic conversion. OfficeIMO.Email directly declares Microsoft's code-page compatibility library because its MIME, MSG, and TNEF readers use legacy character encodings themselves. MSG compound storage is shared OfficeIMO source compiled into OfficeIMO.Email; it is not a public general-purpose CFB package. This keeps the product graph explicit without copying RTF or CFB logic into the facade.
Read and write a message
using OfficeIMO.Email;
EmailDocument message = EmailDocument.Load("message.msg");
Console.WriteLine(message.Subject);
Console.WriteLine(message.Body.Text);
message.Save("message.eml");
Save infers EML, MSG, OFT, or TNEF from .eml, .mime, .msg, .oft, .tnef, or winmail.dat. The convenience methods throw InvalidDataException instead of silently returning a partial document or output when an error diagnostic is produced. Use the explicit overload only when the destination name has another extension:
message.Save("artifact.bin", EmailFileFormat.OutlookMsg);
The async API has the same shape:
EmailDocument message = await EmailDocument.LoadAsync("message.msg", cancellationToken: cancellationToken);
await message.SaveAsync("message.eml", cancellationToken: cancellationToken);
Path-based saves replace an existing destination by default. Use FailIfExists when exporting into a shared or
user-managed directory where claiming a new filename must be atomic and an existing artifact must remain unchanged:
await message.SaveWithConflictPolicyAsync(
"message.eml",
EmailFileConflictPolicy.FailIfExists,
cancellationToken: cancellationToken);
Use EmailDocumentReader when the host needs custom limits, raw-source preservation, or structured diagnostics:
var options = new EmailReaderOptions(
maxInputBytes: 64L * 1024L * 1024L,
maxAttachmentBytes: 32L * 1024L * 1024L,
includeAttachmentContent: true);
EmailReadResult result = await new EmailDocumentReader(options).ReadDocumentAsync("message.msg");
foreach (EmailDiagnostic diagnostic in result.Diagnostics) {
Console.WriteLine($"{diagnostic.Severity}: {diagnostic.Code}: {diagnostic.Message}");
}
if (result.HasErrors) {
// The advanced API leaves recovery policy to the host.
}
When attachment payloads should not be retained in managed arrays, use the streaming reader. Ordinary MIME, MSG/OFT, and TNEF attachments become reopenable temporary-file sources while headers, bodies, recipients, and typed Outlook fields keep the same model:
using EmailReadResult result = await new EmailDocumentReader(options)
.ReadDocumentAsync("large-message.msg", EmailReadContentStorage.TemporaryFiles, cancellationToken);
foreach (EmailAttachment attachment in result.Document.Attachments) {
using Stream content = await attachment.OpenContentStreamAsync(cancellationToken);
await content.CopyToAsync(destination, 81920, cancellationToken);
}
Dispose the EmailReadResult after consuming its file-backed content. Its temporary files and attachment sources
belong to that result and become unavailable after disposal. Save, SaveAsync, Write, and WriteAsync consume
ContentSource attachments through the same bounded writer pipelines instead of first materializing the complete
artifact. The async path uses asynchronous source and destination I/O rather than wrapping the synchronous writer
in a task.
The same model can be written as EML, MSG, OFT, or TNEF. Conversion is a load followed by a save:
EmailDocument.Load("source.eml").Save("converted.msg");
Known semantic loss is blocked by default. This includes changing or cross-converting a signed/encrypted artifact, dropping Outlook recurrence or time-zone blobs into iCalendar, converting an Exchange contact whose address depends on an opaque entry identifier, and writing journal or sticky-note semantics as EML. Analyze the conversion before opening a destination when the host needs to present those choices:
var writer = new EmailDocumentWriter();
EmailConversionReport report = writer.AnalyzeConversion(message, EmailFileFormat.Eml);
foreach (EmailDiagnostic diagnostic in report.Diagnostics) {
Console.WriteLine($"{diagnostic.Severity}: {diagnostic.Code}: {diagnostic.Message}");
}
if (report.CanWrite) {
EmailWriteResult result = writer.Write(message, "converted.eml");
result.ThrowIfLoss();
}
Use EmailConversionLossPolicy.Warn only when the application has made an explicit decision to accept a documented
loss. Opaque MAPI/TNEF metadata that has no portable EML equivalent is reported as a warning while common message
content remains writable. Every artifact writer returns the same EmailWriteResult: SourceSelection says whether
preserved bytes or regenerated model content was emitted, AttachmentContentLifetime records whether bounded content
sources were opened for that operation, DiagnosticCodes retains stable evidence, and LossDisposition distinguishes
no known loss, explicitly accepted loss, and a blocked write. Transport adapters can carry that result without defining
another message or artifact model.
Regenerating a message with DKIM, DomainKey, or ARC signatures is blocked by default because serialization can
invalidate those signatures. Choose new EmailWriterOptions(OfficeSignatureMutationPolicy.RemoveInvalidatedSignatures)
to remove the signature chain from the output, or PreserveSignatureMarkup to retain it with an invalidation warning.
The enum is in the OfficeIMO namespace. Neither option verifies signatures or overrides the separate S/MIME loss
policy. Unchanged raw-source output preserves the original bytes and headers. Regenerated output omits retained
Content-Length, Content-MD5, Content-Digest, Repr-Digest, and Digest headers and reports their removal.
These policies also cover embedded messages and do not mutate the input model's header collection.
Use EmailAttachmentTextReader.Read(attachment, maxBytes, cancellationToken) for text attachments. It honors the
MIME charset, uses a Unicode BOM when present, and returns the text, effective charset, bytes consumed, and decoding
diagnostics. Charsetless text uses UTF-8 with Windows-1252 recovery; unavailable charsets and malformed byte sequences
produce warnings. The byte limit applies to decoded attachment bytes before text decoding.
Compare message semantics
Semantic comparison hashes a canonical, versioned projection rather than serialized bytes. The migration profile normalizes store identity and serialization details, the strict profile includes representation details, and the deduplication profile excludes synchronization and modification state:
EmailSemanticComparisonReport comparison = EmailSemanticComparer.Compare(source, destination);
if (!comparison.IsMatch) {
foreach (EmailSemanticDifference difference in comparison.Differences) {
Console.WriteLine($"{difference.Kind}: {difference.Path}");
}
}
Difference reports contain canonical paths and lengths, not message values. Before persisting fingerprints for
private mail, provide a random digestKey through EmailSemanticComparisonOptions; the resulting HMAC-SHA-256
fingerprints cannot be correlated without that caller-owned key.
Read an mbox archive
An mbox file is an aggregate, so it has a dedicated reader rather than pretending to be one message:
var mailboxReader = new EmailMailboxReader();
EmailMailboxReadResult result = mailboxReader.Read("archive.mbox");
foreach (EmailMailboxEntry entry in result.Mailbox.Messages) {
Console.WriteLine($"{entry.EnvelopeSender}: {entry.Document.Subject}");
}
EmailMailboxWriter writes mboxo or mboxrd with deterministic envelope and escaping behavior.
For a large mailbox, enumerate or write one entry at a time:
var reader = new EmailMailboxReader();
foreach (EmailMailboxEntryReadResult item in reader.ReadEntries("archive.mbox")) {
Console.WriteLine(item.Entry.Document.Subject);
}
using Stream destination = File.Create("export.mbox");
new EmailMailboxWriter().WriteEntries(entries, destination);
ReadEntries retains at most one decoded message and restores a seekable caller-owned stream when enumeration ends.
WriteEntries writes completed entries directly, so a later enumeration or size failure can leave earlier entries in
the destination; use the aggregate EmailMailbox.Save API when atomic file replacement is required.
Outlook item projections
MSG and TNEF properties remain available through MapiProperties even when no convenience property exists. Common Outlook item fields are also projected onto typed models:
EmailDocument item = EmailDocument.Load("meeting.msg");
if (item.OutlookItemKind == OutlookItemKind.Appointment && item.Appointment is not null) {
Console.WriteLine(item.Appointment.Start);
Console.WriteLine(item.Appointment.End);
Console.WriteLine(item.Appointment.Location);
}
Equivalent projections are available through Contact, Task, Journal, and Note.
Personal distribution lists use OutlookItemKind.DistributionList and OutlookDistributionList. Member and One-Off
EntryIDs remain synchronized, validation enforces Outlook's per-property byte limit, and malformed identities keep
their raw bytes and diagnostics. Meeting request/response/cancellation and task request/accept/reject/update items also
have typed lifecycle projections instead of requiring message-class string switches.
Decoded appointment and task recurrence uses one OutlookRecurrence model across MSG, TNEF, and PST. Expansion is
always bounded and stays in local-clock space until the caller supplies either a system time zone or the decoded
Outlook time-zone definition:
OutlookRecurrenceExpansionResult occurrences = OutlookRecurrenceExpander.Expand(
item.Appointment!.Recurrence!,
new OutlookRecurrenceExpansionOptions {
WindowStart = new DateTime(2026, 7, 1),
WindowEnd = new DateTime(2026, 8, 1),
MaxOccurrences = 500
});
OutlookRecurrenceIcsExportResult exported =
OutlookRecurrenceIcsConverter.Export(item.Appointment.Recurrence!);
Modified and deleted occurrences remain explicit. ICS import/export returns a conversion report and does not silently drop a recurrence pattern, exception, or time-zone constraint it cannot represent.
An Outlook template uses the same model and compound-file engine as MSG while retaining its template identity:
EmailDocument template = EmailDocument.Load("meeting.oft");
template.Subject = "Reusable meeting request";
template.Save("updated.oft");
Standalone iCalendar and vCard documents
EmailPortableContentExport.ToCalendar(item) exports an Outlook appointment or task as a standalone ICS stream.
ToVCard(item) exports an individual contact. Both return an editable document, a detached UTF-8 byte snapshot and
diagnostics. Unchanged imported semantic content retains its unknown properties. Regeneration uses the same loss
checks as EML conversion and blocks opaque recurrence, nonportable addresses or changed imported semantics by
default. Select EmailConversionLossPolicy.Warn explicitly when reviewing a lossy projection. These exports do not
preserve the mail envelope, ordinary attachments or transport signatures.
When a message contains several projected calendar or contact MIME parts, export retains every matching part.
The imported source byte limit applies across those parts, with at most 1,000 semantic parts per item.
MIME calendar methods are carried into roots that omit METHOD. Unencoded vCard property charset declarations
are updated to UTF-8; quoted-printable and Base64 payload spellings keep their source charset. These normalizations
have explicit diagnostics. Decoded parsing allows bounded UTF-8 expansion without counting it as imported bytes.
EmailPortableContentExportResult<IcsDocument> exported =
EmailPortableContentExport.ToCalendar(item);
File.WriteAllBytes("meeting.ics", exported.ToBytes());
EmailPortableContentExportResult<VCardDocument> cards =
EmailPortableContentCollection.ToVCards(selectedContacts,
new EmailPortableContentExportOptions(maxOutputBytes: 8 * 1024 * 1024));
File.WriteAllBytes("contacts.vcf", cards.ToBytes());
EmailPortableContentCollection.ToCalendars keeps separate VCALENDAR roots rather than combining timezone,
UID or METHOD scopes. Collection output has one aggregate byte limit and an item limit. The source byte limit
applies to each item's imported semantic content. Generated output is bounded while the codec accumulates it;
these options do not limit the size of a caller-created in-memory Outlook model.
EmailContactConsolidation.Review takes provenance-tagged EmailContactSource contacts. It groups candidates
by exact SMTP addresses and, when supplied, a complete OfflineAddressBookIdentityIndex with an unambiguous
authoritative address match. Display names never create a match. Shared addresses can belong to different people,
so a candidate group is a review suggestion. EmailContactSource.FromAddressBook uses the OAB owner's contact
mapping and rejects distribution lists.
Review groups retain conflicting field variants, ordered repeated values, parameters and source IDs.
Consolidate(review, groupIndex, choices) creates an independent vCard. Every conflicting field needs an explicit
zero-based choice index keyed by EmailContactReviewField.Key; -1 explicitly omits that field. Required vCard
fields, output size and property limits are checked. Reviewing contacts can project opaque Outlook identity data
with warnings; inspect review.Diagnostics before consolidation. The APIs do not update a store or directory.
IcsDocument and VCardDocument expose the same ordered content-line model used by MIME projections. Repeated,
grouped, unknown, IANA, and X- properties and their parameters remain available for inspection and mutation instead
of being discarded by a narrow typed projection:
IcsDocument calendar = IcsDocument.Load("meeting.ics");
ContentLineComponent meeting = calendar.GetComponents("VEVENT").Single();
meeting.SetProperty("SUMMARY", "Updated planning meeting");
meeting.SetTemporalValue("DTSTART",
IcsTemporalValue.Zoned(new DateTime(2026, 7, 20, 9, 0, 0), "Europe/Warsaw"));
IReadOnlyList<ContentLineValidationIssue> calendarIssues = calendar.Validate();
calendar.Save("updated.ics");
VCardDocument contacts = VCardDocument.Load("contacts.vcf");
ContentLineComponent contact = contacts.Cards[0];
contact.SetVCardText("FN", "Ada Lovelace");
contact.AddProperty("EMAIL", "ada@example.test").SetParameter("TYPE", "work");
IReadOnlyList<ContentLineValidationIssue> contactIssues = contacts.Validate();
contacts.Save("updated.vcf");
iCalendar temporal helpers retain DATE, floating, UTC, and TZID-local forms without resolving identifiers through
the host operating system. RRULE helpers parse and update known recurrence parts while retaining unknown parts.
vCard 2.1, 3.0, and 4.0 syntax is supported, including groups, repeated properties, binary/data-URI values, RFC 6868
parameter escaping, legacy quoted parameters, and quoted-printable continuation. Validation reports conformance
issues; it does not erase vendor data. Legacy .vcs vCalendar files use the same preservation model, while validation
continues to report constructs that are not RFC 5545 iCalendar 2.0.
When an appointment or task is written as EML, it becomes a text/calendar iCalendar part. Contacts become vCard
attachments. Reminders become VALARM; task fields without a direct iCalendar property use valid X-OFFICEIMO-*
extensions so they survive an OfficeIMO EML/MSG/TNEF cycle while remaining ignorable to other calendar readers.
Reading those parts restores the corresponding typed model. Source calendar/vCard bytes are retained
while the projected model is unchanged; editing a projected item is blocked by default when regeneration could omit
unmodeled source properties. Meetings whose only attendee data is display text are also blocked because a valid
iCalendar ATTENDEE requires an address. Journal and sticky-note models remain lossless across MSG/TNEF, but have no
standard EML representation and therefore require an explicit non-blocking loss policy for EML output.
Properties that do not have a convenience field remain available through the typed Mapi property bag. The shared
MapiKnownProperties vocabulary covers the standard and Outlook named properties understood by OfficeIMO, while
custom named properties use the same strongly typed key contract:
string? displayName = item.Mapi.GetValueOrDefault(MapiKnownProperties.PidTag.DisplayName);
var customName = new MapiPropertyKey<string>(
"CustomName",
MapiPropertySets.PublicStrings,
"CustomName",
MapiPropertyType.Unicode,
MapiPropertyType.String8);
string? customValue = item.Mapi.GetValueOrDefault(customName);
item.Mapi.Set(customName, "Retained with the artifact");
RTF bodies
EmailBody.Rtf contains the byte-preserving RTF source decoded from PidTagRtfCompressed. The MSG and TNEF writers serialize an assigned RTF body with the MS-OXRTFCP compression format, and the reader accepts both the LZFu and MELA forms.
RTF syntax editing and semantic conversion belong to OfficeIMO.Rtf. Generate RTF through that package when the source contains characters that need RTF escapes. OfficeIMO.Reader will route an RTF-only email body through the registered OfficeIMO.Reader.Rtf handler; without that optional adapter, it preserves the RTF source and reports the fallback explicitly.
Protected messages
EmailDocument.Protection detects opaque and clear-signed S/MIME plus signed or encrypted OpenPGP/MIME wrappers. It
retains the original artifact bytes automatically, including Outlook's complete outer multipart/signed attachment
for IPM.Note.SMIME.MultipartSigned. EmailSmime creates and verifies clear/opaque S/MIME, creates and decrypts
EnvelopedData, and supports sign-then-encrypt through an explicitly supplied security provider; OpenPGP remains outside this package.
Writing an unchanged protected document in its source format emits those bytes verbatim; an edited or cross-format
write is blocked by default because regenerating the wrapper would invalidate its cryptographic meaning.
using System.Security.Cryptography.X509Certificates;
using OfficeIMO.Security;
using X509Certificate2 recipient = LoadRecipientCertificate();
using X509Certificate2 signingCertificate = LoadSigningCertificate();
EmailDocument protectedMessage = EmailDocument.Load("message.eml");
IOfficeSecurityProvider security = OfficeSecurityProvider.Default;
EmailSmimeVerificationResult verified = EmailSmime.Verify(protectedMessage, security);
if (verified.IsCryptographicallyValid) {
Console.WriteLine(verified.SignedContent?.Subject);
}
EmailSmimeDecryptionResult decrypted = EmailSmime.Decrypt(protectedMessage, recipient, security);
if (decrypted.Decrypted) {
Console.WriteLine(decrypted.DecryptedContent?.Body.Text);
}
EmailSmimeProcessingResult processed = EmailSmime.DecryptThenVerify(
protectedMessage, recipient, security);
Console.WriteLine(string.Join(", ", processed.ProcessingOrder));
EmailDocument outgoing = new EmailDocument {
Subject = "Protected report"
};
outgoing.Body.Text = "Attached report details";
EmailSmimeCreationResult signed = EmailSmime.Sign(
outgoing,
signingCertificate,
security,
EmailSmimeSignatureMode.ClearSigned);
File.WriteAllBytes("signed.eml", signed.Message);
EmailSmimeCreationResult encrypted = EmailSmime.SignAndEncrypt(
outgoing,
signingCertificate,
new[] { recipient },
security);
File.WriteAllBytes("signed-and-encrypted.eml", encrypted.Message);
Certificate/key discovery is intentionally not implicit. Verification accepts caller trust/revocation policy through
CmsVerificationOptions and applies the S/MIME email-signing certificate purpose, including the standard
email-protection EKU; creation and decryption require explicitly supplied certificates and a provider. The original
protected document is never mutated, and the decrypted/signed projection is returned separately. Detached verification first
uses the exact retained MIME bytes and, only when necessary, retries the standard CRLF canonical form used by S/MIME
mail clients; SignedMimeEntity still exposes the original bytes and a structured diagnostic records the fallback.
Results name the concrete provider and project signer identity, chain-building, revocation, timestamp, and offline-policy
status into stable email diagnostic codes. DecryptThenVerify records and enforces the outer-decrypt, inner-verify order,
while an unparseable protected entity remains available as retained bytes plus diagnostics.
On .NET 8 and later, the Security provider decrypts RSA PKCS#1/OAEP with AES-CBC through the supplied
platform key handle without exporting private parameters. Keychain identity selection remains caller-owned.
Other envelope profiles and older targets require an exportable RSA key and report
EnvelopePrivateKeyNotExportable when export is unavailable.
Mailbox stores and store-backed content
PST, OST, Outlook for Mac OLM, and Apple Mail EMLX containers are included in OfficeIMO.Email. The Store APIs yield ordinary EmailDocument instances while preserving folder paths, store metadata, diagnostics, and bounded attachment behavior.
EmailStoreSession.IsPstPasswordProtected and EmailStoreInspectionReport.IsPstPasswordProtected expose the PST header's password-protection state. PST uses a checksum-based access deterrent, not cryptographic content encryption; these properties do not claim confidentiality or decrypt content.
using OfficeIMO.Email.Store;
using EmailStoreSession session = EmailStoreSession.Open("archive.pst");
EmailStoreItemReference firstReference = session.EnumerateItems(
new EmailStoreEnumerationOptions(maxItems: 1)).Single();
EmailDocument firstMessage = session.ReadItem(firstReference).Document;
session.AnalyzeArchive() returns read-only folder and UTC month distributions, large attachment metadata and
semantic duplicate candidates. It projects bounded bodies, recipients and attachment metadata; it does not request
attachment payloads or embedded-item content. Matching candidates can contain different attachment bytes and
unloaded properties, so the report does not establish duplicate equality or select mail for deletion.
EmailArchiveAnalysisReport analysis = session.AnalyzeArchive(
new EmailArchiveAnalysisOptions(maxItems: 10_000, maxLargeAttachments: 25));
Console.WriteLine($"Scanned {analysis.ItemsScanned}; exhausted references: {analysis.ExhaustedSelectedReferences}");
Console.WriteLine($"Candidate groups: {analysis.DuplicateCandidateGroupCount}");
The report rechecks a SHA-256 of the complete persisted source. That source hashing performs I/O even though
attachment payloads are not decoded for analysis. OpenSnapshot can reuse its owned snapshot fingerprint.
Header-only and potentially partial local items are excluded from candidate matching. Scan limits, failed analyses,
source warnings, omitted distribution buckets, omitted candidate IDs/groups and diagnostic totals remain explicit.
ExhaustedSelectedReferences describes the session's regular-reference enumeration; it does not prove that a
damaged source catalog includes every original item. Failed analysis can occur after an item was projected.
EstimatedCandidateDeclaredBytes uses available item size declarations and excludes the largest member in each
candidate group. It is neither verified duplicate savings nor a physical PST compaction estimate. No archive is changed.
Long-running PST/OST/OLM/EMLX/Mbox/mail-directory migrations can opt into an atomic checkpoint. The checkpoint binds the exact source byte fingerprint, bounded source catalog, destination, conversion options, writer state, item provenance, and verification journal. Resume rejects changed sources or options instead of silently continuing against different data:
var options = new EmailStorePstConversionOptions(
checkpointPath: "migration.checkpoint",
checkpointIntervalItems: 500,
partialResultPolicy: EmailStorePartialResultPolicy.RetainResumableState,
verifyAfterWrite: true,
failOnDataLoss: true);
EmailStorePstConversionReport migration = EmailStoreConverter.ConvertToPst(
"source-mail", "destination.pst", conversionOptions: options);
Console.WriteLine($"{migration.Disposition}; resumed={migration.WasResumed}");
Attachment streams remain bounded and operation-scoped. A requested verification manifest records keyed fingerprints,
ordinals, outcomes, and difference-path tokens without subjects, addresses, message content, filenames, or store IDs.
Use DiscardIncompleteState when an interrupted migration must not retain its writer-owned staging files.
Use EmailDataArtifact.Open from the included OfficeIMO.Email.Data namespace when an application wants one discovery entry point across individual artifacts, stores, and OAB files. No additional package is required.
Outlook Express DBX
Open one Outlook Express message folder or open Folders.dbx by path to import
the local folder hierarchy. Keep the referenced mailbox files beside the catalog.
Folder names and parent links come from the catalog. An unavailable referenced
mailbox is reported separately from an empty folder.
using OfficeIMO.Email.Store;
using EmailStoreSession source = EmailStoreSession.Open("Mail backup/Folders.dbx");
EmailStoreExportReport export = source.ExportToDirectory("Exported EML");
foreach (EmailStoreExportEntry entry in export.Entries) {
Console.WriteLine(entry.DestinationPath);
}
Open a standalone message database such as Inbox.dbx from a path or a readable
seekable stream. Use EmailStoreSession.OpenSnapshot for repeated metadata
searches or EML export from a standalone DBX file. It copies the source into
private temporary storage once and reuses that stable copy. Keep the original
source stable until snapshot capture returns. Folders.dbx uses the live
path-based catalog and sibling validation.
DBX import reads indexed local RFC messages and their MIME attachments. It supports Windows-1252 catalog names and reports malformed indexes and fragment chains. EML export serializes the projected message. DBX writing, deleted-item carving, remote account recovery, and earlier Outlook Express mailbox formats are outside this profile.
Native DBX original subject, importance and representable declared message size fill the existing typed metadata. MIME importance takes precedence over the native priority. Declared size is a source hint and never controls message admission, which uses the actual fragment lengths. Native strings retain the Windows-1252 qualification. Native subject text shares the selected read's decoded-property budget with MIME content.
Native DBX received times fill missing MIME arrival metadata. An existing MIME
Received timestamp takes precedence. Directory export appends ReceivedAtUtc
to the preservation manifest, retaining arrival metadata beside EML files.
EMLX metadata stores whole-second arrival times. With the manifest disabled,
export reports an omitted arrival time or loss of sub-second EMLX precision.
Apple Mail and Outlook for Mac
Open an exported Apple Mail .mbox package, its containing folder, or a copied Mail directory
with EmailStoreSession.Open(path). Packages containing an aggregate mbox file and directories
containing individual EMLX messages use the same folder and item APIs. Account directories remain
part of folder identity, empty mailbox folders are retained, and AppleDouble ._ sidecars are skipped.
MaxDirectoryEntryCount bounds every visited entry, including unrelated files and directories;
message/attachment-storage file, item, folder, depth, and source-byte limits are separate.
EMLX reads support XML and binary property lists. document.Properties["Emlx:Metadata"] contains
an ordinal, case-sensitive metadata dictionary. This is the authoritative editable catalog; flat
Emlx:Metadata:* properties are read aliases and are used for writing only when no catalog exists. Editing and
writing EMLX preserves unknown supported values and unknown flag bits while updating projected
message flags. Unsupported or malformed trailers remain in Emlx:RawMetadata: Block rejects
opaque metadata rewrites, while Warn and Allow copy the trailer unchanged and report that edits
could not be reconciled. The default Block policy rejects exports that omit retained EMLX, OLM
or MAPI/TNEF metadata, including regenerated embedded messages. Regenerated embedded messages also
undergo the same calendar, contact and protected-content loss checks as the outer message, including
task payloads synthesized from TaskCommunication.EmbeddedTask.
Exact preserved MIME attachment payloads are copied without regenerating their projected models.
Select new EmailWriterOptions(EmailConversionLossPolicy.Warn) to export
the common message content with diagnostics for the omitted fields.
Live EMLX, mbox and OLM sessions validate their source with a bounded SHA-256 before and after each
selected read, rejecting detected changes including same-length edits. Directory sessions pin each message and recovered attachment
file when it is first projected, and reject subsequent content changes. A detected change expires
retained attachment streams; reopen the session to read the changed source.
The buffer size stays fixed, but each check reads the complete artifact or selected directory file.
Use EmailStoreSession.OpenSnapshot for repeated reads of a standalone archive when a private stable
copy can avoid repeated source hashing. The initial snapshot copy and hash perform source I/O.
Use an exported or otherwise quiescent archive when the source is actively written; these reads do
not take an atomic filesystem snapshot.
Directory sessions recover empty MIME parts in Messages/<numeric-id>.partial.emlx
from Attachments/<numeric-id>/<one-based-MIME-part-path>/<file>. For example, nested part
2.1 is the first child of the second root part. Each part directory must contain exactly
one nonempty regular file. Recovery uses MIME identity rather than the attachment filename and
never leaves the selected root or follows links. Opening just Messages or a standalone
EMLX file cannot grant access to sibling storage.
Emlx:RecoveredPartCount and Emlx:UnresolvedPartCount describe the identified placeholders.
Base64, quoted-printable, 7bit, 8bit and binary placeholders are reconstructed as Base64;
original transfer formatting and payload-dependent integrity headers are not retained.
Missing, ambiguous, malformed, unsupported-encoding and protected parts remain unavailable.
Unresolved content is marked indeterminate in ContentAvailability and reported during
conversion. Apple’s X-Apple-Content-Length is retained as provenance; it is not a verified
decoded sibling length. Metadata reads also use a bounded temporary reconstruction to
derive actual payload lengths. Selected streaming reads return session-owned content sources.
Offline recovery cannot establish whether further content exists remotely, so partial
sources retain a completeness diagnostic; Block rejects the conversion, while Warn and Allow
accept it with that diagnostic. The qualification runner
distinguishes the pinned independent storage fixture from native Apple Mail acceptance.
OLM sessions retain summaries and one bounded XML entry, then project selected records. They
preserve nested, repeated, attributed, and case-colliding fields as XML fragments in
Olm:StructuredProperties, and item attributes in Olm:ItemAttributes. Export reports archive
metadata that has no target representation. OLM creation and rewriting are outside the contract.
using EmailStoreSession session = EmailStoreSession.Open("Mail Export");
EmailStoreItemReference reference = session.EnumerateItems().First();
EmailStoreItem selected = session.ReadItem(reference,
new EmailStoreItemReadOptions(preferStreamingAttachmentContent: true));
EMLX, Mbox, mailbox-directory, and OLM selected reads honor the streaming preference. Decoded attachment
files belong to the session; disposing it closes outstanding readers and expires their content
sources. Repeated streaming reads consume the session's aggregate attachment and retained-read
budgets. Keep the session open while writing or copying that content. ReadAll remains a
materializing convenience and follows RetainAttachmentContent.
Store-backed attachment content
EmailAttachment.Content remains the simple in-memory representation. A mailbox or archive provider can instead set
ContentSource to an IEmailContentSource that opens a fresh decoded stream on demand:
EmailAttachment attachment = item.Attachments[0];
using Stream content = await attachment.OpenContentStreamAsync(cancellationToken);
await content.CopyToAsync(destination, 81920, cancellationToken);
EML, MSG, and TNEF writers consume either representation through the same bounded path. The interface deliberately
contains no PST, OST, MAPI, or Outlook types, so mailbox and store owners can yield ordinary EmailDocument
instances while keeping source lifetime and property-stream access in the owning Store API area.
Safe HTML and text projection
Install the optional OfficeIMO.Email.Html bridge when a consumer needs one shared body-selection, RTF-fallback,
sanitization, and resource-resolution contract. It chooses HTML, RTF, or plain text under an explicit policy, blocks
remote resources by default, resolves CID/content-location/filename references, and exposes bounded operation-scoped
resources plus a prepared HtmlConversionDocument. OfficeIMO.Email.Image and OfficeIMO.Reader.Email consume this
same bridge; Reader can then project the prepared safe document to text or Markdown. The core OfficeIMO.Email package
does not reference AngleSharp or another HTML engine.
Inspect local email data
OfficeIMO.Email.Data.EmailDataInspector reports metadata through the existing artifact readers:
using OfficeIMO.Email.Data;
EmailDataInspectionReport report = EmailDataInspector.Inspect("message.eml",
new EmailDataInspectionOptions(maxSamples: 32));
foreach (EmailDataBodyAlternative body in report.Bodies)
Console.WriteLine($"{body.Kind}: {body.CharacterCount} UTF-16 units; charset {body.DeclaredCharset}");
Individual-message reports include body alternatives, declared charsets, attachment metadata, protected-wrapper
classification, transport-signature header names and bounded diagnostic code/severity samples. They omit body
text, signature values, linked paths and original diagnostic messages, and never open deferred attachment streams.
Signature presence does not establish authenticity: CryptographicallyVerified is false.
Store and OAB inspection reports catalogs and declared counts without projecting all messages or address-book
entries. ICS/VCF inspection reports parsed root counts; use those format owners' Validate() operations for
semantic validation. These reports do not promise completeness beyond the selected owner's catalog or read policy.
The default inspection profile bounds individual messages and decoded properties to 16 MiB, store files to
4 GiB and 10,000 items, and OAB components to 64 MiB. OpenOptions supplies explicit owner-specific policies;
the overload accepting an existing EmailDataOpenResult keeps the caller's read policy and resource ownership.
Sample truncation and a bounded signature-header scan are visible in the report. Install OfficeIMO.Email.Html
for the optional HTML safety adapter. Inspection does not access the network, discover certificates, decrypt,
verify signatures, follow linked attachments or change the source.
Resource limits
EmailReaderOptions is immutable and applies limits before retaining decoded content. It controls source size, header size and count, MIME part count and depth, per-attachment and aggregate attachment bytes, embedded-message depth, CFB directory entries, MAPI properties and decoded property bytes, and TNEF attributes.
Use includeAttachmentContent: false when only attachment metadata is needed. Parsing still validates the source
structure, but ordinary decoded attachment payloads are not retained in the result model. Calendar and vCard parts
that define the typed item are retained because they are semantic message content, not optional file payloads.
Reader integration
OfficeIMO.Reader.Email recognizes .eml, .msg, .oft, .mbox, .mbx, .tnef, winmail.dat, .ics, .vcs,
.vcf, .vcard, PST, OST, OLM, EMLX, mailbox directories, and OAB data. Calendar and contact files route through the
public IcsDocument and VCardDocument engines. Store and address-book projections live in that same adapter package;
they add no separate NuGet layer and reuse this package's parsers and models. Rich results include envelope and Outlook
metadata, structured diagnostics, materializable attachment assets, embedded messages, and chunks extracted through
the Reader handlers configured by the host.
using OfficeIMO.Reader;
using OfficeIMO.Reader.Email;
OfficeDocumentReader reader = new OfficeDocumentReaderBuilder()
.AddEmailHandlers()
.Build();
OfficeDocumentReadResult result = reader.ReadDocument("message.msg");
Console.WriteLine(result.Source.Title);
foreach (OfficeDocumentAsset attachment in result.Assets) {
Console.WriteLine($"{attachment.FileName}: {attachment.LengthBytes}");
}
Scope boundary
OfficeIMO.Email owns offline artifact parsing, serialization, and format-neutral Outlook data. It does not connect to mail servers, authenticate users, send messages, discover certificates or private keys, or implement DKIM, ARC, or OpenPGP. EmailSmime.Sign, Encrypt, SignAndEncrypt, Verify, Decrypt, and DecryptThenVerify are thin data-oriented adapters over a caller-supplied IOfficeSecurityProvider: Email owns bounded MIME construction and exact protected-byte handling, while the provider owns CMS, certificates, and trust policy. The adapters create signed or encrypted MIME, verify exact clear-signed bytes and opaque signed-data, decrypt caller-selected EnvelopedData recipients, retain the original protected artifact, and return a separate parsed protected-content document when possible. Certificate/key and provider selection remain explicit and caller-owned.
The package does not expose general-purpose CFB transactions. Its Store API area owns PST, OST, OLM, EMLX, Mbox, Apple Mail, and Maildir traversal, selection, validation, native export, verified conversion, multi-store merge, and verified atomic rewrite mutation of an existing Unicode PST. ANSI PST mutation, OST mutation/writing, in-place NDB editing, append, in-place repair, and password/encryption authoring remain outside the contract. Store also owns distinct-destination verified compaction and query/size-based split; neither operation edits the open source.
For exact pass-through of an ordinary unprotected artifact, read with preserveRawSource: true and write with
usePreservedRawSource: true. Protected artifacts use safe unchanged pass-through automatically.
Dependency footprint
- External: no third-party email engine or Outlook interop.
System.Text.Encoding.CodePagessupplies legacy encodings. - OfficeIMO:
OfficeIMO.CoreandOfficeIMO.Rtf. MIME, MSG/MAPI, TNEF, mbox, iCalendar, vCard, Store, OAB, protected-wrapper detection, and compressed-RTF handling remain first-party and ship in this package. - Optional security: install
OfficeIMO.Securityfor S/MIME CMS/X.509 signing, encryption, verification, and decryption, or provide anotherIOfficeSecurityProvider. It is not a transitive Email dependency. - Optional HTML: install
OfficeIMO.Email.Htmlfor safe body/resource projection. HTML and RTF-to-HTML dependencies remain outside this core package.
See the complete OfficeIMO package map for related formats and conversion paths.
Generated capability summary
This table is generated from the package-neutral OfficeIMO operation catalog. The detailed source contracts remain authoritative for feature-level behavior and limitations.
| Operation | Supported | Partial | Preserved | Rejected | Unsupported | Not applicable |
|---|---|---|---|---|---|---|
| Create | 8 | 0 | 0 | 0 | 7 | 0 |
| Read | 15 | 0 | 0 | 0 | 0 | 0 |
| Edit | 6 | 0 | 4 | 1 | 4 | 0 |
| Preserve | 2 | 4 | 0 | 0 | 4 | 0 |
| Inspect | 15 | 0 | 0 | 0 | 0 | 0 |
| Validate | 11 | 0 | 0 | 0 | 0 | 3 |
| Remove | 0 | 0 | 0 | 0 | 1 | 4 |
| Convert | 12 | 0 | 0 | 0 | 0 | 0 |
| Export | 6 | 0 | 0 | 0 | 0 | 0 |
The complete rows for OfficeIMO.Email are published in the generated operation contract.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 is compatible. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.7.2
- OfficeIMO.Core (>= 3.6.1)
- OfficeIMO.Rtf (>= 3.6.1)
- System.Text.Encoding.CodePages (>= 8.0.0)
-
.NETStandard 2.0
- OfficeIMO.Core (>= 3.6.1)
- OfficeIMO.Rtf (>= 3.6.1)
- System.Text.Encoding.CodePages (>= 8.0.0)
-
net10.0
- OfficeIMO.Core (>= 3.6.1)
- OfficeIMO.Rtf (>= 3.6.1)
-
net8.0
- OfficeIMO.Core (>= 3.6.1)
- OfficeIMO.Rtf (>= 3.6.1)
NuGet packages (7)
Showing the top 5 NuGet packages that depend on OfficeIMO.Email:
| Package | Downloads |
|---|---|
|
OfficeIMO.Reader
Unified, read-only document extraction facade for OfficeIMO (Word/Excel/PowerPoint/Markdown/PDF) intended for AI ingestion. |
|
|
OfficeIMO.Email.Html
Dependency-isolated safe HTML, RTF, text, and inline-resource projection for OfficeIMO email artifacts. |
|
|
OfficeIMO.Reader.Email
Unified email, MHTML, Outlook store, and Offline Address Book adapter for OfficeIMO.Reader.Core. |
|
|
OfficeIMO.Mhtml
MHTML archive loading, saving, HTML projection, and embedded MIME resources for OfficeIMO. |
|
|
Mailozaurr.Artifacts
OfficeIMO.Email and MimeKit interoperability for EML, MSG, OFT, TNEF, and protected-message artifacts. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 3.6.1 | 515 | 11/10/2026 |
| 3.6.0 | 768 | 11/6/2026 |
| 3.5.3 | 4,841 | 10/31/2026 |
| 3.5.2 | 3,906 | 10/24/2026 |
| 3.5.1 | 3,651 | 10/16/2026 |
| 3.4.5 | 1,096 | 10/10/2026 |
| 3.4.4 | 1,700 | 9/27/2026 |
| 3.4.3 | 2,602 | 9/12/2026 |
| 3.4.2 | 701 | 9/9/2026 |
| 3.4.1 | 414 | 9/7/2026 |
| 3.4.0 | 371 | 9/6/2026 |
| 3.3.0 | 353 | 9/2/2026 |
| 3.2.7 | 420 | 8/29/2026 |
| 3.2.6 | 989 | 8/22/2026 |
| 3.2.5 | 466 | 8/21/2026 |
| 3.2.4 | 4,322 | 8/19/2026 |
| 3.2.3 | 1,723 | 8/17/2026 |
| 3.2.2 | 1,646 | 8/13/2026 |
| 3.2.1 | 431 | 8/11/2026 |
| 3.2.0 | 623 | 8/7/2026 |