feat(notifications): EmailTransport enum + parser for the EWS transport discriminator

This commit is contained in:
Joseph Doherty
2026-08-10 06:07:14 -04:00
parent 9f4d7d4bcb
commit d21b7a5a48
2 changed files with 90 additions and 0 deletions
@@ -0,0 +1,50 @@
namespace ZB.MOM.WW.ScadaBridge.NotificationService;
/// <summary>
/// The email delivery transports the service supports. The configured
/// <c>SmtpConfiguration.Transport</c> string is parsed into this enum to choose
/// which client actually submits the message.
/// </summary>
public enum EmailTransport
{
/// <summary>Direct SMTP submission via MailKit (the original path).</summary>
Smtp,
/// <summary>On-prem Exchange Web Services — one CreateItem SOAP call over HTTPS.</summary>
Ews,
}
/// <summary>
/// Parses the free-text <c>SmtpConfiguration.Transport</c> value into an
/// <see cref="EmailTransport"/>, rejecting unknown values rather than silently
/// falling back to SMTP.
/// </summary>
public static class EmailTransportParser
{
/// <summary>
/// Parses a configured transport string. A null or empty value defaults to
/// <see cref="EmailTransport.Smtp"/> — every pre-EWS configuration row stores no
/// transport and is an SMTP row. An unknown value is a configuration error that
/// retrying cannot fix, so it throws and the delivery adapter surfaces it as a
/// permanent failure (mirrors <see cref="SmtpTlsModeParser"/>).
/// </summary>
/// <param name="transport">The transport string to parse (Smtp or Ews); null/empty defaults to Smtp.</param>
/// <exception cref="ArgumentException">The value is not one of Smtp/Ews.</exception>
/// <returns>The corresponding <see cref="EmailTransport"/> enum value.</returns>
public static EmailTransport Parse(string? transport)
{
if (string.IsNullOrWhiteSpace(transport))
{
return EmailTransport.Smtp;
}
return transport.Trim().ToLowerInvariant() switch
{
"smtp" => EmailTransport.Smtp,
"ews" => EmailTransport.Ews,
_ => throw new ArgumentException(
$"Unknown email transport '{transport}'. Expected one of: Smtp, Ews.",
nameof(transport)),
};
}
}
@@ -0,0 +1,40 @@
namespace ZB.MOM.WW.ScadaBridge.NotificationService.Tests;
/// <summary>
/// Tests for parsing the configured email transport discriminator into the two-state enum.
/// </summary>
public class EmailTransportParserTests
{
[Theory]
[InlineData("Smtp", EmailTransport.Smtp)]
[InlineData("smtp", EmailTransport.Smtp)]
[InlineData("SMTP", EmailTransport.Smtp)]
[InlineData("Ews", EmailTransport.Ews)]
[InlineData("ews", EmailTransport.Ews)]
[InlineData("EWS", EmailTransport.Ews)]
[InlineData(" ews ", EmailTransport.Ews)]
public void Parse_KnownTransports_ReturnsExpected(string input, EmailTransport expected)
{
Assert.Equal(expected, EmailTransportParser.Parse(input));
}
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData(" ")]
public void Parse_NullOrEmpty_DefaultsToSmtp(string? input)
{
// Every pre-EWS SmtpConfiguration row stores no transport; those rows are SMTP rows.
Assert.Equal(EmailTransport.Smtp, EmailTransportParser.Parse(input));
}
[Theory]
[InlineData("Graph")]
[InlineData("smtps")]
public void Parse_UnknownTransport_Throws(string input)
{
// An unknown transport must be rejected, not silently treated as SMTP.
var ex = Assert.Throws<ArgumentException>(() => EmailTransportParser.Parse(input));
Assert.Contains(input, ex.Message);
}
}