Refactor Email to EmailContext across codebase

Replaced the `Email` record with the new `EmailContext` record to introduce additional context and functionality in email handling. Updated property definitions to distinguish between .NET Framework (`set`) and other frameworks (`init`).

Modified `SendingEmailEvent` to use `EmailContext` for the `Mail` property. Updated mappings in `EmailMappingProfile` to map `SendEmailCommand` to `EmailContext`. Adjusted `SendEmailCommandHandler` to use `EmailContext` when mapping requests.

Refactored `EmailSender` to use `EmailContext` in its `Send` method, including updates to method signatures and documentation. Updated all related test classes (`EmailSenderTests`, `EmailSenderUrlOverloadTests`, `SendingEmailPublisherTests`) to validate the behavior of `EmailContext`, ensuring consistency and thorough testing of the transition.

These changes ensure compatibility across frameworks and improve the maintainability of the email handling process.
This commit is contained in:
2026-08-05 14:06:41 +02:00
parent c6e67c0f99
commit 3cd8841e80
8 changed files with 14 additions and 14 deletions

View File

@@ -1,6 +1,6 @@
namespace DigitalData.MessagingService.Abstraction; namespace DigitalData.MessagingService.Abstraction;
public record Email public record EmailContext
{ {
#if NETFRAMEWORK #if NETFRAMEWORK
public EmailAccountDto Sender { get; set; } = null!; public EmailAccountDto Sender { get; set; } = null!;

View File

@@ -9,9 +9,9 @@ public record SendingEmailEvent
#endif #endif
#if NETFRAMEWORK #if NETFRAMEWORK
public Email Mail { get; set; } = null!; public EmailContext Mail { get; set; } = null!;
#else #else
public required Email Mail { get; init; } public required EmailContext Mail { get; init; }
#endif #endif
#if NETFRAMEWORK #if NETFRAMEWORK

View File

@@ -13,6 +13,6 @@ public class EmailMappingProfile : Profile
{ {
// SendEmailCommand -> Email // SendEmailCommand -> Email
// Sender is resolved via MediatR in the handler and set separately after mapping. // Sender is resolved via MediatR in the handler and set separately after mapping.
CreateMap<SendEmailCommand, Email>(); CreateMap<SendEmailCommand, EmailContext>();
} }
} }

View File

@@ -46,7 +46,7 @@ public class SendEmailCommandHandler(ISender Sender, ISendingEmailPublisher Publ
?? throw new NotFoundException( ?? throw new NotFoundException(
$"No email account found for the given sender criteria (Id: {request.Sender.Id}, Username: {request.Sender.Username})."); $"No email account found for the given sender criteria (Id: {request.Sender.Id}, Username: {request.Sender.Username}).");
var email = Mapper.Map<Email>(request) with { Sender = senderAccount }; var email = Mapper.Map<EmailContext>(request) with { Sender = senderAccount };
// Enqueue to RabbitMQ // Enqueue to RabbitMQ
var sendingEmailEvent = new SendingEmailEvent() var sendingEmailEvent = new SendingEmailEvent()

View File

@@ -113,13 +113,13 @@ public static class EmailSender
/// Thrown when <see cref="ConnectRabbitMq(Action{RabbitMqConfiguration}, OnReconnect)"/> has not been called prior to sending. /// Thrown when <see cref="ConnectRabbitMq(Action{RabbitMqConfiguration}, OnReconnect)"/> has not been called prior to sending.
/// </exception> /// </exception>
/// <remarks> /// <remarks>
/// This method maps <see cref="Email"/> to <see cref="SendingEmailEvent"/>, /// This method maps <see cref="EmailContext"/> to <see cref="SendingEmailEvent"/>,
/// then resolves <see cref="ISendingEmailPublisher"/> from the internal /// then resolves <see cref="ISendingEmailPublisher"/> from the internal
/// service provider and calls <c>EnqueueAsync</c> in a fire-and-forget manner. /// service provider and calls <c>EnqueueAsync</c> in a fire-and-forget manner.
/// Ensure that any unhandled exceptions from the async operation are handled /// Ensure that any unhandled exceptions from the async operation are handled
/// at the publisher level. /// at the publisher level.
/// </remarks> /// </remarks>
public static void Send(Email email) public static void Send(EmailContext email)
{ {
if(!IsConnected) if(!IsConnected)
throw new InvalidOperationException("Messaging service is not connected. Call ConnectRabbitMq first."); throw new InvalidOperationException("Messaging service is not connected. Call ConnectRabbitMq first.");

View File

@@ -75,7 +75,7 @@ public sealed class EmailSenderTests
[Fact] [Fact]
public void Send_WithValidEmail_DoesNotThrow() public void Send_WithValidEmail_DoesNotThrow()
{ {
var email = new Email var email = new EmailContext
{ {
Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" },
Recipients = ["hakanttek@gmail.com"], Recipients = ["hakanttek@gmail.com"],
@@ -92,7 +92,7 @@ public sealed class EmailSenderTests
[Fact] [Fact]
public void Send_WithPlainTextBody_DoesNotThrow() public void Send_WithPlainTextBody_DoesNotThrow()
{ {
var email = new Email var email = new EmailContext
{ {
Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" },
Recipients = ["hakanttek@gmail.com"], Recipients = ["hakanttek@gmail.com"],

View File

@@ -55,7 +55,7 @@ public sealed class EmailSenderUrlOverloadTests
[Fact] [Fact]
public void Send_AfterUrlOverloadConnection_DoesNotThrow() public void Send_AfterUrlOverloadConnection_DoesNotThrow()
{ {
var email = new Email var email = new EmailContext
{ {
Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" },
Recipients = ["url-overload-test@example.com"], Recipients = ["url-overload-test@example.com"],

View File

@@ -37,7 +37,7 @@ public sealed class SendingEmailPublisherTests : IAsyncDisposable
var email = new SendingEmailEvent var email = new SendingEmailEvent
{ {
Id = Guid.NewGuid(), Id = Guid.NewGuid(),
Mail = new Email Mail = new EmailContext
{ {
Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" },
Recipients = ["test@example.com"], Recipients = ["test@example.com"],
@@ -66,7 +66,7 @@ public sealed class SendingEmailPublisherTests : IAsyncDisposable
var emails = Enumerable.Range(1, 3).Select(i => new SendingEmailEvent var emails = Enumerable.Range(1, 3).Select(i => new SendingEmailEvent
{ {
Id = Guid.NewGuid(), Id = Guid.NewGuid(),
Mail = new Email Mail = new EmailContext
{ {
Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" },
Recipients = new List<string> { $"recipient{i}@example.com" }, Recipients = new List<string> { $"recipient{i}@example.com" },
@@ -93,7 +93,7 @@ public sealed class SendingEmailPublisherTests : IAsyncDisposable
var email = new SendingEmailEvent var email = new SendingEmailEvent
{ {
Id = Guid.NewGuid(), Id = Guid.NewGuid(),
Mail = new Email Mail = new EmailContext
{ {
Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" },
Recipients = ["depth-test@example.com"], Recipients = ["depth-test@example.com"],
@@ -120,7 +120,7 @@ public sealed class SendingEmailPublisherTests : IAsyncDisposable
var email = new SendingEmailEvent var email = new SendingEmailEvent
{ {
Id = id, Id = id,
Mail = new Email Mail = new EmailContext
{ {
Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" }, Sender = new EmailAccountDto { Username = "test@example.com", Password = "password", SmtpServer = "smtp.example.com" },
Recipients = new List<string> { "serialize@example.com" }, Recipients = new List<string> { "serialize@example.com" },