---
title: "Create an EML file in C#"
url: https://recursiveai.org/onemail/cookbook/create-eml/
description: "Create an .eml file in C#: headers, a plain text and HTML body and an attachment, written as standard MIME any mail program opens. Runnable code with OneMail 0.3.0-preview.2."
version: "0.3.0-preview.2"
---

# Create an EML file in C#

Build the message from `MimeMultipart` and `MimePart`, add the headers, and call `WriteTo`. The program below writes an email with plain text and HTML bodies and a CSV attachment, then reads it back.

```shell
dotnet new console -o CreateEml && cd CreateEml
dotnet add package RecursiveAI.OneMail --version 0.3.0-preview.2
```

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

```csharp
using System.Globalization;
using System.Text;
using RecursiveAI.OneMail;
using RecursiveAI.OneMail.Mime;
using RecursiveAI.OneMail.Mime.Transfer;
using RecursiveAI.OneMail.Text;

var message = new MimeMultipart("mixed");
// Address headers are written as given: encode a non-ASCII display name yourself
message.Headers.Add("From", $"{Rfc2047.Encode("Zoë Martín")} <zoe@example.com>");
message.Headers.Add("To", "Sam Lee <sam@example.org>");
// Free text such as the subject is encoded for you
message.Headers.Add("Subject", "Q3 report – final");
string date = DateTime.UtcNow.ToString("ddd, dd MMM yyyy HH:mm:ss +0000",
    CultureInfo.InvariantCulture);
message.Headers.Add("Date", date);
message.Headers.Add("Message-ID", $"<{Guid.NewGuid():N}@example.com>");
message.Headers.Add("MIME-Version", "1.0");

// Plain text and HTML versions of the same body
var body = new MimeMultipart("alternative");
var text = new MimePart("text/plain; charset=utf-8");
text.SetDecodedContent(Utf8("Hi Sam,\r\n\r\nThe report is attached.\r\n"),
    ContentTransferEncoding.QuotedPrintable);
var html = new MimePart("text/html; charset=utf-8");
html.SetDecodedContent(Utf8("<p>Hi Sam,</p><p>The report is attached.</p>"),
    ContentTransferEncoding.QuotedPrintable);
body.Add(text);
body.Add(html);
message.Add(body);

// An attachment, base64-encoded (the default)
var csv = new MimePart("text/csv; name=\"q3.csv\"");
csv.Headers.Add("Content-Disposition", "attachment; filename=\"q3.csv\"");
csv.SetDecodedContent(Utf8("month,revenue\r\nJul,1200\r\nAug,1350\r\n"));
message.Add(csv);

using (FileStream file = File.Create("report.eml"))
    message.WriteTo(file);
Console.WriteLine($"report.eml: {new FileInfo("report.eml").Length:N0} bytes");

// Read it back
IMailItem check = Mail.Parse(File.ReadAllBytes("report.eml"));
Console.WriteLine($"{check.From[0]} -> {check.ToRecipients[0]}: {check.Subject}");
string plain = check.TextBody!.ReadText();
Console.WriteLine($"text: {plain.ReplaceLineEndings(" ").Trim()}");
IMailAttachment attached = check.Attachments[0];
Console.WriteLine($"attachment: {attached.FileName}, {attached.Size} bytes");
Console.WriteLine($"defects: {check.Defects.Count()}");

static byte[] Utf8(string s) => Encoding.UTF8.GetBytes(s);
```

```text
report.eml: 1,019 bytes
Zoë Martín <zoe@example.com> -> Sam Lee <sam@example.org>: Q3 report – final
text: Hi Sam,  The report is attached.
attachment: q3.csv, 35 bytes
defects: 0
```

`report.eml` opens in any mail program; Python’s `email` package also reads it with no defects. A boundary for each multipart is generated for you, and lines end in CRLF as MIME requires.

## How the parts fit

- `multipart/mixed` holds the body and the attachments.
- `multipart/alternative` inside it holds versions of the same body, plainest first. Mail programs show the last one they support.
- `SetDecodedContent` takes the raw bytes and encodes them: base64 by default, or quoted-printable for text people may read in the source.
- Header values must be one line. A line break throws, so user input can’t inject headers.

## Limits

- **A preview.** 0.3.0-preview.2: the API can change before 1.0.
- **A low-level API.** There is no message builder yet. You set each header yourself, and you encode non-ASCII display names in address headers with `Rfc2047.Encode`, as above. Subjects and other free text are encoded for you.
- **No sending.** SMTP isn’t in this preview. The file is ready to hand to any SMTP client.
- **No Outlook formats.** OneMail can’t write MSG or PST files yet.

Reading messages back: [Parse an EML file](https://recursiveai.org/onemail/cookbook/parse-eml/). The writer: [Reading and writing MIME](https://recursiveai.org/onemail/docs/mime-reading/).
