---
title: "Read an OLM file in C#"
url: https://recursiveai.org/onemail/cookbook/read-olm-file/
description: "Read an Outlook for Mac .olm file in C#: every folder, message, attachment, appointment, contact and task, with no Mac and no Outlook. Runnable code with OneMail 0.3.0-preview.2."
version: "0.3.0-preview.2"
---

# Read an OLM file in C#

Open the archive with `Mail.Open` and enumerate it. An `.olm` file is what Outlook for Mac exports, and it holds mail, calendar items, contacts, tasks and notes. Each record comes back as an `IMailItem` with its folder, so mail reads exactly like a PST. The program below reads the example archive of the OLMReader project (BSD-2-Clause).

```shell
dotnet new console -o ReadOlm && cd ReadOlm
dotnet add package RecursiveAI.OneMail --version 0.3.0-preview.2
curl -LO https://raw.githubusercontent.com/teverett/OLMReader/c3f14c3e49d181f180750a2125984fb67a82fd58/src/test/resources/Outlook16/outlook_example.olm
```

Put this in `Program.cs` and run `dotnet run`:

```csharp
using RecursiveAI.OneMail;

// Mail.Open reads the format from the bytes: an .olm is a zip of XML records
using MailContainer olm = Mail.Open("outlook_example.olm");
Console.WriteLine($"Format: {olm.Format}");

// Records are read one at a time, in the order they sit in the archive
List<IMailItem> items = olm.Enumerate().ToList();
foreach (var kind in items.GroupBy(i => i.Kind))
    Console.WriteLine($"{kind.Key}: {kind.Count()}");

foreach (IMailItem msg in items.Where(i => i.Kind == MailItemKind.Message))
{
    Console.WriteLine();
    Console.WriteLine($"{msg.Provenance.Folder}: {msg.Subject}");
    foreach (IMailAttachment a in msg.Attachments)
        Console.WriteLine($"  {a.FileName}  {a.Size:N0} bytes  {a.ContentType}");
}
```

```text
Format: Olm
Other: 10
Contact: 5
DistributionList: 2
Appointment: 8
Task: 5
Note: 1
Message: 7

Outlook PST/Inbox: [ubuntu-ko] 우분투 시작 안내서의 10. Tips & Trick 의 번역이 일단락되었습니다.

Outlook PST/Drafts: パーティーは何時ですか？
  017091.docx  37,440 bytes  application/vnd.openxmlformats-officedocument.wordprocessingml.document
  037025.docx  95,167 bytes  application/vnd.openxmlformats-officedocument.wordprocessingml.document
  000038.xls  71,680 bytes  application/vnd.ms-excel

Outlook PST/Drafts: What time is party?
  000046.xls  74,240 bytes  application/vnd.ms-excel
  018375.pptx  111,596 bytes  application/vnd.openxmlformats-officedocument.presentationml.presentation
  000006.doc  67,584 bytes  application/msword

Outlook PST/Drafts: באיזה שעה המסיבה?
  000100.doc  58,368 bytes  application/msword
  005227.pdf  147,455 bytes  application/pdf
  008708.pdf  148,328 bytes  application/pdf

Outlook PST/Archive: Email Test

Drafts: Draft with low priority

Drafts: Mail with followup
```

`Kind` says what each record is (`Other` here is the archive’s list of categories), and `Provenance.Folder` is its folder in the archive. Two of the attachment types weren’t stored and come from the file extension, so `ContentTypeInferred` is true for them. Messages have `From`, `ToRecipients`, `Sent`, `TextBody`, `HtmlBody` and `Attachments`, like every other format. An attachment’s `Open()` streams it from the archive.

## Calendar items and contacts

Appointments, tasks and notes have a subject and a body in the read view. For their times, attendees and recurrence, convert them: `Mail.Convert(item, ConvertFormat.Ics)` gives the `.ics` bytes and `ConvertFormat.VCard` the `.vcf` bytes of a contact, each with a loss report. To turn the whole archive into mbox files plus `.ics` and `.vcf` files, see [Convert a PST file to mbox](https://recursiveai.org/onemail/cookbook/convert-pst-to-mbox/): the same call takes an `.olm`.

## Limits

- **A preview.** 0.3.0-preview.2: the API can change before 1.0.
- **Reading only.** OneMail never writes OLM files.
- **Checked on few archives.** In the project’s words: “no Outlook 2011 layout sample; no archive with a raw MIME source, attendees or exceptions seen; a damaged zip is refused (recovery comes later)”.
- **Dates.** OLM stores times in UTC with no time zone, so `Sent` is UTC.
- **Memory.** The zip directory stays in memory, about 1 KB per entry in the archive.

Everything about the format: [OLM (Outlook for Mac)](https://recursiveai.org/onemail/docs/olm/). Everything checked, and every known gap: [Fidelity and known gaps](https://recursiveai.org/onemail/docs/compatibility/).
