From b2857c558f1a5cbbc954d56325c38d80d708d757 Mon Sep 17 00:00:00 2001 From: TekH Date: Wed, 12 Aug 2026 15:26:15 +0200 Subject: [PATCH] Refactor: Replace EmailAccountDto with EmailAccount Replaced the `EmailAccountDto` class with the `EmailAccount` class across the codebase to consolidate the `EmailAccount` entity into the domain layer. Updated namespaces, method signatures, property types, and test cases to reflect this change. Moved `EmailAccount` from `DigitalData.MessagingService.Application.Common.Dto` to `DigitalData.MessagingService.Domain.Entities`. Updated XML documentation and removed redundant project file entries. Adjusted namespaces for related queries, validators, and commands to align with the new structure. These changes improve separation of concerns and align with domain-driven design principles. --- .../Common/Dto/EmailContext.cs | 8 +++++--- .../Common/Interfaces/IImapEmailService.cs | 5 +++-- .../Common/Options/EmailAccountsOptions.cs | 6 +++--- .../Queries/GetSenderQuery.cs | 10 +++++----- .../Validators/GetSenderQueryValidator.cs | 4 ++-- .../EmailReceiving/Commands/MarkEmailAsSeenCommand.cs | 2 +- .../EmailReceiving/Queries/FetchEmailsQuery.cs | 2 +- .../EmailSending/Commands/PublishEmailCommand.cs | 2 +- .../DigitalData.MessagingService.Domain.csproj | 4 ---- .../Entities/EmailAccount.cs} | 4 ++-- .../Services/LimilabsEmailService.cs | 5 +++-- .../Services/LimilabsImapEmailService.cs | 7 ++++--- .../Integration/EmailSenderTests.cs | 5 +++-- .../Integration/EmailSenderUrlOverloadTests.cs | 3 ++- .../Integration/SendingEmailPublisherTests.cs | 11 ++++++----- 15 files changed, 41 insertions(+), 37 deletions(-) rename src/core/DigitalData.MessagingService.Application/{EmailAccount => EmailAccounts}/Queries/GetSenderQuery.cs (76%) rename src/core/DigitalData.MessagingService.Application/{EmailAccount => EmailAccounts}/Validators/GetSenderQueryValidator.cs (85%) rename src/core/{DigitalData.MessagingService.Application/Common/Dto/EmailAccountDto.cs => DigitalData.MessagingService.Domain/Entities/EmailAccount.cs} (92%) diff --git a/src/core/DigitalData.MessagingService.Application/Common/Dto/EmailContext.cs b/src/core/DigitalData.MessagingService.Application/Common/Dto/EmailContext.cs index 2f941c7..640103c 100644 --- a/src/core/DigitalData.MessagingService.Application/Common/Dto/EmailContext.cs +++ b/src/core/DigitalData.MessagingService.Application/Common/Dto/EmailContext.cs @@ -1,11 +1,13 @@ -namespace DigitalData.MessagingService.Application.Common.Dto; +using DigitalData.MessagingService.Domain.Entities; + +namespace DigitalData.MessagingService.Application.Common.Dto; public record EmailContext { #if NETFRAMEWORK - public EmailAccountDto Sender { get; set; } = null!; + public EmailAccount Sender { get; set; } = null!; #else - public required EmailAccountDto Sender { get; init; } + public required EmailAccount Sender { get; init; } #endif /// diff --git a/src/core/DigitalData.MessagingService.Application/Common/Interfaces/IImapEmailService.cs b/src/core/DigitalData.MessagingService.Application/Common/Interfaces/IImapEmailService.cs index 865fc1c..f73b4c4 100644 --- a/src/core/DigitalData.MessagingService.Application/Common/Interfaces/IImapEmailService.cs +++ b/src/core/DigitalData.MessagingService.Application/Common/Interfaces/IImapEmailService.cs @@ -1,6 +1,7 @@ #if NET using DigitalData.MessagingService.Application.Common.Dto; using DigitalData.MessagingService.Application.Common.Dto.MailSearch; +using DigitalData.MessagingService.Domain.Entities; namespace DigitalData.MessagingService.Application.Common.Interfaces; @@ -19,7 +20,7 @@ public interface IImapEmailService /// /// Cancellation token. Task> FetchEmailsAsync( - EmailAccountDto account, + EmailAccount account, MailSearchFilter filter, CancellationToken cancellationToken = default); @@ -27,7 +28,7 @@ public interface IImapEmailService /// Marks a message as seen (read) on the server. /// Task MarkAsSeenAsync( - EmailAccountDto account, + EmailAccount account, long uid, string folder = "INBOX", CancellationToken cancellationToken = default); diff --git a/src/core/DigitalData.MessagingService.Application/Common/Options/EmailAccountsOptions.cs b/src/core/DigitalData.MessagingService.Application/Common/Options/EmailAccountsOptions.cs index 4e5f7b3..06ac656 100644 --- a/src/core/DigitalData.MessagingService.Application/Common/Options/EmailAccountsOptions.cs +++ b/src/core/DigitalData.MessagingService.Application/Common/Options/EmailAccountsOptions.cs @@ -1,10 +1,10 @@ #if NET -using DigitalData.MessagingService.Application.Common.Dto; +using DigitalData.MessagingService.Domain.Entities; namespace DigitalData.MessagingService.Application.Common.Options; /// -/// Wrapper options class that holds a list of entries +/// Wrapper options class that holds a list of entries /// bound from the EmailAccounts configuration section. /// public class EmailAccountsOptions @@ -14,7 +14,7 @@ public class EmailAccountsOptions /// /// The list of configured email accounts. /// - public required IEnumerable Accounts { get; init; } = []; + public required IEnumerable Accounts { get; init; } = []; /// /// How often the IMAP sync worker polls for new emails, in seconds. diff --git a/src/core/DigitalData.MessagingService.Application/EmailAccount/Queries/GetSenderQuery.cs b/src/core/DigitalData.MessagingService.Application/EmailAccounts/Queries/GetSenderQuery.cs similarity index 76% rename from src/core/DigitalData.MessagingService.Application/EmailAccount/Queries/GetSenderQuery.cs rename to src/core/DigitalData.MessagingService.Application/EmailAccounts/Queries/GetSenderQuery.cs index f038e11..a0e3cf6 100644 --- a/src/core/DigitalData.MessagingService.Application/EmailAccount/Queries/GetSenderQuery.cs +++ b/src/core/DigitalData.MessagingService.Application/EmailAccounts/Queries/GetSenderQuery.cs @@ -1,13 +1,13 @@ #if NET using DigitalData.MessagingService.Application.Common.Options; -using DigitalData.MessagingService.Application.Common.Dto; using MediatR; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using DigitalData.MessagingService.Domain.Entities; -namespace DigitalData.MessagingService.Application.EmailAccount.Queries; +namespace DigitalData.MessagingService.Application.EmailAccounts.Queries; -public record GetSenderQuery : IRequest +public record GetSenderQuery : IRequest { public int? Id { get; init; } @@ -19,9 +19,9 @@ public record GetSenderQuery : IRequest /// /// /// -public class GetSenderQueryHandler(IOptions Options, ILogger Logger) : IRequestHandler +public class GetSenderQueryHandler(IOptions Options, ILogger Logger) : IRequestHandler { - public Task Handle(GetSenderQuery request, CancellationToken cancellationToken) + public Task Handle(GetSenderQuery request, CancellationToken cancellationToken) { var accounts = request.Id is not null ? Options.Value.Accounts.Where(a => a.Id == request.Id) diff --git a/src/core/DigitalData.MessagingService.Application/EmailAccount/Validators/GetSenderQueryValidator.cs b/src/core/DigitalData.MessagingService.Application/EmailAccounts/Validators/GetSenderQueryValidator.cs similarity index 85% rename from src/core/DigitalData.MessagingService.Application/EmailAccount/Validators/GetSenderQueryValidator.cs rename to src/core/DigitalData.MessagingService.Application/EmailAccounts/Validators/GetSenderQueryValidator.cs index 61adbcd..846d9c4 100644 --- a/src/core/DigitalData.MessagingService.Application/EmailAccount/Validators/GetSenderQueryValidator.cs +++ b/src/core/DigitalData.MessagingService.Application/EmailAccounts/Validators/GetSenderQueryValidator.cs @@ -1,8 +1,8 @@ #if NET -using DigitalData.MessagingService.Application.EmailAccount.Queries; +using DigitalData.MessagingService.Application.EmailAccounts.Queries; using FluentValidation; -namespace DigitalData.MessagingService.Application.EmailAccount.Validators; +namespace DigitalData.MessagingService.Application.EmailAccounts.Validators; /// /// Validator for . diff --git a/src/core/DigitalData.MessagingService.Application/EmailReceiving/Commands/MarkEmailAsSeenCommand.cs b/src/core/DigitalData.MessagingService.Application/EmailReceiving/Commands/MarkEmailAsSeenCommand.cs index 6c5f23e..4e54038 100644 --- a/src/core/DigitalData.MessagingService.Application/EmailReceiving/Commands/MarkEmailAsSeenCommand.cs +++ b/src/core/DigitalData.MessagingService.Application/EmailReceiving/Commands/MarkEmailAsSeenCommand.cs @@ -1,6 +1,6 @@ #if NET using DigitalData.MessagingService.Application.Common.Interfaces; -using DigitalData.MessagingService.Application.EmailAccount.Queries; +using DigitalData.MessagingService.Application.EmailAccounts.Queries; using DigitalData.MessagingService.Domain.Exceptions; using MediatR; diff --git a/src/core/DigitalData.MessagingService.Application/EmailReceiving/Queries/FetchEmailsQuery.cs b/src/core/DigitalData.MessagingService.Application/EmailReceiving/Queries/FetchEmailsQuery.cs index d2bb708..eeebe4e 100644 --- a/src/core/DigitalData.MessagingService.Application/EmailReceiving/Queries/FetchEmailsQuery.cs +++ b/src/core/DigitalData.MessagingService.Application/EmailReceiving/Queries/FetchEmailsQuery.cs @@ -2,7 +2,7 @@ using DigitalData.MessagingService.Application.Common.Dto; using DigitalData.MessagingService.Application.Common.Dto.MailSearch; using DigitalData.MessagingService.Application.Common.Interfaces; -using DigitalData.MessagingService.Application.EmailAccount.Queries; +using DigitalData.MessagingService.Application.EmailAccounts.Queries; using DigitalData.MessagingService.Domain.Exceptions; using MediatR; diff --git a/src/core/DigitalData.MessagingService.Application/EmailSending/Commands/PublishEmailCommand.cs b/src/core/DigitalData.MessagingService.Application/EmailSending/Commands/PublishEmailCommand.cs index 35585ba..d6299de 100644 --- a/src/core/DigitalData.MessagingService.Application/EmailSending/Commands/PublishEmailCommand.cs +++ b/src/core/DigitalData.MessagingService.Application/EmailSending/Commands/PublishEmailCommand.cs @@ -1,11 +1,11 @@ #if NET using AutoMapper; -using DigitalData.MessagingService.Application.EmailAccount.Queries; using DigitalData.MessagingService.Domain.Exceptions; using DigitalData.MessagingService.Application.Common.Dto; using MediatR; using System.Text.Json.Serialization; using DigitalData.MessagingService.Application.Common.Interfaces; +using DigitalData.MessagingService.Application.EmailAccounts.Queries; namespace DigitalData.MessagingService.Application.EmailSending.Commands; diff --git a/src/core/DigitalData.MessagingService.Domain/DigitalData.MessagingService.Domain.csproj b/src/core/DigitalData.MessagingService.Domain/DigitalData.MessagingService.Domain.csproj index ff515ef..23957d0 100644 --- a/src/core/DigitalData.MessagingService.Domain/DigitalData.MessagingService.Domain.csproj +++ b/src/core/DigitalData.MessagingService.Domain/DigitalData.MessagingService.Domain.csproj @@ -11,8 +11,4 @@ - - - - diff --git a/src/core/DigitalData.MessagingService.Application/Common/Dto/EmailAccountDto.cs b/src/core/DigitalData.MessagingService.Domain/Entities/EmailAccount.cs similarity index 92% rename from src/core/DigitalData.MessagingService.Application/Common/Dto/EmailAccountDto.cs rename to src/core/DigitalData.MessagingService.Domain/Entities/EmailAccount.cs index 2d23298..5530c92 100644 --- a/src/core/DigitalData.MessagingService.Application/Common/Dto/EmailAccountDto.cs +++ b/src/core/DigitalData.MessagingService.Domain/Entities/EmailAccount.cs @@ -1,9 +1,9 @@ -namespace DigitalData.MessagingService.Application.Common.Dto; +namespace DigitalData.MessagingService.Domain.Entities; /// /// DTO for a single email account configuration. /// -public class EmailAccountDto +public class EmailAccount { /// /// Logical name to identify this account (e.g. "default", "support"). diff --git a/src/infrastructure/DigitalData.MessagingService.Infrastructure/Services/LimilabsEmailService.cs b/src/infrastructure/DigitalData.MessagingService.Infrastructure/Services/LimilabsEmailService.cs index c0c1dd3..05971a1 100644 --- a/src/infrastructure/DigitalData.MessagingService.Infrastructure/Services/LimilabsEmailService.cs +++ b/src/infrastructure/DigitalData.MessagingService.Infrastructure/Services/LimilabsEmailService.cs @@ -6,6 +6,7 @@ using Limilabs.Mail; using Limilabs.Mail.Headers; using DigitalData.MessagingService.Infrastructure.Services.Extensions; using DigitalData.MessagingService.Application.Common.Dto; +using DigitalData.MessagingService.Domain.Entities; namespace DigitalData.MessagingService.Infrastructure.Services; @@ -13,7 +14,7 @@ namespace DigitalData.MessagingService.Infrastructure.Services; /// Email service using Limilabs Mail.dll for SMTP operations (send-only). /// Commercial-grade library with superior Exchange support. /// SMTP configuration is injected via IOptions<EmailAccountsOptions> from appsettings.json. -/// Uses the first account in the list whose equals "default", +/// Uses the first account in the list whose equals "default", /// or falls back to the first account if none is named "default". /// public class LimilabsEmailService() : IEmailService @@ -70,7 +71,7 @@ public class LimilabsEmailService() : IEmailService } } - private static async Task ConnectAndAuthenticateSmtpAsync(Smtp smtp, EmailAccountDto smtpAccount) + private static async Task ConnectAndAuthenticateSmtpAsync(Smtp smtp, EmailAccount smtpAccount) { if (smtpAccount.SmtpUseSsl) { diff --git a/src/infrastructure/DigitalData.MessagingService.Infrastructure/Services/LimilabsImapEmailService.cs b/src/infrastructure/DigitalData.MessagingService.Infrastructure/Services/LimilabsImapEmailService.cs index 672f992..cd7a81b 100644 --- a/src/infrastructure/DigitalData.MessagingService.Infrastructure/Services/LimilabsImapEmailService.cs +++ b/src/infrastructure/DigitalData.MessagingService.Infrastructure/Services/LimilabsImapEmailService.cs @@ -1,6 +1,7 @@ using DigitalData.MessagingService.Application.Common.Dto; using DigitalData.MessagingService.Application.Common.Dto.MailSearch; using DigitalData.MessagingService.Application.Common.Interfaces; +using DigitalData.MessagingService.Domain.Entities; using DigitalData.MessagingService.Domain.Exceptions; using DigitalData.MessagingService.Infrastructure.Services.Extensions; using Limilabs.Client.IMAP; @@ -26,7 +27,7 @@ public class LimilabsImapEmailService(ILogger Logger, // Public API public async Task> FetchEmailsAsync( - EmailAccountDto account, + EmailAccount account, MailSearchFilter filter, CancellationToken cancel = default) { @@ -188,7 +189,7 @@ public class LimilabsImapEmailService(ILogger Logger, } public async Task MarkAsSeenAsync( - EmailAccountDto account, + EmailAccount account, long uid, string folder = "INBOX", CancellationToken cancel = default) @@ -213,7 +214,7 @@ public class LimilabsImapEmailService(ILogger Logger, } } - private static async Task OpenAsync(EmailAccountDto account, string folder, CancellationToken cancel) + private static async Task OpenAsync(EmailAccount account, string folder, CancellationToken cancel) { var imap = new Imap(); diff --git a/tests/DigitalData.MessagingService.Tests/Integration/EmailSenderTests.cs b/tests/DigitalData.MessagingService.Tests/Integration/EmailSenderTests.cs index 920e21e..5d61418 100644 --- a/tests/DigitalData.MessagingService.Tests/Integration/EmailSenderTests.cs +++ b/tests/DigitalData.MessagingService.Tests/Integration/EmailSenderTests.cs @@ -1,5 +1,6 @@ using DigitalData.MessagingService.Application.Common.Dto; using DigitalData.MessagingService.Client; +using DigitalData.MessagingService.Domain.Entities; namespace DigitalData.MessagingService.Tests.Integration; @@ -77,7 +78,7 @@ public sealed class EmailSenderTests { var email = new EmailContext { - Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, + Sender = new EmailAccount { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, Recipients = ["hakanttek@gmail.com"], Subject = "EmailSender.Send Integration Test", Body = "

Sent via EmailSender static client.

", @@ -94,7 +95,7 @@ public sealed class EmailSenderTests { var email = new EmailContext { - Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, + Sender = new EmailAccount { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, Recipients = ["hakanttek@gmail.com"], Subject = "Plain Text Test", Body = "This is a plain text email.", diff --git a/tests/DigitalData.MessagingService.Tests/Integration/EmailSenderUrlOverloadTests.cs b/tests/DigitalData.MessagingService.Tests/Integration/EmailSenderUrlOverloadTests.cs index 1686d36..ef84b44 100644 --- a/tests/DigitalData.MessagingService.Tests/Integration/EmailSenderUrlOverloadTests.cs +++ b/tests/DigitalData.MessagingService.Tests/Integration/EmailSenderUrlOverloadTests.cs @@ -1,5 +1,6 @@ using DigitalData.MessagingService.Application.Common.Dto; using DigitalData.MessagingService.Client; +using DigitalData.MessagingService.Domain.Entities; namespace DigitalData.MessagingService.Tests.Integration; @@ -57,7 +58,7 @@ public sealed class EmailSenderUrlOverloadTests { var email = new EmailContext { - Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, + Sender = new EmailAccount { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, Recipients = ["url-overload-test@example.com"], Subject = "URL Overload Integration Test", Body = "

Sent after URL-based connection.

", diff --git a/tests/DigitalData.MessagingService.Tests/Integration/SendingEmailPublisherTests.cs b/tests/DigitalData.MessagingService.Tests/Integration/SendingEmailPublisherTests.cs index 56a0468..6cc5328 100644 --- a/tests/DigitalData.MessagingService.Tests/Integration/SendingEmailPublisherTests.cs +++ b/tests/DigitalData.MessagingService.Tests/Integration/SendingEmailPublisherTests.cs @@ -5,6 +5,7 @@ using DigitalData.MessagingService.RabbitMQ; using Microsoft.Extensions.DependencyInjection; using DigitalData.MessagingService.Application.Common.Dto; using DigitalData.MessagingService.Application.Common.Interfaces; +using DigitalData.MessagingService.Domain.Entities; namespace DigitalData.MessagingService.Tests.Integration; @@ -38,7 +39,7 @@ public sealed class SendingEmailPublisherTests : IAsyncDisposable Id = Guid.NewGuid(), Mail = new EmailContext { - Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, + Sender = new EmailAccount { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, Recipients = ["test@example.com"], Subject = "Integration Test - EnqueueAsync", Body = "

Hello from integration test.

", @@ -67,8 +68,8 @@ public sealed class SendingEmailPublisherTests : IAsyncDisposable Id = Guid.NewGuid(), Mail = new EmailContext { - Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, - Recipients = new List { $"recipient{i}@example.com" }, + Sender = new EmailAccount { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, + Recipients = [$"recipient{i}@example.com"], Subject = $"Integration Test - Batch #{i}", Body = $"Batch message {i}", IsHtml = false, @@ -94,7 +95,7 @@ public sealed class SendingEmailPublisherTests : IAsyncDisposable Id = Guid.NewGuid(), Mail = new EmailContext { - Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, + Sender = new EmailAccount { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, Recipients = ["depth-test@example.com"], Subject = "Integration Test - GetQueueDepth", Body = "Queue depth test", @@ -121,7 +122,7 @@ public sealed class SendingEmailPublisherTests : IAsyncDisposable Id = id, Mail = new EmailContext { - Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, + Sender = new EmailAccount { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, Recipients = new List { "serialize@example.com" }, Subject = "Serialization Test", Body = "Bold",