@sanket8753
GroupDocs.Conversion fully supports all three scenarios you described. The key is using the LoadContext parameter in the Converter constructor — it provides access to the original attachment stream (SourceStream) for every document being processed, including embedded attachments.
Case 1: MSG / EML — Extract original attachments + convert to PDF
string source = "input.msg"; // or .eml
int fileIndex = 0;
using (var converter = new Converter(source, (LoadContext ctx) =>
{
// ctx.SourceStream contains the ORIGINAL attachment data
// ctx.HierarchyLevel = 0 for the main email, > 0 for attachments
if (ctx.HierarchyLevel > 0)
{
// Save the original attachment in its native format
ctx.SourceStream.Position = 0;
using (var file = File.Create($"originals/{ctx.SourceFileName}"))
{
ctx.SourceStream.CopyTo(file);
}
ctx.SourceStream.Position = 0;
return null; // use default load options for the attachment
}
return new EmailLoadOptions
{
ConvertOwner = true, // convert the email body
ConvertOwned = true // convert attachments
};
}))
{
converter.Convert(
(SaveContext c) => File.Create($"converted-{++fileIndex}.pdf"),
c => new PdfConvertOptions());
}
If you only want the attachments (skip the email body), set ConvertOwner = false:
return new EmailLoadOptions
{
ConvertOwner = false, // skip email body
ConvertOwned = true // convert attachments only
};
Case 2: DOCX / XLS / PPT — Extract embedded OLE objects + convert to PDF
string source = "input.docx"; // or .xlsx, .pptx
int fileIndex = 0;
using (var converter = new Converter(source, (LoadContext ctx) =>
{
if (ctx.HierarchyLevel > 0)
{
ctx.SourceStream.Position = 0;
using (var file = File.Create($"originals/{ctx.SourceFileName}"))
{
ctx.SourceStream.CopyTo(file);
}
ctx.SourceStream.Position = 0;
return null; // use default load options for the embedded object
}
return new WordProcessingLoadOptions // or SpreadsheetLoadOptions, PresentationLoadOptions
{
ConvertOwner = true,
ConvertOwned = true
};
}))
{
converter.Convert(
(SaveContext c) => File.Create($"converted-{++fileIndex}.pdf"),
c => new PdfConvertOptions());
}
Use the matching load options for your source format:
.docx / .doc / .rtf / .dot / .dotx → WordProcessingLoadOptions
.xls / .xlsx → SpreadsheetLoadOptions
.ppt / .pptx → PresentationLoadOptions
Case 3: PDF — Extract embedded file attachments + convert to PDF
string source = "input.pdf";
int fileIndex = 0;
using (var converter = new Converter(source, (LoadContext ctx) =>
{
if (ctx.HierarchyLevel > 0)
{
ctx.SourceStream.Position = 0;
using (var file = File.Create($"originals/{ctx.SourceFileName}"))
{
ctx.SourceStream.CopyTo(file);
}
ctx.SourceStream.Position = 0;
return null; // use default load options for the embedded file
}
return new PdfLoadOptions
{
ConvertOwner = true,
ConvertOwned = true
};
}))
{
converter.Convert(
(SaveContext c) => File.Create($"converted-{++fileIndex}.pdf"),
c => new PdfConvertOptions());
}
How it works
The LoadContext parameter in the constructor callback is called for every document being processed — the main document and each embedded attachment/OLE object. It provides:
| Property |
Description |
SourceFileName |
The name of the file being loaded (e.g., report.docx, image.png) |
SourceFormat |
The detected file format |
SourceStream |
The original stream of the document/attachment in its native format |
HierarchyLevel |
0 for the main document, 1 for direct attachments, 2+ for nested |
Return the appropriate LoadOptions (with ConvertOwner/ConvertOwned flags) only for the root document (HierarchyLevel == 0). For attachments, return null to let GroupDocs.Conversion auto-detect the correct options based on the file format.
The ConvertOwner / ConvertOwned flags control what gets converted:
| ConvertOwner |
ConvertOwned |
Result |
true |
true |
Convert everything (main doc + all attachments) |
true |
false |
Convert main document only |
false |
true |
Convert attachments only |
This gives you full control: extract originals via LoadContext.SourceStream, and convert to PDF in the same pass.
Useful documentation links
The ConvertOwner/ConvertOwned properties are available on WordProcessingLoadOptions, SpreadsheetLoadOptions, PresentationLoadOptions, and PdfLoadOptions via the IDocumentsContainerLoadOptions interface.