Document Automation Made Simple

Convert EML and MSG Emails to PDF in C#, Python, and Node.js

Convert emails to PDF as part of a pipeline: headers rendered, attachments converted and merged into one document, and optional PDF/A output for regulated archives. Working C#, Python, and Node.js code with real input and output files to download.

Tomas, CEO

Email is business correspondence, and regulators treat it that way: finance, legal, and healthcare teams must retain messages for years in a format nobody can quietly edit. The practical answer is converting emails to PDF as part of a pipeline - a helpdesk export, a CRM archive, an e-discovery job - not one message at a time by hand.

This guide converts EML and MSG emails to PDF programmatically: headers rendered, attachments converted and merged into the same document, and the result optionally emitted as archival PDF/A. Working code in C#, Python, and Node.js, with real input and output files to download at the end.

Why Not Just Print to PDF from Outlook?

Outlook's built-in print-to-PDF works for one message, but it has two problems that make it useless in a pipeline. It drops the attachments - the printout references them without their content - and it needs a human at the keyboard. An archiving or e-discovery workflow needs both fixed: every attachment preserved, and zero clicks per message.

EML and MSG: Same Job, Two Formats

  • EML is the open plain-text format (RFC 5322 with MIME parts). Most mail systems, exports, and mail-fetching libraries produce it.
  • MSG is Outlook's binary format - what you get when you drag a message out of Outlook to a folder.

The EML to PDF and MSG to PDF converters accept either extension with identical parameters, so one integration covers both.

Convert an Email to PDF

One request. By default the output opens with a mail-client-style header block - From, Sent, To, Cc, Subject - followed by the rendered body:

curl -X POST https://v2.convertapi.com/convert/eml/to/pdf \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -F "File=@shipment-notification.eml" \
  -F "StoreFile=true"

The header block comes from ConvertHeader (default true) - turn it off if you only want the message body. Page geometry is controlled with PageSize, PageOrientation, and margin parameters when your archive has layout requirements.

Include the Attachments in One PDF

This is the part manual methods cannot do. Set ConvertAttachments=true and every attachment is converted and appended to the email PDF - Merge defaults to true, so everything arrives as a single document:

curl -X POST https://v2.convertapi.com/convert/eml/to/pdf \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -F "File=@shipment-notification.eml" \
  -F "ConvertAttachments=true" \
  -F "StoreFile=true"

In our test run below, an email with a PDF form and a JPG attached went from a 1-page body-only PDF to a single 3-page document: the message first, then each attachment as its own pages. Two related switches:

  • Merge=false - keep the body and each converted attachment as separate output files
  • IgnoreAttachmentErrors=true - skip attachments the converter cannot process instead of failing the whole message, which is what you want when batch-processing years of mixed correspondence

Batch Convert a Mailbox Export

Point a loop at the folder your mail system exported. C# with the official .NET SDK:

using ConvertApiDotNet;

var convertApi = new ConvertApi("YOUR_API_TOKEN");

foreach (var emlFile in Directory.EnumerateFiles(@"C:\mailbox-export", "*.eml", SearchOption.AllDirectories))
{
    var result = await convertApi.ConvertAsync("eml", "pdf",
        new ConvertApiFileParam(emlFile),
        new ConvertApiParam("ConvertAttachments", "true"),
        new ConvertApiParam("IgnoreAttachmentErrors", "true")
    );
    await result.SaveFilesAsync(Path.GetDirectoryName(emlFile));
}

Python:

import convertapi
from pathlib import Path

convertapi.api_credentials = 'YOUR_API_TOKEN'

for eml in Path('/mailbox-export').rglob('*.eml'):
    convertapi.convert('pdf', {
        'File': str(eml),
        'ConvertAttachments': 'true',
        'IgnoreAttachmentErrors': 'true'
    }, from_format = 'eml').save_files(str(eml.parent))

Node.js:

const convertapi = require('convertapi')('YOUR_API_TOKEN');

const result = await convertapi.convert('pdf', {
    File: './mailbox-export/shipment-notification.eml',
    ConvertAttachments: 'true',
    IgnoreAttachmentErrors: 'true'
}, 'eml');

await result.saveFiles('./archive');

For .msg exports, change the source format to msg - everything else stays the same. Each conversion is stateless, so batches parallelize with your language's standard concurrency tools.

Archive Straight to PDF/A

For regulated retention, add Pdfa=true and the converter emits PDF/A-1b directly - no second conversion step:

curl -X POST https://v2.convertapi.com/convert/eml/to/pdf \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -F "File=@shipment-notification.eml" \
  -F "ConvertAttachments=true" \
  -F "Pdfa=true" \
  -F "StoreFile=true"

The sample file below was produced exactly this way and checked with the PDF/A validation endpoint: verdict Compliant, PDF/A-1B. If your archive requires a specific newer PDF/A version, chain the output through the PDF to PDF/A converter instead - our PDF/A for e-invoicing guide covers choosing a version, and the validation guide covers proving compliance.

Try It Yourself: Download the Sample Files

One fictional dispatch email with two attachments (a PDF form and a JPG), run through the exact calls above:

Frequently Asked Questions

What is the difference between EML and MSG?

EML is the open, plain-text MIME format used by most mail systems. MSG is Outlook's proprietary binary container. Both hold the same message data, and both convert with the same parameters here.

How do I get emails out of Outlook for the API?

Dragging a message from Outlook to a folder produces a .msg file, and Save As offers both formats. At pipeline scale, mailbox exports and mail-retrieval libraries (Graph, EWS, IMAP tooling) produce .eml or .msg files the same loop can process.

What happens to attachments the converter cannot render?

By default an unconvertible attachment fails the conversion, so you notice. Set IgnoreAttachmentErrors=true to skip such attachments and still get the message and everything else - the right trade-off for large mixed archives.

Can I keep the attachments as separate PDFs?

Yes. Keep ConvertAttachments=true but set Merge=false, and the response contains the body PDF plus each converted attachment as its own file.

Does this need Outlook or a mail client installed?

No. Conversion runs in the cloud over REST, so it works identically from a Windows server, a Linux container, or a CI pipeline.

Conclusion

Email retention is a pipeline problem, and the whole pipeline is three parameters: ConvertAttachments=true so nothing is lost, IgnoreAttachmentErrors=true so old archives do not jam, and Pdfa=true when the destination is a regulated archive. Try it with your own exports on the EML to PDF converter page - the interactive demo generates working code for your language.


Related converters

Ready to Streamline Your File Conversions?