đź’ˇ Full working example available on GitHub: convert-email-and-attachments-to-pdf-dotnet

Email-to-PDF conversion is a GroupDocs.Conversion workflow for .NET that turns an Outlook message and its attachments into one or more PDF files without one attachment overwriting another or one unsupported file breaking the whole run. It replaces a manual export-and-rename routine with a few lines of code that know, for every item, where it came from and whether it converted at all.

The Old Way Was Painful

Imagine a support inbox where every case e-mail carries two or three attachments - a report here, a screenshot there, sometimes a file format nobody on the team recognizes. Nothing about that is unusual. Filing that case means opening the message, saving each attachment by hand, renaming the ones that collide because two systems both exported a file called report.csv, and hoping nothing in the set is a format your PDF viewer cannot open either. Do that fifty times a week and the “quick export” becomes the slowest part of the job, and the part most likely to be rushed, which is exactly when mistakes happen.

Doing this by hand does not just cost time - it is also where files quietly go missing. Save two attachments both named report.csv into the same folder without renaming them first, and the second save overwrites the first; nobody notices until the September numbers are nowhere to be found. A message with even one attachment in a format nobody has a converter for can stall the whole export until someone decides what to do with it.

The real cost of doing it manually: a renamed-and-overwritten attachment does not throw an error - it just silently disappears, and the case file looks complete until someone needs the data that was in it.

There’s a Better Way

GroupDocs.Conversion for .NET turns this into a few lines of code. No manual renaming is needed. Its EmailLoadOptions class controls whether the message, the attachments, or both get converted, and a SaveContext callback describes every output item well enough that two attachments named report.csv never collide and an attachment with no route to PDF never stops the rest of the run. Every call to that callback reports ItemIndex (a running count starting at 1), HierarchyLevel (0 for the message, 1 for an attachment) and SourceFileName (the original file name), which is enough context to build a collision-free output name without writing any extra bookkeeping.

Before we start, you’ll need:

  • .NET SDK 8.0 or later
  • GroupDocs.Conversion for .NET 26.10.0 (get a temporary license to remove evaluation limits)
  • An Outlook .msg or .eml message to convert

Install with one command:

dotnet add package GroupDocs.Conversion --version 26.10.0

The New Way: Converting a Message and Its Attachments

Here’s what the same task looks like with GroupDocs.Conversion. The following example converts an Outlook message and every one of its attachments into its own PDF, with file names that never collide.

Step 1 - Decide What to Convert

EmailLoadOptions.ConvertOwner and ConvertOwned independently switch the message and its attachments on or off; Depth (default 2) limits how far nested attachments are followed.

// Convert the message itself and every attachment it carries
var loadOptions = new EmailLoadOptions
{
    ConvertOwner = true,
    ConvertOwned = true,
    Depth = 2
};

Step 2 - Name Every Output From SaveContext

Pass a SaveContext callback to Converter.Convert instead of a fixed output path. The callback fires once per item, with ItemIndex unique per item even when two attachments share a file name.

using (var converter = new Converter(messagePath, (LoadContext _) => loadOptions))
{
    converter.Convert((SaveContext item) =>
    {
        // ItemIndex is 1 for the message, then counts up per attachment
        string name = $"{item.ItemIndex:D2}-{item.SourceFileName}.pdf";
        return File.Create(Path.Combine(outputFolder, name));
    }, new PdfConvertOptions());
}

Step 3 - Handle Attachments With No PDF Route

Not every attachment can become a PDF. Check SaveContext.TargetFormat against FileType.Unknown and save that one item under its own name instead of converting it.

converter.Convert((SaveContext item) =>
{
    bool passedThrough = item.TargetFormat == FileType.Unknown;
    string baseName = $"{item.ItemIndex:D2}-{item.SourceFileName}";
    string name = passedThrough
        ? baseName
        : $"{baseName}.{item.TargetFormat.Extension}";
    return File.Create(Path.Combine(outputFolder, name));
}, new PdfConvertOptions());

Point this code at a sample support e-mail with two attachments both named report.csv and one attachment in an unsupported format. Three PDFs come out: the message and both CSV reports. The unsupported file comes out too, untouched - open it next to the original and every one of its 32 bytes lines up.

How do I avoid overwriting attachments that share a file name?

A file name on its own cannot serve as a safe key for the output, because two attachments can carry the exact same one. Fold SaveContext.ItemIndex into the name together with SaveContext.SourceFileName, and two attachments named report.csv stop competing for the same slot on disk; each gets its own zero-padded prefix (02- and 03- in the sample, after the message’s 01-) and its own file, whatever name the source used.

Side-by-Side: Before vs. After

Before (Manual) After (GroupDocs.Conversion)
Time Minutes per message, by hand A few lines of code, any number of messages
Duplicate names Silently overwritten Kept separate via ItemIndex
Unsupported attachment Breaks the whole conversion (pre-26.10) Saved under its own name, run continues
Output Whatever your PDF viewer could save Structured PDFs you can file or index

The sample’s support e-mail is built from exactly that mix: two monthly CSV exports with the same name, and one capture file no converter recognizes.

Real-World Example: Support Case Archiving

A support team logs every customer case as an e-mail with one or more spreadsheet attachments, and the case-tracking system needs each attachment filed as its own searchable PDF, separate from the message. Running the message through KeepAttachmentsWithoutPdfRoute once per incoming case turns the message and its attachments into a numbered set of files, with no attachment ever overwriting another even when two reports share a name. A case e-mail with two monthly report.csv exports and one capture file in a format nobody converts comes out as four files: the message, both CSV reports as PDFs, and the capture file saved under its own name - nothing dropped, nothing merged, nothing silently overwritten.

// One call per case e-mail - no manual export, no renamed duplicates
int kept = KeepAttachmentsWithoutPdfRoute(caseMessagePath, caseOutputFolder);

What Else Can You Do with GroupDocs.Conversion for .NET?

Beyond splitting a message from its attachments, EmailLoadOptions covers more of the message itself:

  • Field visibility: show or hide the header and its From, To, Cc and Bcc lines with DisplayHeader and the related Display* options (Cc and Bcc are hidden by default).
  • Localized headers: map each EmailField to a different caption with FieldTextMap, for example translating Subject and Attachments into another language.
  • Date formatting: the Sent line follows the culture of the machine that runs the conversion, and TimeZoneOffset sets the UTC offset used for the message dates.
  • Message-only output: set ConvertOwned to false when the PDF only needs to stand in for the message, with attachment names still listed in the header for reference.

See the full EmailLoadOptions reference for every option.

Conclusion

What used to mean opening a message, saving attachments by hand, and re-checking for overwritten duplicates now takes a SaveContext callback and a few lines of code. GroupDocs.Conversion for .NET gives every output item - the message and each attachment - a name that never collides, and keeps an attachment with no PDF route instead of failing the run. The same three building blocks - ConvertOwner, ConvertOwned and the SaveContext callback - scale from a single summary PDF up to a full, collision-safe breakdown of a message and every attachment it carries, so you can start small and grow into the full workflow as your inbox demands it.

Ready to automate your e-mail-to-PDF workflow?

Additional Resources