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); }
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); } }
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); }
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); }