Read and convert mailbox stores
Edit on GitHubRead PST, OST, OLM, mbox, EMLX, Apple Mail, Maildir, and mailbox directories in .NET, export messages, and convert supported stores to PST.
The Store API opens PST, OST, Outlook for Mac OLM, mbox, EMLX, Apple Mail, Maildir, and mailbox-directory sources without Outlook or COM. Store items are returned as ordinary EmailDocument objects while folder paths, store metadata, associated items, diagnostics, and bounded attachment access remain available.
Enumerate and read a PST or OST
using OfficeIMO.Email;
using OfficeIMO.Email.Store;
using EmailStoreSession session = EmailStoreSession.Open("archive.pst");
foreach (EmailStoreItemReference reference in session.EnumerateItems(
new EmailStoreEnumerationOptions(maxItems: 1000))) {
EmailStoreItem item = session.ReadItem(reference);
Console.WriteLine($"{reference.FolderPath}: {item.Document.Subject}");
}
Use reader options to set item, attachment, and total attachment limits before opening untrusted or very large stores.
Convert OST or another supported store to PST
ExportToPst and EmailStoreConverter.ConvertToPst write a new PST; they do not modify the source store.
using OfficeIMO.Email.Store;
using EmailStoreSession source = EmailStoreSession.Open("mailbox.ost");
EmailStorePstConversionReport report = source.ExportToPst(
"mailbox-export.pst",
new EmailStorePstConversionOptions(
continueOnItemError: true,
includeAssociatedItems: true,
includeOrphanedItems: true));
Console.WriteLine($"Converted: {report.ConvertedItems}");
Console.WriteLine($"Skipped: {report.SkippedItems}");
Console.WriteLine($"Verified: {report.Verification?.IsSuccessful}");
This is a source-to-new-PST conversion, not an in-place OST rewrite. The report distinguishes converted and skipped items and includes verification results when verification is enabled.
For a path-based conversion with explicit input limits:
var readerOptions = new EmailStoreReaderOptions(
maxItemCount: 100_000,
maxAttachmentBytes: 64L * 1024L * 1024L,
maxTotalAttachmentBytes: 2L * 1024L * 1024L * 1024L,
retainAttachmentContent: false);
EmailStorePstConversionReport report = EmailStoreConverter.ConvertToPst(
"archive.olm",
"archive.pst",
readerOptions,
new EmailStorePstConversionOptions(continueOnItemError: true));
Extract messages
Read each store item and save it in the message format your workflow requires:
Directory.CreateDirectory("messages");
using EmailStoreSession session = EmailStoreSession.Open("archive.pst");
int index = 0;
foreach (EmailStoreItemReference reference in session.EnumerateItems()) {
EmailDocument message = session.ReadItem(reference).Document;
message.Save(Path.Combine("messages", $"{index++:D6}.eml"));
}
Choose file names and directory layout from stable identifiers or sanitized metadata in production. Do not use untrusted subjects directly as paths.
Verify a migration without storing private values
PST conversion can write a verification manifest containing keyed semantic fingerprints, match status, paths, and lengths without message subjects, addresses, attachment names, or body values:
string encodedDigestKey =
Environment.GetEnvironmentVariable("OFFICEIMO_EMAIL_DIGEST_KEY")
?? throw new InvalidOperationException(
"Set OFFICEIMO_EMAIL_DIGEST_KEY to a private Base64-encoded key.");
byte[] digestKey = Convert.FromBase64String(encodedDigestKey);
var verificationOptions = new EmailSemanticComparisonOptions(digestKey: digestKey);
using EmailStoreSession source = EmailStoreSession.Open("source.ost");
EmailStorePstConversionReport report = source.ExportToPst(
"destination.pst",
new EmailStorePstConversionOptions(
verificationOptions: verificationOptions,
verificationManifestPath: "destination.verification.tsv"));
if (report.Verification is { IsSuccessful: false } verification) {
foreach (EmailStorePstVerificationIssue issue in verification.Issues) {
Console.WriteLine(issue.SourceItemId);
}
}
Generate the digest key outside the application, store it as a secret, and provide at least 16 random bytes. Do not commit or log it. The same key is required when comparing persisted fingerprints later. See safety and verification for comparison profiles and limits.