private async Task MarkBlastAsDelivered(EmailBlast blast, int sent, CancellationToken cancellationToken)
 {
     blast.Status          = "Delivered";
     blast.EmailsDelivered = sent;
     blast.StatusChangedOn = DateTime.Now;
     await _emailBlastRepository.UpdateAsync(blast, cancellationToken);
 }
Exemple #2
0
        public async Task DeliverBlast(EmailBlast blast, CancellationToken cancellationToken)
        {
            _logger.LogInformation($"Processing email blast with id {blast.Id}");

            if (blast.Template == null)
            {
                throw new Exception($"Could not send blast with id {blast.Id}: template id was null");
            }

            if (blast.Customer == null)
            {
                throw new Exception($"Could not send blast with id {blast.Id}: customer id was null");
            }

            var template = await _templateRepository.GetByIdAsync(blast.Template, cancellationToken);

            if (template == null)
            {
                await MarkBlastAsErrored(blast, cancellationToken);

                throw new Exception($"Could not send blast with id {blast.Id}: template with " +
                                    $"id {blast.Template} not found");
            }

            var customer = await _customerRepository.GetByIdAsync(blast.Customer, cancellationToken);

            if (customer == null)
            {
                await MarkBlastAsErrored(blast, cancellationToken);

                throw new Exception($"Could not send email blast with id {blast.Id}: " +
                                    $"customer not found");
            }

            try
            {
                _logger.LogInformation($"Delivering email blast with template '{template.Name}' " +
                                       $"for customer '{customer.FirstName} {customer.LastName}'");

                var recipients =
                    await _recipientRepository.GetRecipientsForCustomer(blast.Customer, cancellationToken);

                await ProcessBlast(template, customer, recipients, cancellationToken);
                await MarkBlastAsDelivered(blast, recipients.Count, cancellationToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"Could not send email blast for blast {blast.Id}");
                await MarkBlastAsErrored(blast, cancellationToken);
            }
        }
Exemple #3
0
        private async Task ScheduleBlast(EmailBlast blast, CancellationToken cancellationToken)
        {
            if (_scheduler == null)
            {
                throw new Exception("Scheduler should not be null");
            }

            try {
                var jobDetails = new JobDetailImpl($"EmailDeliver_{blast.Id}", typeof(EmailDeliveryJob));
                jobDetails.JobDataMap["blastId"] = blast.Id ?? "";

                var trigger = new CronTriggerImpl($"EmailDeliveryTrigger_{blast.Id}", "email", blast.Schedule);

                await _scheduler.ScheduleJob(jobDetails, trigger, cancellationToken);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Couldn't schedule blast");
            }
        }
        public async Task Should_Not_Send_An_Email_When_Template_Id_Is_Missing()
        {
            // Arrange
            var stubBlast = new EmailBlast {
                Template = "123"
            };

            _emailBlastRepository.Setup(x =>
                                        x.GetPendingEmailBlastsAsync(It.IsAny <CancellationToken>()))
            .ReturnsAsync(new List <EmailBlast>(new [] { stubBlast }));

            // Act
            var tcs = new CancellationTokenSource();

            tcs.CancelAfter(TimeSpan.FromSeconds(10));
            await _sut.ExecuteAsync(tcs.Token);

            // Assert
            _smtpClient.Verify(x => x.SendMailAsync(It.IsAny <MailMessage>()),
                               Times.Never);
        }
Exemple #5
0
        public async Task Should_Send_Emails_To_Recipients_Using_Template()
        {
            // Arrange
            var stubBlast = new EmailBlast
            {
                Customer = "123",
                Template = "456"
            };
            var stubCustomer = new Customer
            {
                Id        = "123",
                FirstName = "Derek",
                LastName  = "Smith",
                Email     = "*****@*****.**"
            };
            var stubTemplate = new Template
            {
                Id   = "456",
                Name = "Test Template"
            };
            var stubRecipient1 = new EmailRecipient {
                Email = "*****@*****.**"
            };
            var stubRecipient2 = new EmailRecipient {
                Email = "*****@*****.**"
            };
            var stubRecipient3 = new EmailRecipient {
                Email = "*****@*****.**"
            };

            _emailBlastRepository.Setup(x =>
                                        x.GetPendingEmailBlastsAsync(It.IsAny <CancellationToken>()))
            .ReturnsAsync(new List <EmailBlast>(new[] { stubBlast }));
            _templateRepository.Setup(x =>
                                      x.GetByIdAsync(stubBlast.Template, It.IsAny <CancellationToken>()))
            .ReturnsAsync(stubTemplate);
            _customerRepository.Setup(x =>
                                      x.GetByIdAsync(stubBlast.Customer, It.IsAny <CancellationToken>()))
            .ReturnsAsync(stubCustomer);
            _recipientRepository.Setup(x =>
                                       x.GetRecipientsForCustomer(stubBlast.Customer, It.IsAny <CancellationToken>()))
            .ReturnsAsync(new List <EmailRecipient>(new[]
                                                    { stubRecipient1, stubRecipient2, stubRecipient3 }));
            _templateEngine.Setup(x => x.MergeTemplate(It.IsAny <Template>(), It.IsAny <Customer>(),
                                                       stubRecipient1, It.IsAny <CancellationToken>()))
            .ReturnsAsync("Email to stub recipient 1.");
            _templateEngine.Setup(x => x.MergeTemplate(It.IsAny <Template>(), It.IsAny <Customer>(),
                                                       stubRecipient2, It.IsAny <CancellationToken>()))
            .ReturnsAsync("Email to stub recipient 2.");
            _templateEngine.Setup(x => x.MergeTemplate(It.IsAny <Template>(), It.IsAny <Customer>(),
                                                       stubRecipient3, It.IsAny <CancellationToken>()))
            .ReturnsAsync("Email to stub recipient 3.");

            // Act
            var cts = new CancellationTokenSource();

            cts.CancelAfter(TimeSpan.FromSeconds(10));
            await _sut.DeliverBlast(stubBlast, cts.Token);

            // Assert
            _smtpClient.Verify(x =>
                               x.SendMailAsync(It.Is <MailMessage>(m =>
                                                                   m.Body == "Email to stub recipient 1.")), Times.Once);
            _smtpClient.Verify(x =>
                               x.SendMailAsync(It.Is <MailMessage>(m =>
                                                                   m.Body == "Email to stub recipient 2.")), Times.Once);
            _smtpClient.Verify(x =>
                               x.SendMailAsync(It.Is <MailMessage>(m =>
                                                                   m.Body == "Email to stub recipient 3.")), Times.Once);
        }
 private async Task MarkBlastAsErrored(EmailBlast blast, CancellationToken cancellationToken)
 {
     blast.Status          = "Error";
     blast.StatusChangedOn = DateTime.Now;
     await _emailBlastRepository.UpdateAsync(blast, cancellationToken);
 }