refactor(notification-outbox): share SMTP helpers between NotificationService and the Email adapter

FU1 of the Notification Outbox follow-ups. EmailNotificationDeliveryAdapter
carried verbatim private copies of credential redaction, SMTP error
classification, and address validation because the NotificationService
helpers were internal. This eliminates the divergence risk by promoting the
helpers to public and deleting the adapter's copies.

- CredentialRedactor: internal -> public.
- Extract SmtpErrorClassifier + SmtpErrorClass enum into a new public static
  class; NotificationDeliveryService now routes classification through it
  (behavior unchanged). Adds focused SmtpErrorClassifierTests.
- NotificationDeliveryService.ValidateAddresses: internal -> public; the
  adapter calls it directly.
- EmailNotificationDeliveryAdapter: deleted ScrubCredentials, ClassifySmtpError,
  SmtpErrorClass, IsTransientSmtpError and ValidateAddresses copies.

No InternalsVisibleTo hack — specific helpers promoted to public. Both test
suites green; full solution builds clean.
This commit is contained in:
Joseph Doherty
2026-05-19 03:34:22 -04:00
parent 213b9c7c0a
commit 5e80f64cd8
5 changed files with 250 additions and 188 deletions

View File

@@ -6,8 +6,12 @@ namespace ScadaLink.NotificationService;
/// MailKit authentication exceptions can contain server responses that quote the
/// supplied credentials; this prevents a password, client secret, or OAuth2 token
/// from leaking into the operational logs.
/// <para>
/// Public so the central Notification Outbox's <c>EmailNotificationDeliveryAdapter</c>
/// can share this exact redaction logic rather than carry a divergent copy.
/// </para>
/// </summary>
internal static class CredentialRedactor
public static class CredentialRedactor
{
private const string Mask = "***REDACTED***";