Refactor namespaces and remove Abstraction project

Replaced `DigitalData.MessagingService.Abstraction` with
`DigitalData.MessagingService.Application.Common.Dto` and
`DigitalData.MessagingService.Application.Common.Dto.MailSearch`
to improve modularity and organization.

Removed the `Abstraction` project and updated all references
to use the `Application` project. Updated namespaces, `using`
directives, and dependencies across the codebase.

Refactored interfaces, commands, queries, validators, and
services to use the new DTOs. Updated RabbitMQ integration,
AutoMapper profiles, background services, and tests to align
with the new structure.

Performed general cleanup by removing redundant `using`
directives and obsolete references.
This commit is contained in:
2026-08-12 15:13:15 +02:00
parent 4dd0974c6f
commit 91581649ba
37 changed files with 44 additions and 67 deletions

View File

@@ -0,0 +1,15 @@
#if NET
namespace DigitalData.MessagingService.Application.Common.Dto.MailSearch;
/// <summary>
/// Constrains the search to messages within an arrival-date range.
/// </summary>
/// <remarks>
/// At least one of <see cref="After"/> or <see cref="Before"/> must be provided.
/// When both are set <see cref="After"/> must be earlier than <see cref="Before"/>.
/// Both bounds are <b>inclusive</b>.
/// </remarks>
/// <param name="After">Earliest date to include (inclusive). Maps to IMAP <c>SINCE</c>.</param>
/// <param name="Before">Latest date to include (inclusive). Maps to IMAP <c>BEFORE</c> (next day is used internally).</param>
public record DateFilter(DateTime? After = null, DateTime? Before = null);
#endif

View File

@@ -0,0 +1,80 @@
#if NET
namespace DigitalData.MessagingService.Application.Common.Dto.MailSearch;
/// <summary>
/// Describes all criteria and options used when searching an IMAP mailbox.
/// </summary>
/// <remarks>
/// All text-match properties are <b>case-insensitive</b> substring searches performed server-side via IMAP SEARCH.
/// Combine multiple criteria freely; an implicit AND is applied across all non-null fields.
/// </remarks>
public record MailSearchFilter
{
/// <summary>
/// Mailbox folder to search. Defaults to <c>"INBOX"</c>.
/// </summary>
public string Folder { get; init; } = "INBOX";
/// <summary>
/// When <see langword="true"/>, only unread (UNSEEN) messages are returned.
/// </summary>
public bool UnseenOnly { get; init; } = false;
/// <summary>
/// When <see langword="true"/>, attachment data is included in the results; otherwise attachments are omitted.
/// Defaults to <see langword="false"/>.
/// </summary>
public bool WithAttachments { get; init; } = false;
/// <summary>
/// Maximum number of messages to retrieve. <c>0</c> means unlimited.
/// Applied after sorting; defaults to <c>50</c>.
/// </summary>
public int? MaxCount { get; init; } = null;
/// <summary>
/// Controls the order of the returned messages. Defaults to <see cref="MailSortOrder.NewestFirst"/>.
/// </summary>
public MailSortOrder SortOrder { get; init; } = MailSortOrder.NewestFirst;
// ── Text filters ───────────────────────────────────────────────────────────
/// <summary>
/// Case-insensitive substring the message subject must contain.
/// Maps to IMAP <c>SUBJECT</c>.
/// </summary>
public string? SubjectContains { get; init; } = null;
/// <summary>
/// Case-insensitive substring that must appear in the <c>From</c> header.
/// Maps to IMAP <c>FROM</c>.
/// </summary>
public string? SenderContains { get; init; } = null;
/// <summary>
/// Case-insensitive substring that must appear in <c>To</c> or <c>Cc</c>.
/// Maps to IMAP <c>TO</c>.
/// </summary>
public string? RecipientContains { get; init; } = null;
/// <summary>
/// Case-insensitive substring that must appear anywhere in the message body (text or HTML part).
/// Maps to IMAP <c>BODY</c>.
/// </summary>
public string? BodyContains { get; init; } = null;
// ── Structured filters ─────────────────────────────────────────────────────
/// <summary>
/// Constrains results to a specific UID or a UID range.
/// See <see cref="UidFilter"/> for mutual-exclusion rules between its fields.
/// </summary>
public UidFilter? Uid { get; init; } = null;
/// <summary>
/// Constrains results to messages received within a date range.
/// See <see cref="DateFilter"/> for rules between its fields.
/// </summary>
public DateFilter? Date { get; init; } = null;
}
#endif

View File

@@ -0,0 +1,17 @@
namespace DigitalData.MessagingService.Application.Common.Dto.MailSearch;
/// <summary>
/// Controls the order in which fetched messages are returned.
/// </summary>
public enum MailSortOrder
{
/// <summary>
/// Newest messages first (default).
/// </summary>
NewestFirst,
/// <summary>
/// Oldest messages first.
/// </summary>
OldestFirst
}

View File

@@ -0,0 +1,16 @@
#if NET
namespace DigitalData.MessagingService.Application.Common.Dto.MailSearch;
/// <summary>
/// Constrains the search to a specific UID or a UID range.
/// </summary>
/// <remarks>
/// Use <see cref="Absolute"/> for an exact single-message lookup.
/// Use <see cref="Min"/> and/or <see cref="Max"/> for an open or closed range.
/// Mixing <see cref="Absolute"/> with <see cref="Min"/> or <see cref="Max"/> is not allowed.
/// </remarks>
/// <param name="Min">Lower bound of the UID range (inclusive). Ignored when <see cref="Absolute"/> is set.</param>
/// <param name="Max">Upper bound of the UID range (inclusive). Ignored when <see cref="Absolute"/> is set.</param>
/// <param name="Absolute">Exact UID to match. When set, <see cref="Min"/> and <see cref="Max"/> must be <see langword="null"/>.</param>
public record UidFilter(long? Min = null, long? Max = null, long? Absolute = null);
#endif