From 61ccf9c777272211936be266f59123ec0c5bf1c4 Mon Sep 17 00:00:00 2001 From: Anatolii Grynchuk Date: Sat, 2 May 2026 02:57:36 +0300 Subject: [PATCH] feat: add test channel feature in admin UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - POST /admin/channels/{id}/test — direct SMTP send via MailKit - Test button shown only on existing channels (not create) - Bootstrap modal with recipient email input and spinner - Inline success/error result inside the modal Ref: IT-628 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Directory.Packages.props | 2 +- .../Admin/AdminChannelsController.cs | 45 ++++++++++++ .../HrynCo.NotificationService.Web.csproj | 1 + .../Views/AdminChannels/Edit.cshtml | 68 +++++++++++++++++++ 4 files changed, 115 insertions(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index a14dcb9..d9e8dc6 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -31,7 +31,7 @@ - + diff --git a/HrynCo.NotificationService.Web/Controllers/Admin/AdminChannelsController.cs b/HrynCo.NotificationService.Web/Controllers/Admin/AdminChannelsController.cs index 2f0cd56..f833b03 100644 --- a/HrynCo.NotificationService.Web/Controllers/Admin/AdminChannelsController.cs +++ b/HrynCo.NotificationService.Web/Controllers/Admin/AdminChannelsController.cs @@ -5,8 +5,11 @@ using HrynCo.NotificationService.Services.EmailChannels.Get; using HrynCo.NotificationService.Services.EmailChannels.GetAll; using HrynCo.NotificationService.Services.EmailChannels.Update; using HrynCo.NotificationService.Web.Controllers.Admin.ViewModels; +using MailKit.Net.Smtp; +using MailKit.Security; using MediatR; using Microsoft.AspNetCore.Mvc; +using MimeKit; namespace HrynCo.NotificationService.Web.Controllers.Admin; @@ -142,6 +145,46 @@ public class AdminChannelsController : Controller return RedirectToAction(nameof(Index)); } + // POST /admin/channels/{id}/test + [HttpPost("{id:guid}/test")] + public async Task Test(Guid id, [FromBody] TestChannelRequest request, CancellationToken ct) + { + var result = await _mediator.Send(new GetEmailChannelQuery(id), ct); + if (!result.IsSuccess || result.Result is null) + return NotFound(new { success = false, message = "Channel not found." }); + + if (result.Result.Settings is not SmtpChannelSettings smtp) + return BadRequest(new { success = false, message = "Only SMTP channels are supported." }); + + try + { + var message = new MimeMessage(); + message.From.Add(new MailboxAddress(smtp.FromName, smtp.FromEmail)); + message.To.Add(MailboxAddress.Parse(request.ToEmail)); + message.Subject = "✅ Test email from Notification Service"; + message.Body = new TextPart("plain") + { + Text = $"This is a test email sent from the Notification Service admin panel.\n\nChannel: {result.Result.ServiceName}\nHost: {smtp.Host}:{smtp.Port}" + }; + + using var client = new SmtpClient(); + var secureSocket = smtp.UseSsl ? SecureSocketOptions.SslOnConnect : SecureSocketOptions.StartTlsWhenAvailable; + await client.ConnectAsync(smtp.Host, smtp.Port, secureSocket, ct); + + if (!string.IsNullOrWhiteSpace(smtp.Username)) + await client.AuthenticateAsync(smtp.Username, smtp.Password, ct); + + await client.SendAsync(message, ct); + await client.DisconnectAsync(true, ct); + + return Ok(new { success = true, message = $"Test email sent to {request.ToEmail}." }); + } + catch (Exception ex) + { + return Ok(new { success = false, message = ex.Message }); + } + } + // POST /admin/channels/{id}/delete [HttpPost("{id:guid}/delete")] [ValidateAntiForgeryToken] @@ -151,3 +194,5 @@ public class AdminChannelsController : Controller return RedirectToAction(nameof(Index)); } } + +public record TestChannelRequest(string ToEmail); diff --git a/HrynCo.NotificationService.Web/HrynCo.NotificationService.Web.csproj b/HrynCo.NotificationService.Web/HrynCo.NotificationService.Web.csproj index ad68963..72f7b80 100644 --- a/HrynCo.NotificationService.Web/HrynCo.NotificationService.Web.csproj +++ b/HrynCo.NotificationService.Web/HrynCo.NotificationService.Web.csproj @@ -7,6 +7,7 @@ + all diff --git a/HrynCo.NotificationService.Web/Views/AdminChannels/Edit.cshtml b/HrynCo.NotificationService.Web/Views/AdminChannels/Edit.cshtml index ded7506..82dae81 100644 --- a/HrynCo.NotificationService.Web/Views/AdminChannels/Edit.cshtml +++ b/HrynCo.NotificationService.Web/Views/AdminChannels/Edit.cshtml @@ -134,8 +134,76 @@ + @if (!Model.IsNew) + { + + } Cancel } + +@if (!Model.IsNew) +{ + + + +}