Replace shared email commands with MediatR notifications (#280)

This commit is contained in:
Aaron Po
2026-09-05 22:37:00 -04:00
committed by GitHub
parent 4aa7ba5d9b
commit d958933250
24 changed files with 322 additions and 218 deletions

View File

@@ -1,22 +0,0 @@
using Features.Emails.Services;
using MediatR;
using Shared.Application.Emails;
namespace Features.Emails.Commands.SendRegistrationEmail;
/// <summary>
/// Handles <see cref="SendRegistrationEmailCommand" />, the cross-slice command sent by Features.Users
/// after a new user registers.
/// </summary>
public class SendRegistrationEmailHandler(IEmailDispatcher emailDispatcher)
: IRequestHandler<SendRegistrationEmailCommand>
{
public Task Handle(SendRegistrationEmailCommand request, CancellationToken cancellationToken)
{
return emailDispatcher.SendRegistrationEmailAsync(
request.FirstName,
request.Email,
request.ConfirmationToken
);
}
}

View File

@@ -1,25 +0,0 @@
using Features.Emails.Services;
using MediatR;
using Shared.Application.Emails;
namespace Features.Emails.Commands.SendResendConfirmationEmail;
/// <summary>
/// Handles <see cref="SendResendConfirmationEmailCommand" />, the cross-slice command sent by Features.Users
/// when a user requests a fresh confirmation link.
/// </summary>
public class SendResendConfirmationEmailHandler(IEmailDispatcher emailDispatcher)
: IRequestHandler<SendResendConfirmationEmailCommand>
{
public Task Handle(
SendResendConfirmationEmailCommand request,
CancellationToken cancellationToken
)
{
return emailDispatcher.SendResendConfirmationEmailAsync(
request.FirstName,
request.Email,
request.ConfirmationToken
);
}
}

View File

@@ -18,5 +18,6 @@
<ProjectReference Include="..\..\Infrastructure\Infrastructure.Email\Infrastructure.Email.csproj" />
<ProjectReference Include="..\..\Infrastructure\Infrastructure.Email.Templates\Infrastructure.Email.Templates.csproj" />
<ProjectReference Include="..\..\Shared\Shared.Application\Shared.Application.csproj" />
<ProjectReference Include="..\Features.Users\Features.Users.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,44 @@
using Features.Auth.Notifications;
using Features.Emails.Services;
using MediatR;
using Microsoft.Extensions.Logging;
namespace Features.Emails.Notifications;
/// <summary>
/// Handles <see cref="ConfirmationEmailResendRequestedNotification" />, the cross-slice notification
/// published by Features.Users when a user requests a fresh confirmation link, by sending the resend
/// confirmation email.
/// </summary>
public class ConfirmationEmailResendRequestedNotificationHandler(
IEmailDispatcher emailDispatcher,
ILogger<ConfirmationEmailResendRequestedNotificationHandler> logger
) : INotificationHandler<ConfirmationEmailResendRequestedNotification>
{
/// <remarks>
/// Delivery failures are logged and swallowed rather than rethrown, so that a broken mail server
/// never fails the resend request that already succeeded.
/// </remarks>
public async Task Handle(
ConfirmationEmailResendRequestedNotification notification,
CancellationToken cancellationToken
)
{
try
{
await emailDispatcher.SendResendConfirmationEmailAsync(
notification.FirstName,
notification.Email,
notification.ConfirmationToken
);
}
catch (Exception ex)
{
logger.LogError(
ex,
"Failed to send resend confirmation email to user {UserId}",
notification.UserId
);
}
}
}

View File

@@ -0,0 +1,40 @@
using Features.Auth.Notifications;
using Features.Emails.Services;
using MediatR;
using Microsoft.Extensions.Logging;
namespace Features.Emails.Notifications;
/// <summary>
/// Handles <see cref="UserRegisteredNotification" />, the cross-slice notification published by
/// Features.Users after a new user registers, by sending the registration confirmation email.
/// </summary>
public class UserRegisteredNotificationHandler(
IEmailDispatcher emailDispatcher,
ILogger<UserRegisteredNotificationHandler> logger
) : INotificationHandler<UserRegisteredNotification>
{
/// <remarks>
/// Delivery failures are logged and swallowed rather than rethrown, so that a broken mail server
/// never fails the registration that already succeeded.
/// </remarks>
public async Task Handle(UserRegisteredNotification notification, CancellationToken cancellationToken)
{
try
{
await emailDispatcher.SendRegistrationEmailAsync(
notification.FirstName,
notification.Email,
notification.ConfirmationToken
);
}
catch (Exception ex)
{
logger.LogError(
ex,
"Failed to send registration confirmation email to user {UserId}",
notification.UserId
);
}
}
}