---
title: "Convert a PST file to EML in C#"
url: https://recursiveai.org/onemail/cookbook/convert-pst-to-eml/
description: "Convert a PST or OST file to EML files in C#: one .eml per message, in a folder per PST folder, with attachments and a loss report. Runnable code with OneMail 0.3.0-preview.2."
version: "0.3.0-preview.2"
---

# Convert a PST file to EML in C#

Walk the store’s folders with `PstStore`, convert each message with `MapiToMimeConverter`, and write one `.eml` per message. The program below exports Apache Tika’s public test store.

```shell
dotnet new console -o PstToEml && cd PstToEml
dotnet add package RecursiveAI.OneMail --version 0.3.0-preview.2
curl -LO https://raw.githubusercontent.com/apache/tika/4.2.0/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/resources/test-documents/testPST.pst
```

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

```csharp
using RecursiveAI.OneMail.Conversion.OxcMail;
using RecursiveAI.OneMail.Pst.Messaging;

if (!PstStore.TryOpen("testPST.pst", out PstStore? store, out var defects))
{
    Console.WriteLine($"Not a PST: {string.Join(", ", defects)}");
    return;
}

var converter = new MapiToMimeConverter();
int written = 0, unresolved = 0;
using (store)
{
    foreach (PstFolder folder in store!.EnumerateFolders())
    {
        foreach (PstMessage message in folder.EnumerateMessages())
        {
            // One folder per PST folder, one .eml per message
            string dir = Path.Combine(["eml", .. folder.Path.Split('/').Select(Safe)]);
            Directory.CreateDirectory(dir);
            var result = converter.Convert(message);
            string file = Path.Combine(dir, $"{++written:D5}.eml");
            using (FileStream eml = File.Create(file))
                result.Value.WriteTo(eml);

            // Exchange-only senders with no SMTP address are left out and reported
            unresolved += result.Report.Count(e => e.Code == "AddressUnresolved");
            Console.WriteLine($"{file}  {new FileInfo(file).Length,7:N0} bytes");
        }
    }
}
Console.WriteLine($"{written} messages, {unresolved} unresolved addresses");

static string Safe(string name) =>
    string.Concat(name.Select(c =>
        Path.GetInvalidFileNameChars().Contains(c) ? '_' : c));
```

```text
eml/Début du fichier de données Outlook/00001.eml    5,899 bytes
eml/Début du fichier de données Outlook/00002.eml    9,006 bytes
eml/Début du fichier de données Outlook/00003.eml    4,493 bytes
eml/Début du fichier de données Outlook/00004.eml    4,745 bytes
eml/Début du fichier de données Outlook/00005.eml    5,277 bytes
eml/Début du fichier de données Outlook/00006.eml   18,368 bytes
eml/Début du fichier de données Outlook/00007.eml   21,015 bytes
7 messages, 2 unresolved addresses
```

Every file opens in Python’s `email` package and with the `onemail` tool. Messages that arrived over the Internet keep the headers they arrived with. The forwarded message in `00007.eml` is still attached as a message. Messages are read one at a time, so a large store doesn’t have to fit in memory.

## The two unresolved addresses

Message 7 was sent inside an Exchange organization. Its sender has only an Exchange (X.500) address, with no SMTP form in the store, so the `.eml` has no `From` header. The report lists it as `AddressUnresolved`. The project reports the same gap on its own test set: 30 such entries over 70 items.

## Limits

- **A preview.** 0.3.0-preview.2: the API can change before 1.0.
- **Exchange addresses.** There is no directory lookup: “EX addresses with no SMTP form in the item are left out and reported”.
- **Bcc** isn’t written by default (`OxcMailExportOptions.IncludeBcc`).
- **Mail only.** This loop writes messages. To write appointments and tasks as `.ics` files too, convert the whole store with `Mail.ConvertAsync`, as in [Convert a PST file to mbox](https://recursiveai.org/onemail/cookbook/convert-pst-to-mbox/).
- **Search folders and hidden items** are skipped, so no message is written twice.

To write one mbox instead of many files, see [Convert a PST file to mbox](https://recursiveai.org/onemail/cookbook/convert-pst-to-mbox/). One message at a time: [Convert MSG to EML](https://recursiveai.org/onemail/cookbook/convert-msg-to-eml/). Every rule: [MAPI and MIME conversion](https://recursiveai.org/onemail/docs/conversion/).
