Конвертация и трансформация сообщений с минимальным кодом

Преобразование email раньше означало загрузку его в MailMessage, выбирая правильный SaveOptions, подключая потоки и запоминая, какие переключатели нужны для какого формата. Aspose.Email.LowCode namespace сводит всё это к единому статическому вызову. Вы передаёте ему поток, имя файла и желаемый формат — он разбирается с остальным и пишет результат туда, куда вы укажете.5899c1__](../src/LowCodeEmailConversion) проекта, который поставляется вместе с ним.

Почему пространство имён «low-code»?

Aspose.Email.LowCode это тонкая, ориентированная на задачу оболочка над полным API email. Она существует для 80 % случаев — «Мне просто нужно преобразовать это сообщение в тот формат» — когда вы не хотите думать о моделях сообщений, MIME или вариантах сохранения.

Он построен вокруг трёх типов:

| Тип | Роль | | — | — | | Converter | Статические методы, выполняющие преобразование. | |94b97d5590014b04_IOutputHandler) — ключевая идея дизайна: одно строковое преобразование может направлять вывод на диск, в память, в базу данных, в облачное хранилище или в HTTP‑ответ просто заменой обработчика.

API Конвертера в кратце

Каждый метод является static, возвращает Task, и следует той же схеме:

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);

| Параметр | Значение | | — | — | | input | Исходное сообщение как Stream (файл, загрузка, буфер памяти…). | | nameWithExtension | Оригинальное имя файла, например "message.msg". Расширение сообщает Конвертеру исходный формат, поэтому оно должно быть точным. | | handler | The IOutputHandler который получает поток преобразованного вывода. | | outputType | (Только перегрузки во время выполнения) целевой формат как строка. |

Поддерживаемые исходные форматы — EML и MSG; поддерживаемые цели — EML, MSG, HTML, MHT и MHTML.

Примечание: эти методы асинхронные — всегда await их. Конвертер > пишет в обработчик как часть этой задачи, поэтому вывод не гарантированно будет > сброшен до возврата Task завершено.

Автоматическое определение формата преобразования

Convert читает расширение nameWithExtension, определяет исходный формат и генерирует всё, что outputType вы запрашиваете. Это самая гибкая точка входа, когда целевой формат определяется во время выполнения (например, из ввода пользователя или конфигурации).

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

Когда назначение фиксировано и известно во время компиляции, предпочтительнее явный, явно указывающий на намерение метод. ConvertToEml превращает Outlook .msg в стандартный 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

Обратное направление. Используйте ConvertToMsg когда приложение или получатель ожидает нативные элементы Outlook:

using FileStream input = File.OpenRead("message.eml");
var handler = new FolderOutputHandler(@"C:\output\msg");

await Converter.ConvertToMsg(input, "message.eml", handler);

Email → HTML

ConvertToHtml отображает сообщение как отдельный HTML‑документ — идеально для предварительного просмотра письма в браузере или встраивания его в веб‑страницу. Принимает либо .eml или .msg ввод:

using FileStream input = File.OpenRead("message.eml");
var handler = new FolderOutputHandler(@"C:\output\html");

await Converter.ConvertToHtml(input, "message.eml", handler);

Email → MHT и MHTML

Оба формата упаковывают тело сообщения и его ресурсы в один web‑архивный файл, что удобно для архивирования или обмена автономным снимком. MHTML — более богатый вариант и обычно сохраняет заголовки письма (From / To / Subject / Date) в выводе.

// 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"));

Преобразовывать только при необходимости

ConvertEmlOrMsg преобразует ввод в запрошенный формат только если он ещё не в этом формате. Укажите её на смешанную кучу .eml и .msg файлы и запрашивают "eml": .eml файлы проходят сквозь, .msg файлы преобразуются — без вашего ветвления по расширениям. Это идеально подходит для нормализации входящих в один формат.

// .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");

Пакетное преобразование папки

Поскольку каждое преобразование — это просто вызов метода, масштабирование до массовой обработки требует почти никакого дополнительного кода — перечислите файлы и переиспользуйте обработчик. Здесь каждое сообщение в папке преобразуется в 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");
}

Подсказка: FolderOutputHandler записывает в существующую папку, но не > создает её. Вызов Directory.CreateDirectory(...) сначала. Присвоение каждому источнику > собственного подпапки также предотвращает столкновения, когда несколько сообщений делят базовое имя > (два message.* файлы бы иначе оба хотели записать message.html).

Отправка вывода в место, отличное от диска

Это место, где IOutputHandler абстракцию, которая окупается. Интерфейс миниатюрный:

public interface IOutputHandler
{
    void AddOutputStream(string name, Action<Stream> writeAction);
    Task AddOutputStream(string name, Func<Stream, Task> writeActionAsync);
}

Конвертер вызывает один из этих перегрузок с именем выходного файла и писателем. Ваша реализация поставляет Stream и решает, что делать с байтами. Обработчик, который захватывает всё в памяти, выглядит так:

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();
    }
}

Сам вызов конвертации остаётся прежним — меняется только обработчик:

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...

Отсюда короткий шаг к Stream-to-облако или Stream-to-HTTP-обработчик ответа.

Выбор правильного метода

| Цель | Использование | | — | — | | Формат назначения известен во время компиляции | ConvertToEml / ConvertToMsg / ConvertToHtml / ConvertToMht / ConvertToMhtml | | Формат назначения определяется во время выполнения | Convert(..., outputType) | | Нормализовать файлы, пропуская уже целевого формата | ConvertEmlOrMsg(..., outputType) | | Записывать результаты в папку | FolderOutputHandler | | Записывать результаты в память / облако / HTTP / базу данных | Пользовательский IOutputHandler |