public async Task NotifyOfOrderFailureAsyncReturnsTheExceptionResultIfCreatingTheMessageThrows() { var config = new EmailNotifierConfiguration { Enabled = true }; var mockLogger = new Mock <ILogger>(); var notifier = new Mock <UnderTest.EmailNotifier>(config, mockLogger.Object) { CallBase = true }; mockLogger .Setup(logger => logger.ForContext(It.IsAny <string>(), It.IsAny <object>(), It.IsAny <bool>())) .Returns(mockLogger.Object); notifier .Protected() .Setup <MailMessage>("CreateMessage", ItExpr.IsAny <string>(), ItExpr.IsAny <string>(), ItExpr.IsAny <string>(), ItExpr.IsAny <IEnumerable <string> >()) .Throws(new MissingDependencyException()); var result = await notifier.Object.NotifyOfOrderFailureAsync("ABC", "123"); result.Should().NotBeNull("becuase a result should have been returned"); result.ShouldBeEquivalentTo(OperationResult.ExceptionResult, "because the exception should short-circuit the processing"); }
public async Task NotifyDeadLetterMessageAsyncRespectsTheEnabledFlag() { var config = new EmailNotifierConfiguration { Enabled = false }; var mockLogger = new Mock <ILogger>(); var notifier = new Mock <UnderTest.EmailNotifier>(config, mockLogger.Object) { CallBase = true }; mockLogger .Setup(logger => logger.ForContext(It.IsAny <string>(), It.IsAny <object>(), It.IsAny <bool>())) .Returns(mockLogger.Object); var result = await notifier.Object.NotifyDeadLetterMessageAsync("Some-Queue", "ABC", "123"); notifier .Protected() .Verify("CreateMessage", Times.Never(), ItExpr.IsAny <string>(), ItExpr.IsAny <string>(), ItExpr.IsAny <string>(), ItExpr.IsAny <IEnumerable <string> >()); notifier .Protected() .Verify("CreateSmtpClient", Times.Never(), ItExpr.IsAny <EmailNotifierConfiguration>()); notifier .Protected() .Verify("SendMessage", Times.Never(), ItExpr.IsAny <SmtpClient>(), ItExpr.IsAny <MailMessage>()); result.Should().NotBeNull("becuase a result should have been returned"); result.Outcome.Should().Be(Outcome.Success, "because a skipped notification should be successful"); }
public async Task NotifyDeadLetterMessageAsyncBuildsTheCorrectMessage() { var config = new EmailNotifierConfiguration { Enabled = true, DeadLetterNotificationBody = "{location}/{partner}/{orderId}/{correlationId}", DeadLetterNotificationSubject = "omg! subject", FromEmailAddress = "*****@*****.**", ToEmailAddressList = "[email protected],[email protected]" }; var mockLogger = new Mock <ILogger>(); var notifier = new Mock <UnderTest.EmailNotifier>(config, mockLogger.Object) { CallBase = true }; var client = new SmtpClient(); var message = default(MailMessage); var location = "process-order"; var partner = "ABC"; var order = "345"; var correlation = "DEF456"; var expectedBody = config.DeadLetterNotificationBody .Replace("{location}", location) .Replace("{partner}", partner) .Replace("{orderId}", order) .Replace("{correlationId}", correlation); mockLogger .Setup(logger => logger.ForContext(It.IsAny <string>(), It.IsAny <object>(), It.IsAny <bool>())) .Returns(mockLogger.Object); notifier .Protected() .Setup <SmtpClient>("CreateSmtpClient", ItExpr.IsAny <EmailNotifierConfiguration>()) .Returns(client); notifier .Protected() .Setup("SendMessage", ItExpr.Is <SmtpClient>(value => value == client), ItExpr.IsAny <MailMessage>()) .Callback <SmtpClient, MailMessage>((clientParam, messageParam) => message = messageParam); var result = await notifier.Object.NotifyDeadLetterMessageAsync(location, partner, order, correlation); result.Should().NotBeNull("becuase a result should have been returned"); result.Outcome.Should().Be(Outcome.Success, "because the notification should be successful"); message.Should().NotBeNull("because the message should have been sent"); message.Subject.Should().Be(config.DeadLetterNotificationSubject, "because the configuration subject should be used"); message.Body.Should().Be(expectedBody, "because the body should have been populated from the configuration and parameers"); message.From.Should().Be(config.FromEmailAddress); foreach (var recipient in config.ToEmailAddressList.Split(',')) { message.To.Any(to => to.Address == recipient).Should().BeTrue("because the recipient {0} should be on the message", recipient); } }
/// <summary> /// Initializes a new instance of the <see cref="EmailNotifier"/> class. /// </summary> /// /// <param name="configuration">The configuration to use for influencing behavior of the notifier.</param> /// <param name="logger">The logger to be used for emitting telemetry from the controller.</param> /// <param name="jsonSerializerSettings">The settings to use for JSON serializerion.</param> /// public EmailNotifier(EmailNotifierConfiguration configuration, ILogger logger) { this.configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); this.Log = logger ?? throw new ArgumentNullException(nameof(logger)); this.emailToAddresses = this.SplitEmailAddressList(EmailNotifier.EmailAddressListSplitChars, configuration.ToEmailAddressList); this.rng = new Random(); }
/// <summary> /// Performs the actions needed to create an SMTP client that can be used to /// sent email. /// </summary> /// /// <param name="configuration">The configuration to use for configuring the SMTP client.</param> /// /// <returns>The SMTP client with the requested configuration</returns> /// protected virtual SmtpClient CreateSmtpClient(EmailNotifierConfiguration configuration) => new SmtpClient { Host = configuration.SmtpHostAddress, Port = configuration.SmtpPort, DeliveryMethod = SmtpDeliveryMethod.Network, UseDefaultCredentials = false, Credentials = new NetworkCredential(configuration.SmtpUserName, configuration.SmtpPasword), Timeout = configuration.SmtpTimeoutMilliseconds };
public async Task NotifyDeadLetterMessageAsyncBuildsTheCorrectClient() { var config = new EmailNotifierConfiguration { Enabled = true, SmtpHostAddress = "server.thing.com", SmtpPort = 1234, SmtpUserName = "******", SmtpPasword = "fly", SmtpTimeoutMilliseconds = 4 }; var mockLogger = new Mock <ILogger>(); var notifier = new Mock <UnderTest.EmailNotifier>(config, mockLogger.Object) { CallBase = true }; var client = default(SmtpClient); var message = new MailMessage(); var location = "process-order"; var partner = "ABC"; var order = "345"; var correlation = "DEF456"; mockLogger .Setup(logger => logger.ForContext(It.IsAny <string>(), It.IsAny <object>(), It.IsAny <bool>())) .Returns(mockLogger.Object); notifier .Protected() .Setup <MailMessage>("CreateMessage", ItExpr.IsAny <string>(), ItExpr.IsAny <string>(), ItExpr.IsAny <string>(), ItExpr.IsAny <IEnumerable <string> >()) .Returns(message); notifier .Protected() .Setup("SendMessage", ItExpr.IsAny <SmtpClient>(), ItExpr.Is <MailMessage>(value => value == message)) .Callback <SmtpClient, MailMessage>((clientParam, messageParam) => client = clientParam); var result = await notifier.Object.NotifyDeadLetterMessageAsync(location, partner, order, correlation); result.Should().NotBeNull("becuase a result should have been returned"); result.Outcome.Should().Be(Outcome.Success, "because the notification should be successful"); client.Should().NotBeNull("because the message should have been sent using the client"); client.Host.Should().Be(config.SmtpHostAddress, "because the host from configuration should be used"); client.Port.Should().Be(config.SmtpPort, "because the port from configuration should be used"); client.Timeout.Should().Be(config.SmtpTimeoutMilliseconds, "because the timeout from configuration should be used"); var credentials = client.Credentials as NetworkCredential; credentials.Should().NotBeNull("because the credentials should be set"); credentials.UserName.Should().Be(config.SmtpUserName, "because the user from configuration should have been used"); credentials.Password.Should().Be(config.SmtpPasword, "because the password from configuration should have been used"); }
public async Task NotifyDeadLetterMessageAsyncSendsTheEmailNotification() { var config = new EmailNotifierConfiguration { Enabled = true }; var mockLogger = new Mock <ILogger>(); var notifier = new Mock <UnderTest.EmailNotifier>(config, mockLogger.Object) { CallBase = true }; var message = new MailMessage(); var client = new SmtpClient(); mockLogger .Setup(logger => logger.ForContext(It.IsAny <string>(), It.IsAny <object>(), It.IsAny <bool>())) .Returns(mockLogger.Object); notifier .Protected() .Setup <MailMessage>("CreateMessage", ItExpr.IsAny <string>(), ItExpr.IsAny <string>(), ItExpr.IsAny <string>(), ItExpr.IsAny <IEnumerable <string> >()) .Returns(message); notifier .Protected() .Setup <SmtpClient>("CreateSmtpClient", ItExpr.IsAny <EmailNotifierConfiguration>()) .Returns(client); notifier .Protected() .Setup("SendMessage", ItExpr.Is <SmtpClient>(value => value == client), ItExpr.Is <MailMessage>(value => value == message)) .Verifiable("The message should have been sent"); var result = await notifier.Object.NotifyDeadLetterMessageAsync("Some-Queue", "ABC", "123"); result.Should().NotBeNull("becuase a result should have been returned"); result.Outcome.Should().Be(Outcome.Success, "because the notification should be successful"); notifier.VerifyAll(); }
public async Task NotifyDeadLetterMessageAsyncHonorsTheRetryPolicyIfSendingTheMessageThrows() { var config = new EmailNotifierConfiguration { Enabled = true, OperationRetryMaxCount = 4, OperationRetryExponentialSeconds = 0, OperationRetryJitterSeconds = 0 }; var mockLogger = new Mock <ILogger>(); var notifier = new Mock <UnderTest.EmailNotifier>(config, mockLogger.Object) { CallBase = true }; var retries = 0; mockLogger .Setup(logger => logger.ForContext(It.IsAny <string>(), It.IsAny <object>(), It.IsAny <bool>())) .Returns(mockLogger.Object); notifier .Protected() .Setup <MailMessage>("CreateMessage", ItExpr.IsAny <string>(), ItExpr.IsAny <string>(), ItExpr.IsAny <string>(), ItExpr.IsAny <IEnumerable <string> >()) .Returns(new MailMessage()); notifier .Protected() .Setup <SmtpClient>("CreateSmtpClient", ItExpr.IsAny <EmailNotifierConfiguration>()) .Returns(new SmtpClient()); notifier .Protected() .Setup("SendMessage", ItExpr.IsAny <SmtpClient>(), ItExpr.IsAny <MailMessage>()) .Callback(() => ++ retries) .Throws(new NullReferenceException()); var result = await notifier.Object.NotifyDeadLetterMessageAsync("Process", "ABC", "123"); retries.Should().Be(config.OperationRetryMaxCount + 1, "because a failure should trigger the retry policy"); }