Convert and Transform Messages with Minimal Code
Converting an email used to mean loading it into a MailMessage, picking the
right SaveOptions, wiring up streams, and remembering which format needs which
switches. The Aspose.Email.LowCode
namespace collapses all of that into a single static call. You hand it a stream,
the file name, and the format you want — it figures out the rest and writes the
result wherever you tell it to.
This article walks through every conversion the namespace supports, using the runnable LowCodeEmailConversion project that ships alongside it.
Why a “low-code” namespace?
Aspose.Email.LowCode is a thin, task-oriented surface over the full email API.
It exists for the 80% case — “I just need to turn this message into that format” —
where you don’t want to think about message models, MIME, or persistence options.
It is built around three types:
| Type | Role |
|---|---|
Converter |
Static methods that perform the conversion. |
IOutputHandler |
A contract that decides where the converted bytes go. |
FolderOutputHandler |
A ready-made IOutputHandler that writes to a folder. |
The split between what to convert (Converter) and where it lands
(IOutputHandler) is the key design idea: the same one-line conversion can target
disk, memory, a database, a cloud bucket, or an HTTP response simply by swapping
the handler.
The Converter API at a glance
Every method is static, returns a Task, and follows the same shape:
Task Converter.ConvertToEml (Stream input, string nameWithExtension, IOutputHandler handler);
Task Converter.ConvertToMsg (Stream input, string nameWithExtension, IOutputHandler handler);
Task Converter.ConvertToHtml (Stream input, string nameWithExtension, IOutputHandler handler);
Task Converter.ConvertToMht (Stream input, string nameWithExtension, IOutputHandler handler);
Task Converter.ConvertToMhtml(Stream input, string nameWithExtension, IOutputHandler handler);
// Format chosen at run time via the outputType string ("eml", "msg", "html", ...):
Task Converter.Convert (Stream input, string nameWithExtension, IOutputHandler handler, string outputType);
Task Converter.ConvertEmlOrMsg(Stream input, string nameWithExtension, IOutputHandler handler, string outputType);
| Parameter | Meaning |
|---|---|
input |
The source message as a Stream (a file, an upload, a memory buffer…). |
nameWithExtension |
The original file name, e.g. "message.msg". The extension tells the Converter the source format, so it must be accurate. |
handler |
The IOutputHandler that receives the converted output stream. |
outputType |
(Run-time overloads only) the target format as a string. |
Supported source formats are EML and MSG; supported targets are EML, MSG, HTML, MHT, and MHTML.
Note: these methods are asynchronous — always
awaitthem. The Converter writes to the handler as part of that task, so the output isn’t guaranteed to be flushed until the returnedTaskcompletes.
Auto-detecting conversion
Convert reads the extension of nameWithExtension, detects the source format,
and produces whatever outputType you ask for. This is the most flexible entry
point when the target format is decided at run time (for example, from user input
or configuration).
using Aspose.Email.LowCode;
using FileStream input = File.OpenRead("message.msg");
var handler = new FolderOutputHandler(@"C:\output\auto");
await Converter.Convert(input, "message.msg", handler, "eml");
MSG → EML
When the destination is fixed and known at compile time, prefer the explicit,
intent-revealing method. ConvertToEml turns an Outlook .msg into a standard
RFC 822 .eml:
using FileStream input = File.OpenRead("message.msg");
var handler = new FolderOutputHandler(@"C:\output\eml");
await Converter.ConvertToEml(input, "message.msg", handler);
EML → MSG
The reverse direction. Use ConvertToMsg when an application or recipient expects
native Outlook items:
using FileStream input = File.OpenRead("message.eml");
var handler = new FolderOutputHandler(@"C:\output\msg");
await Converter.ConvertToMsg(input, "message.eml", handler);
Email → HTML
ConvertToHtml renders a message as a standalone HTML document — ideal for
previewing email in a browser or embedding it in a web page. It accepts either
.eml or .msg input:
using FileStream input = File.OpenRead("message.eml");
var handler = new FolderOutputHandler(@"C:\output\html");
await Converter.ConvertToHtml(input, "message.eml", handler);
Email → MHT and MHTML
Both formats bundle the message body and its resources into a single web-archive file, which is convenient for archiving or sharing a self-contained snapshot. MHTML is the richer variant and typically preserves the email headers (From / To / Subject / Date) in the rendered output.
// MHT
using (FileStream input = File.OpenRead("message.msg"))
await Converter.ConvertToMht(input, "message.msg", new FolderOutputHandler(@"C:\output\mht"));
// MHTML
using (FileStream input = File.OpenRead("message.eml"))
await Converter.ConvertToMhtml(input, "message.eml", new FolderOutputHandler(@"C:\output\mhtml"));
Convert only when needed
ConvertEmlOrMsg converts the input to the requested format only if it isn’t
already in that format. Point it at a mixed pile of .eml and .msg files and
ask for "eml": the .eml files pass through, the .msg files are converted —
without you branching on the extension yourself. This makes it perfect for
normalizing an inbox to one format.
// .eml input requesting "eml" -> passes through
using (FileStream input = File.OpenRead("message.eml"))
await Converter.ConvertEmlOrMsg(input, "message.eml", handler, "eml");
// .msg input requesting "eml" -> converted
using (FileStream input = File.OpenRead("message.msg"))
await Converter.ConvertEmlOrMsg(input, "message.msg", handler, "eml");
Batch-converting a folder
Because each conversion is just a method call, scaling to bulk work needs almost no extra code — enumerate the files and reuse the handler. Here every message in a folder is rendered to HTML:
foreach (string path in Directory.EnumerateFiles(inputDir)
.Where(f => f.EndsWith(".eml") || f.EndsWith(".msg")))
{
var handler = new FolderOutputHandler(Path.Combine(outputDir, Path.GetFileNameWithoutExtension(path)));
using FileStream input = File.OpenRead(path);
await Converter.Convert(input, Path.GetFileName(path), handler, "html");
}
Tip:
FolderOutputHandlerwrites into an existing folder but does not create it. CallDirectory.CreateDirectory(...)first. Giving each source its own subfolder also prevents collisions when several messages share a base name (twomessage.*files would otherwise both want to writemessage.html).
Sending output somewhere other than disk
This is where the IOutputHandler abstraction pays off. The interface is tiny:
public interface IOutputHandler
{
void AddOutputStream(string name, Action<Stream> writeAction);
Task AddOutputStream(string name, Func<Stream, Task> writeActionAsync);
}
The Converter calls one of these overloads with the output file name and a writer.
Your implementation supplies a Stream and decides what to do with the bytes. A
handler that captures everything in memory looks like this:
public sealed class InMemoryOutputHandler : IOutputHandler
{
private readonly Dictionary<string, byte[]> _files = new(StringComparer.OrdinalIgnoreCase);
public IReadOnlyDictionary<string, byte[]> Files => _files;
public void AddOutputStream(string name, Action<Stream> writeAction)
{
using var buffer = new MemoryStream();
writeAction(buffer);
_files[name] = buffer.ToArray();
}
public async Task AddOutputStream(string name, Func<Stream, Task> writeActionAsync)
{
using var buffer = new MemoryStream();
await writeActionAsync(buffer);
_files[name] = buffer.ToArray();
}
}
The conversion call itself is unchanged — only the handler differs:
var handler = new InMemoryOutputHandler();
using (FileStream input = File.OpenRead("message.msg"))
await Converter.ConvertToHtml(input, "message.msg", handler);
byte[] html = handler.Files["message.html"]; // stream it, store it, return it...
From here it’s a short step to a Stream-to-cloud or Stream-to-HTTP-response
handler.
Choosing the right method
| Goal | Use |
|---|---|
| Target format known at compile time | ConvertToEml / ConvertToMsg / ConvertToHtml / ConvertToMht / ConvertToMhtml |
| Target format decided at run time | Convert(..., outputType) |
| Normalize files, skipping ones already in the target format | ConvertEmlOrMsg(..., outputType) |
| Write results to a folder | FolderOutputHandler |
| Write results to memory / cloud / HTTP / database | A custom IOutputHandler |