Converts Outlook .msg email files to PDF. No Outlook/COM required; runs on Windows, macOS and Linux.
Pipeline: MsgReader extracts the message as HTML (an Outlook-print-style header block, the body — HTML, RTF or plain text — and inline images embedded as data URIs), then PuppeteerSharp renders it to PDF with headless Chromium.
using Tideway.MsgToPdf;
await using var converter = new MsgToPdfConverter();
// bytes → bytes
byte[] pdf = await converter.ConvertAsync(msgBytes);
// or file → file
await converter.ConvertFileAsync("mail.msg", "mail.pdf");The converter keeps one Chromium instance alive across calls — reuse a single instance for batch conversions and dispose it when done.
var converter = new MsgToPdfConverter(new MsgToPdfOptions
{
IncludeMessageHeader = true, // From/Sent/To/Cc/Subject/Attachments block (default true)
NeutralizeOutlookPageBreaks = true, // stop Outlook's WordSection CSS forcing a blank first page (default true)
AppendPdfAttachments = false, // merge the message's PDF attachments after the body (default false)
OnWarning = w => log.Warn(w), // non-fatal issues, e.g. an encrypted attachment skipped
PaperFormat = PaperFormat.A4, // default A4
Landscape = false,
Margins = new MarginOptions { Top = "15mm", Bottom = "15mm", Left = "12mm", Right = "12mm" },
PageFooterTemplate = null, // Chromium print footer HTML (pageNumber/totalPages spans)
ChromiumExecutablePath = null, // null → BrowserFetcher downloads Chromium on first use
ChromiumArgs = new[] { "--no-sandbox" },
});With AppendPdfAttachments = true, the message's non-inline .pdf attachments are merged (in attachment order) after the rendered body via Tideway.PdfTools, producing one PDF — e.g. an email plus its report appendices. Password-protected or unparseable attachments are skipped and reported through OnWarning. The native libqpdf library is required only when this option is enabled (see the PdfTools README for per-platform setup).
string html = MsgToPdfConverter.RenderHtml(msgStream); // self-contained HTML document
byte[] pdf = await converter.HtmlToPdfAsync(html); // also usable for generic HTML → PDFBy default the first conversion downloads a private Chromium build (~150 MB, cached in the user profile). In containers, install Chromium in the image instead and point the converter at it:
RUN apt-get update && apt-get install -y chromium && rm -rf /var/lib/apt/lists/*new MsgToPdfOptions
{
ChromiumExecutablePath = "/usr/bin/chromium",
ChromiumArgs = new[] { "--no-sandbox" }, // needed when running as root
}- RTF-only bodies are converted with RtfPipe; Outlook's usual RTF-encapsulated HTML is handled by MsgReader itself.
- External images (
http(s)references) are fetched during rendering when reachable; unreachable ones render as broken-image icons. cid:inline images are embedded as base64 data URIs, so the intermediate HTML is fully self-contained.