Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions Docs/Platform-Architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,58 @@ The recommended shape is:

This avoids duplicating logic and gives one headless contract for the ecosystem.

## Skills

Skills should be treated as reusable agent guidance, not as a replacement for shared Mailozaurr capabilities.

The preferred split is:

- `MCP` exposes executable tools over shared Mailozaurr services
- `skills` teach agents how to use those tools safely and consistently

Examples of skill responsibilities:

- when to prefer drafts over immediate send
- when to use queue-first sending
- how to summarize before delete/move
- how to select compact versus rich read surfaces

Examples of non-skill responsibilities:

- mailbox search logic
- message retrieval
- attachment saving
- queue processing
- provider auth/session behavior

Those belong in shared code, not only in prompt guidance.

## HTML Body Projection Roadmap

Mailozaurr should eventually support reusable HTML body projection for non-PowerShell headless surfaces, especially CLI and MCP.

The recommended split is:

- keep raw provider body retrieval in `Mailozaurr`
- place body projection abstractions and policies in `Mailozaurr.Application`
- keep PowerShell dependency-light by default
- document PowerShell recipes for richer HTML handling instead of forcing heavy dependencies into the module

### Recommended integration model

- `CLI` / `MCP`
Add optional shared HTML-to-Markdown projection via `OfficeIMO.Markdown.Html`
- `PowerShell`
Keep raw body access in the Mailozaurr module
Show examples using `PSWriteOffice` / `OfficeIMO.Markdown.Html` for Markdown projection
Show examples using `PSParseHTML` for DOM-style extraction and structured data recovery

### Placement rule

If HTML-to-Markdown projection becomes reusable across CLI, MCP, GUI, or plain C# consumers, the abstraction belongs in shared Mailozaurr layers.

If a PowerShell workflow only demonstrates how to pipe a retrieved HTML body into another module, that belongs in documentation/examples, not in the core Mailozaurr PowerShell adapter by default.

## Migration Guidance

Not every existing area must be refactored immediately.
Expand Down
13 changes: 13 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,19 @@ Additional dependency:

- [Platform Architecture](Docs/Platform-Architecture.md) - layering and reuse rules for future library, PowerShell, CLI, MCP, and GUI work

## Additional surfaces

Mailozaurr is no longer only a library and PowerShell module. The repository now also contains shared application-layer work and headless surfaces for broader automation scenarios:

- `.NET library` for direct application and service integration
- `PowerShell module` for administrators and automation users
- `mailozaurr` executable for cross-platform CLI workflows
- `mailozaurr mcp serve` for MCP-based integrations

CLI and MCP are intended to sit on top of shared Mailozaurr services instead of duplicating mailbox, draft, queue, send, and message-action behavior independently.

If you want the placement rules and longer-term cross-surface direction, see [Platform Architecture](Docs/Platform-Architecture.md).

This started with a single goal to replace `Send-MailMessage` which is deprecated/obsolete with something more modern, but since MailKit and MimeKit have lots of options why not build on that?

## Support This Project
Expand Down
45 changes: 45 additions & 0 deletions Sources/Mailozaurr.Application/CommonMessageActionsPreview.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
namespace Mailozaurr.Application;

/// <summary>
/// Aggregate dry-run result comparing common mailbox actions for the same message selection.
/// </summary>
public sealed class CommonMessageActionsPreview : OperationResult {
/// <summary>Owning profile identifier.</summary>
public string ProfileId { get; set; } = string.Empty;

/// <summary>Owning mailbox identifier when relevant.</summary>
public string? MailboxId { get; set; }

/// <summary>Optional source folder identifier.</summary>
public string? FolderId { get; set; }

/// <summary>Optional custom destination folder value included in the comparison.</summary>
public string? RequestedDestinationFolderId { get; set; }

/// <summary>Total raw message identifiers provided in the request.</summary>
public int RequestedCount { get; set; }

/// <summary>Total unique, non-empty message identifiers after normalization.</summary>
public int UniqueMessageCount { get; set; }

/// <summary>Total duplicate or empty message identifiers removed during normalization.</summary>
public int DuplicateOrEmptyCount { get; set; }

/// <summary>The normalized unique message identifiers that would be acted on.</summary>
public List<string> MessageIds { get; set; } = new();

/// <summary>Total number of action previews included in the bundle.</summary>
public int IncludedActionCount { get; set; }

/// <summary>Total number of action previews that are supported and ready.</summary>
public int SucceededActionCount { get; set; }

/// <summary>Total number of action previews that are unsupported or otherwise blocked.</summary>
public int FailedActionCount { get; set; }

/// <summary>Top-level warnings detected during preview normalization.</summary>
public List<string> Warnings { get; set; } = new();

/// <summary>Included action previews such as read-state, flagged-state, archive, trash, move, and delete.</summary>
public List<MessageActionPreviewItem> Actions { get; set; } = new();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace Mailozaurr.Application;

/// <summary>
/// Request for previewing a common bundle of message actions side by side.
/// </summary>
public sealed class CommonMessageActionsPreviewRequest {
/// <summary>Profile identifier.</summary>
public string ProfileId { get; set; } = string.Empty;

/// <summary>Optional mailbox identifier for multi-mailbox providers.</summary>
public string? MailboxId { get; set; }

/// <summary>Optional source folder identifier or folder path.</summary>
public string? FolderId { get; set; }

/// <summary>Provider-specific message identifiers to preview.</summary>
public List<string> MessageIds { get; set; } = new();

/// <summary>Optional custom destination folder identifier or alias to include as a generic move preview.</summary>
public string? DestinationFolderId { get; set; }
}
33 changes: 33 additions & 0 deletions Sources/Mailozaurr.Application/DeleteMessagesPreview.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
namespace Mailozaurr.Application;

/// <summary>
/// Aggregate dry-run result for a planned message delete.
/// </summary>
public sealed class DeleteMessagesPreview : OperationResult {
/// <summary>Owning profile identifier.</summary>
public string ProfileId { get; set; } = string.Empty;

/// <summary>Owning mailbox identifier when relevant.</summary>
public string? MailboxId { get; set; }

/// <summary>Optional source folder identifier.</summary>
public string? FolderId { get; set; }

/// <summary>Total raw message identifiers provided in the request.</summary>
public int RequestedCount { get; set; }

/// <summary>Total unique, non-empty message identifiers after normalization.</summary>
public int UniqueMessageCount { get; set; }

/// <summary>Total duplicate or empty message identifiers removed during normalization.</summary>
public int DuplicateOrEmptyCount { get; set; }

/// <summary>The normalized unique message identifiers that would be acted on.</summary>
public List<string> MessageIds { get; set; } = new();

/// <summary>Optional confirmation token that can be supplied when executing the delete.</summary>
public string? ConfirmationToken { get; set; }

/// <summary>Warnings detected during preview.</summary>
public List<string> Warnings { get; set; } = new();
}
18 changes: 18 additions & 0 deletions Sources/Mailozaurr.Application/DeleteMessagesPreviewRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace Mailozaurr.Application;

/// <summary>
/// Request for previewing a message delete without executing it.
/// </summary>
public sealed class DeleteMessagesPreviewRequest {
/// <summary>Profile identifier.</summary>
public string ProfileId { get; set; } = string.Empty;

/// <summary>Optional mailbox identifier for multi-mailbox providers.</summary>
public string? MailboxId { get; set; }

/// <summary>Optional folder identifier or folder path.</summary>
public string? FolderId { get; set; }

/// <summary>Provider-specific message identifiers to preview.</summary>
public List<string> MessageIds { get; set; } = new();
}
21 changes: 21 additions & 0 deletions Sources/Mailozaurr.Application/DeleteMessagesRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace Mailozaurr.Application;

/// <summary>
/// Request for deleting one or more messages.
/// </summary>
public sealed class DeleteMessagesRequest {
/// <summary>Profile identifier.</summary>
public string ProfileId { get; set; } = string.Empty;

/// <summary>Optional mailbox identifier for multi-mailbox providers.</summary>
public string? MailboxId { get; set; }

/// <summary>Optional folder identifier or folder path.</summary>
public string? FolderId { get; set; }

/// <summary>Provider-specific message identifiers to delete.</summary>
public List<string> MessageIds { get; set; } = new();

/// <summary>Optional confirmation token from a prior preview for this exact action.</summary>
public string? ConfirmationToken { get; set; }
}
Loading
Loading