---
title: "Parse an EML file in C#"
url: https://recursiveai.org/onemail/cookbook/parse-eml/
description: "Parse an .eml file in C#: subject, addresses, date, decoded text and HTML bodies and attachments, from a file or bytes. Malformed mail is repaired, not thrown. Runnable code with OneMail 0.3.0-preview.2."
version: "0.3.0-preview.2"
---

# Parse an EML file in C#

Pass the bytes to `Mail.Parse`. Headers come back decoded (encoded words, charsets) and the bodies as .NET strings, with base64 and quoted-printable undone. The program below parses a public test message from Apache Tika with two attachments.

```shell
dotnet new console -o ParseEml && cd ParseEml
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-mail-module/src/test/resources/test-documents/testRFC822_multipart_attachments.eml
```

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

```csharp
using RecursiveAI.OneMail;

IMailItem msg = Mail.Parse(File.ReadAllBytes("testRFC822_multipart_attachments.eml"));

Console.WriteLine($"Subject: {msg.Subject}");
Console.WriteLine($"From:    {msg.From.FirstOrDefault()}");
Console.WriteLine($"To:      {string.Join(", ", msg.ToRecipients)}");
Console.WriteLine($"Date:    {(msg.Sent is { } d ? d.Value.ToString("u") : "none")}");

// Bodies come decoded (base64, quoted-printable, charset) as .NET strings
string? text = msg.TextBody?.ReadText();
string? html = msg.HtmlBody?.ReadText();
Console.WriteLine($"Text:    {text?.ReplaceLineEndings(" ").Trim()}");
Console.WriteLine($"HTML:    {html?.Length} characters");

foreach (IMailAttachment a in msg.Attachments)
    Console.WriteLine($"Attachment: {a.FileName}, {a.ContentType}, {a.Size} bytes");

// Malformed input is repaired, never thrown; each repair is listed
Console.WriteLine($"Defects: {msg.Defects.Count()}");
```

```text
Subject: EML 1
From:    Bugs Bunny <Bugs.Bunny@acme.com>
To:      Bugs Bunny <Bugs.Bunny@acme.com>
Date:    none
Text:    Hi,  This is test email for EML1  Thanks, Chetan
HTML:    151 characters
Attachment: Test TxtA.txt, text/plain, 33 bytes
Attachment: Test TxtB.txt, text/plain, 33 bytes
Defects: 0
```

This message has no `Date` header, so `Sent` is null. For a file that might be an `.eml`, an `.msg` or a mailbox, use `Mail.Open(path)` instead: it decides from the content.

## What you get

- **Addresses** as `MailAddress` values (`Name`, `Address`), with groups flattened: `From`, `ToRecipients`, `Cc`, `Bcc`, `ReplyTo`, `Sender`.
- **Ids and threading:** `MessageId`, `InReplyTo`, `References`, without angle brackets.
- **Bodies:** `TextBody` and `HtmlBody` are the candidates the message carries; neither is converted into the other.
- **Repairs, not exceptions.** Accessors never throw on malformed content. Every repair is a `MailDefect` with its byte offset.
- **Lossless.** Parsing doesn’t copy the bodies, and an untouched message writes back byte for byte. The lower layer, `MimeEntity.Parse`, gives the full part tree and every header.

## Limits

- **A preview.** 0.3.0-preview.2: the API can change before 1.0.
- **Ambiguous mail.** Where mail clients disagree on how to read broken input, OneMail picks one reading and marks the defect as an ambiguity. The project calls these choices “provisional until mail clients are observed”.
- **No signatures or encryption.** S/MIME and OpenPGP parts are read as parts; checking or decrypting them isn’t in this preview.

Everything checked, and every known gap: [Fidelity and known gaps](https://recursiveai.org/onemail/docs/compatibility/). The reader: [Reading and writing MIME](https://recursiveai.org/onemail/docs/mime-reading/).
