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 await them. The Converter writes to the handler as part of that task, so the output isn’t guaranteed to be flushed until the returned Task completes.

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: FolderOutputHandler writes into an existing folder but does not create it. Call Directory.CreateDirectory(...) first. Giving each source its own subfolder also prevents collisions when several messages share a base name (two message.* files would otherwise both want to write message.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