Esempio n. 1
0
        private EmailQueueItem PanelActionEmail(ActionType actionType, string[] cc, string[] bcc, bool isHtml)
        {
            var emailType = "PanelAction_" + actionType;

            var template = _templateService.GetTemplate(emailType);

            if (template == null)
            {
                template = _templateService.GetTemplate("PanelAction");
                if (template == null)
                {
                    return(null);
                }
            }


            var queue = new EmailQueueItem
            {
                IsBodyHtml = isHtml,
                From       = template.From,
                Subject    = template.Subject,
                Body       = template.Body,
                Priority   = (short)template.Priority,
                CreatedOn  = DateTime.Now
            };

            _templateService.PopulateHeaders(queue, null, cc, bcc, isHtml);

            return(queue);
        }
        /// <summary>
        /// Retrieves attachments for an EmailQueueItem
        /// </summary>
        /// <param name="item">The item to get attachments for</param>
        /// <returns></returns>
        public Attachment[] GetAttachments(EmailQueueItem item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            TroutLog.Log.Info(string.Format("Retrieving attachments for email {0}", item.ID));

            List <Attachment> attachments = new List <Attachment>();

            if (!Directory.Exists(GetAttachmentDirectory(item)))
            {
                return(attachments.ToArray());
            }

            var attachmentDirectories = Directory.EnumerateDirectories(GetAttachmentDirectory(item));

            foreach (var attachmentDirectory in attachmentDirectories)
            {
                var files = Directory.EnumerateFiles(attachmentDirectory);

                if (files.Any())
                {
                    attachments.Add(new Attachment(files.First()));
                }
            }

            TroutLog.Log.Info(string.Format("Retrieved {0} attachments for email {1}", attachments.Count, item.ID));

            return(attachments.ToArray());
        }
Esempio n. 3
0
        public ActionConfirmation Queue(EmailQueueItem item)
        {
            try
            {
                if (item.IsValid())
                {
                    _queueRepository.SaveOrUpdate(item);
                    _queueRepository.DbContext.CommitChanges();

                    var saveOrUpdateConfirmation = ActionConfirmation.CreateSuccess("The emails were successfully queued.");
                    saveOrUpdateConfirmation.Value = item;

                    return(saveOrUpdateConfirmation);
                }
                else
                {
                    _queueRepository.DbContext.RollbackTransaction();

                    return
                        (ActionConfirmation.CreateFailure(
                             "The item could not be queued due to missing or invalid information"));
                }
            }
            catch (Exception exception)
            {
                return
                    (ActionConfirmation.CreateFailure(
                         "The email could not be saved due to missing or invalid information > " + exception.Message));
            }
        }
Esempio n. 4
0
        private MailMessage GetMailMessage(EmailQueueItem message, OverrideList overrides)
        {
            var mailMessage = new MailMessage();

            mailMessage.From = Config.FromAddress;
            if (!string.IsNullOrWhiteSpace(message.To))
            {
                mailMessage.To.Add(message.To);
            }
            if (!string.IsNullOrWhiteSpace(message.Cc))
            {
                mailMessage.CC.Add(message.Cc);
            }
            if (!string.IsNullOrWhiteSpace(message.Bcc))
            {
                mailMessage.Bcc.Add(message.Bcc);
            }
            mailMessage.Subject    = message.Subject;
            mailMessage.Body       = message.Body;
            mailMessage.IsBodyHtml = message.IsBodyHtml;

            mailMessage = StaticOverridesesProvider.StaticOverrides.ApplyOverrides(mailMessage);
            mailMessage = overrides.ApplyOverrides(mailMessage);
            return(mailMessage);
        }
        /// <summary>
        /// Saves attachments on the provided MailMessage based on values in the EmailQueueItem
        /// </summary>
        /// <param name="item">EmailQueueItem that attachments are to be saved on</param>
        /// <param name="mailMessage">MailMessage which contains attachments</param>
        public void SaveAttachments(EmailQueueItem item, MailMessage mailMessage)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            if (mailMessage == null)
            {
                throw new ArgumentNullException("mailMessage");
            }

            TroutLog.Log.Info(string.Format("Saving {0} attachments for email {1}", mailMessage.Attachments.Count, item.ID));

            for (int i = 0; i < mailMessage.Attachments.Count; i++)
            {
                var attachment = mailMessage.Attachments[i];

                Directory.CreateDirectory(GetAttachmentDirectory(item, i));

                using (FileStream file = new FileStream(GetAttachmentFileName(item, i, attachment), FileMode.OpenOrCreate, FileAccess.ReadWrite))
                {
                    byte[] buffer = new byte[attachment.ContentStream.Length];

                    attachment.ContentStream.Read(buffer, 0, buffer.Length);

                    file.Write(buffer, 0, buffer.Length);
                }
            }

            TroutLog.Log.Info(string.Format("Saved {0} attachments for email {1}", mailMessage.Attachments.Count, item.ID));
        }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="emailQueueItem"></param>
 /// <param name="isSuccess"></param>
 /// <param name="message"></param>
 /// <param name="sentMailMessage"></param>
 /// <param name="tries"></param>
 public DequeueResultItem(EmailQueueItem emailQueueItem, bool isSuccess, string message, MailMessage sentMailMessage, int tries)
 {
     EmailQueueItem  = emailQueueItem;
     Tries           = tries;
     SentMailMessage = sentMailMessage;
     Message         = message;
     IsSuccess       = isSuccess;
 }
 private string GetAttachmentDirectory(EmailQueueItem item)
 {
     return(string.Format("{0}\\{1}t\\{2}t\\{3}\\",
                          Config.AttachmentPath,
                          (item.ID / 100000).ToString("000\0\0"), //123,456,789 -> 123400
                          (item.ID / 1000) % 100,                 //123,456,789 -> 56
                          item.ID));
 }
        private void PurgeAttachments(EmailQueueItem item)
        {
            if (!Directory.Exists(GetAttachmentDirectory(item)))
            {
                return;
            }

            TroutLog.Log.Info(string.Format("Purging attachments for email {0} attachments", item.ID));

            Directory.Delete(GetAttachmentDirectory(item), true);
        }
Esempio n. 9
0
 public void Update(string id, EmailMessage message)
 {
     using (SqlEmailServiceContext configContext = new SqlEmailServiceContext(this.nameOrConnectionString))
     {
         Guid           itemID = new Guid(id);
         EmailQueueItem item   = configContext.EmailQueueItems.FirstOrDefault(x => x.ID == itemID && x.SendDate == null);
         item.ErrorMessage = message.ErrorMessage;
         item.RetryAttempt = message.RetryAttempt;
         item.SendDate     = message.SendDate;
         configContext.SaveChanges();
     }
 }
        public async Task Test_ForgotPassword_Succeeds()
        {
            // Arrange
            const int IpAddressInt = 0x2414188f;
            const string IpAddressString = "143.24.20.36";

            const string ConfirmEmailUrl = "https://some.url";

            // Set up HTTP context accessor
            var httpContextAccessor = TestHelpers.CreateHttpContextAccessor(IpAddressInt);

            // Set up user manager
            var mockUserManager = CreateMockUserManager(userIsConfirmed: true);

            // Set up email repository
            var otherUserEmail = new EmailQueueItem { To = "Other email address", Subject = "Reset password" };
            var otherSubjectEmail = new EmailQueueItem { To = EmailAddress, Subject = "Other subject" };

            var mockEmailRepository = new Mock<IEmailRepository>(MockBehavior.Strict);
            mockEmailRepository.Setup(e => e.AddToQueue(It.IsAny<ResetPassword>()));
            mockEmailRepository
                .Setup(e => e.GetRecent())
                .Returns(new[] { otherUserEmail, otherSubjectEmail });

            // Set up model
            var httpContext = new DefaultHttpContext();

            var mockUrlHelper = CreateMockUrlHelper(httpContext, ConfirmEmailUrl);

            var model = new ForgotPasswordModel(
                httpContextAccessor,
                mockUserManager.Object,
                mockEmailRepository.Object)
            {
                PageContext = { HttpContext = httpContext },
                Input = new ForgotPasswordModel.InputModel { Email = EmailAddress },
                Url = mockUrlHelper.Object
            };

            // Act
            var result = await model.OnPostAsync();

            // Assert
            Assert.IsType<RedirectToPageResult>(result);
            Assert.Equal("./ForgotPasswordConfirmation", ((RedirectToPageResult)result).PageName);

            mockEmailRepository.Verify(p => p.AddToQueue(
                    It.Is<ResetPassword>(e =>
                        e.To == EmailAddress &&
                        e.HtmlBody.Contains(ConfirmEmailUrl, StringComparison.Ordinal) &&
                        e.HtmlBody.Contains(IpAddressString, StringComparison.OrdinalIgnoreCase))),
                Times.Once);
        }
        public async Task Send(IEnumerable<string> to, IEnumerable<string> cc, string @from, string emailTemplateId, Dictionary<string, string> mergeValues)
        {
            EmailQueueItem item = new EmailQueueItem
            {
                Cc = new List<string>(cc),
                EmailTemplateId = emailTemplateId,
                From = from,
                MergeData = mergeValues,
                To = new List<string>(to)
            };

            await _queue.EnqueueAsync(item);
        }
        public async Task Send(IEnumerable<string> to, IEnumerable<string> cc, string @from, string subject, string htmlBody, string textBody)
        {
            EmailQueueItem item = new EmailQueueItem
            {
                Cc = new List<string>(cc),
                From = from,
                To = new List<string>(to),
                Subject = subject,
                HtmlBody = htmlBody,
                TextBody = textBody
            };

            await _queue.EnqueueAsync(item);
        }
Esempio n. 13
0
 public string Save(EmailMessage message)
 {
     using (SqlEmailServiceContext configContext = new SqlEmailServiceContext(this.nameOrConnectionString))
     {
         EmailQueueItem item = new EmailQueueItem();
         item.ID           = Guid.NewGuid().ToCombGuid();
         item.ErrorMessage = string.Empty;
         item.CreateDate   = DateTime.UtcNow;
         item.Message      = EmailMessage.Serialize(message);
         configContext.EmailQueueItems.Add(item);
         configContext.SaveChanges();
         return(item.ID.ToStringValue());
     }
 }
        public async Task SendAsync(IEnumerable<string> to, IEnumerable<string> cc, string @from, string subject, string htmlBody, string textBody)
        {
            _logger?.Verbose("EmailQueueDispatcher - SendAsync with subject/body - {0}", subject);

            EmailQueueItem item = new EmailQueueItem
            {
                Cc = new List<string>(cc),
                From = from,
                To = new List<string>(to),
                Subject = subject,
                HtmlBody = htmlBody,
                TextBody = textBody
            };

            await _queue.EnqueueAsync(item);
        }
Esempio n. 15
0
        public void ValidatorMustCaptureInvalidEmail()
        {
            var emailQueueItem = new EmailQueueItem
            {
                Sender   = "test",
                Receiver = "*****@*****.**",
                Subject  = "Title",
                Body     = "Body"
            };
            var validator = new EmailQueueItemValidator();
            var results   = validator.Validate(emailQueueItem);

            Assert.False(results.IsValid);
            Assert.StrictEqual("Sender", results.Errors[0].PropertyName);
            Assert.StrictEqual("'Sender' is not a valid email address.", results.Errors[0].ErrorMessage);
        }
        public async Task SendAsync(IEnumerable<string> to, IEnumerable<string> cc, string @from, string emailTemplateId, Dictionary<string, string> mergeValues, TemplateSyntaxEnum templateSyntax = TemplateSyntaxEnum.Razor)
        {
            _logger?.Verbose("EmailQueueDispatcher - SendAsync with template - {0}", emailTemplateId);

            EmailQueueItem item = new EmailQueueItem
            {
                Cc = new List<string>(cc),
                EmailTemplateId = emailTemplateId,
                From = from,
                MergeData = mergeValues,
                To = new List<string>(to),
                TemplateSyntax = templateSyntax
            };

            await _queue.EnqueueAsync(item);
        }
Esempio n. 17
0
        /// <summary>
        /// Enqueues a set of MailMessages to be sent
        /// </summary>
        /// <param name="messages"></param>
        public void EnqueueMessages(IEnumerable <MailMessage> messages)
        {
            if (messages == null)
            {
                throw new ArgumentNullException("messages");
            }

            TroutLog.Log.Info(string.Format("Beginning queuing of {0} messages", messages.Count()));

            List <Tuple <EmailQueueItem, MailMessage> > createdMessages = new List <Tuple <EmailQueueItem, MailMessage> >();

            foreach (var message in messages.Where(m => m != null))
            {
                var emailQueueItem = new EmailQueueItem()
                {
                    To              = message.To.ToString(),
                    Cc              = message.CC.ToString(),
                    Bcc             = message.Bcc.ToString(),
                    Subject         = message.Subject,
                    Body            = message.Body,
                    CreateDate      = DateTime.Now,
                    IsSent          = false,
                    NumberTries     = 0,
                    LastTryDate     = null,
                    SendDate        = null,
                    IsBodyHtml      = true,
                    AttachmentCount = (byte)message.Attachments.Count
                };

                createdMessages.Add(new Tuple <EmailQueueItem, MailMessage>(emailQueueItem, message));

                Repository.Add(emailQueueItem);
            }

            Repository.SaveChanges();

            foreach (var createdMessage in createdMessages)
            {
                if (createdMessage.Item1.AttachmentCount > 0)
                {
                    AttachmentFileSystem.SaveAttachments(createdMessage.Item1, createdMessage.Item2);
                }

                TroutLog.Log.Info(string.Format("{0} was queued", createdMessage.Item1.ID));
            }
        }
        /// <summary>
        /// Sends an email to the specified email(s) using this template and the merge data provided.
        /// Use comma to separate multiple emails.
        /// </summary>
        public void Send(string to, object mergeData, Action<EmailQueueItem> customise = null)
        {
            if (mergeData == null) throw new ArgumentNullException("mergeData");
            if (to.IsEmpty()) throw new ArgumentNullException("to");

            var message = new EmailQueueItem
            {
                Html = true,
                Subject = this.MergeSubject(mergeData),
                Body = this.MergeBody(mergeData),
                To = to,
            };

            if (customise != null) customise(message);

            Database.Save(message);
        }
Esempio n. 19
0
        protected override bool ParseArguments(string[] args)
        {
            OptionSet optionSet = new OptionSet().Add("id=", (int v) => EmailID = v);

            try
            {
                optionSet.Parse(args);
            }
            catch (OptionException)
            {
                Console.WriteLine("Error");
                return(false);
            }

            Email = Repository.First(e => e.ID == EmailID);

            return(Email != null);
        }
Esempio n. 20
0
        public EmailMessage Get(string id)
        {
            using (SqlEmailServiceContext configContext = new SqlEmailServiceContext(this.nameOrConnectionString))
            {
                Guid           itemID = new Guid(id);
                EmailQueueItem item   = configContext.EmailQueueItems.FirstOrDefault(x => x.ID == itemID && x.SendDate == null);

                if (item != null)
                {
                    EmailMessage message = EmailMessage.Deserialize(item.Message);
                    message.ErrorMessage = item.ErrorMessage;
                    message.SendDate     = item.SendDate;
                    message.RetryAttempt = item.RetryAttempt;
                    return(message);
                }
            }

            return(null);
        }
Esempio n. 21
0
        private static MailMessage CreateEmailMessageFromQueue(EmailQueueItem email)
        {
            var message = new MailMessage
            {
                From         = new MailAddress(email.From),
                Priority     = (MailPriority)email.Priority,
                IsBodyHtml   = email.IsBodyHtml,
                Subject      = email.Subject,
                Body         = email.Body,
                BodyEncoding = email.BodyEncoding
            };

            var toArray = email.To.Split(';');

            foreach (var t in toArray)
            {
                message.To.Add(t);
            }

            return(message);
        }
Esempio n. 22
0
        public void PopulateHeadersToHtmlEmail(EmailQueueItem email, string to, string[] cc, string[] bcc)
        {
            email.IsBodyHtml = true;
            var bodyStyle =
                "bgcolor=\"#F8F8F8\" style=\"font-variant: normal; font-weight: normal; font-size: 12px; margin: 0; background-repeat: repeat-x; background-color: #F8F8F8; line-height: 17px; font-family: 'Lucida Grande' , 'Lucida Sans Unicode', Verdana, sans-serif; padding: 0; text-align: center;  font-style: normal;\"";

            email.Body =
                $"<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" /></head><body {bodyStyle}>{FormatEmail(email.Body.Trim())}</body></html>";

            if (!string.IsNullOrEmpty(to))
            {
                email.To = to;
            }

            if (cc != null)
            {
                email.Cc = cc.ToDelimitedString(",");
            }

            if (bcc != null)
            {
                email.Bcc = bcc.ToDelimitedString(",");
            }
        }
Esempio n. 23
0
        public void PopulateHeaders(EmailQueueItem email, string to, string[] cc, string[] bcc, bool isHtml)
        {
            if (isHtml)
            {
                email.IsBodyHtml = true;
                email.Body       =
                    $"<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" /></head><body>{FormatPlainTextAsHtml(email.Body).Trim()}</body></html>";
            }

            if (!string.IsNullOrEmpty(to))
            {
                email.To = to;
            }

            if (cc != null)
            {
                email.Cc = cc.ToDelimitedString(",");
            }

            if (bcc != null)
            {
                email.Bcc = bcc.ToDelimitedString(",");
            }
        }
        /// <summary>
        /// Sends an email to all the specified users using this template and the merge data provided.
        /// </summary>
        public void Send(IEnumerable<User> toUsers, object mergeData, Action<EmailQueueItem> customise = null)
        {
            if (mergeData == null) throw new ArgumentNullException("mergeData");
            if (toUsers.None()) throw new ArgumentNullException("toUsers");

            var emails = new List<EmailQueueItem>();

            foreach (var email in toUsers.Select(u => u.Email))
            {
                var message = new EmailQueueItem
                {
                    Html = true,
                    Subject = this.MergeSubject(mergeData),
                    Body = this.MergeBody(mergeData),
                    To = email,
                };

                if (customise != null) customise(message);

                emails.Add(message);
            }

            Database.Save(emails);
        }
Esempio n. 25
0
 public Attachment[] GetAttachments(EmailQueueItem item)
 {
     return(Attachments.ContainsKey(item) ? Attachments[item] : new Attachment[0]);
 }
Esempio n. 26
0
 public void SaveAttachments(EmailQueueItem item, MailMessage mailMessage)
 {
     Attachments[item] = mailMessage.Attachments.ToArray();
 }
Esempio n. 27
0
        public static async Task Test_SendPending()
        {
            // Arrange
            var unsentEmail = new EmailQueueItem
            {
                To            = "[email protected]",
                Subject       = "Unsent email subject",
                HtmlBody      = "<p>Unsent email body</p>",
                PlainTextBody = "Unsent email body"
            };

            var otherUnsentEmail = new EmailQueueItem
            {
                To            = "[email protected]",
                Subject       = "Other unsent email subject",
                HtmlBody      = "<p>Other unsent email body</p>",
                PlainTextBody = "Other unsent email body"
            };

            var unsentEmails = new[] { unsentEmail, otherUnsentEmail };

            var mockEmailRepository = new Mock <IEmailRepository>(MockBehavior.Strict);

            mockEmailRepository
            .Setup(r => r.GetUnsent())
            .Returns(unsentEmails);
            mockEmailRepository
            .Setup(r => r.MarkAsSent(It.IsAny <EmailQueueItem>()));

            var disabledMockEmailSender = new Mock <IEmailSender>(MockBehavior.Strict);

            disabledMockEmailSender
            .SetupGet(s => s.CanSend)
            .Returns(false);

            var enabledMockEmailSender = new Mock <IEmailSender>(MockBehavior.Strict);

            enabledMockEmailSender
            .SetupGet(s => s.CanSend)
            .Returns(true);
            enabledMockEmailSender
            .Setup(s => s.Send(It.IsAny <IEmailTemplate>()))
            .Returns(Task.CompletedTask);

            // Act
            var emailProcessor = new EmailProcessor(
                mockEmailRepository.Object,
                new[] { disabledMockEmailSender.Object, enabledMockEmailSender.Object },
                Mock.Of <ILogger <EmailProcessor> >());

            await emailProcessor.SendPending();

            // Assert
            foreach (var emailQueueItem in unsentEmails)
            {
                enabledMockEmailSender.Verify(
                    s => s.Send(It.Is <IEmailTemplate>(e =>
                                                       e.To == emailQueueItem.To &&
                                                       e.Subject == emailQueueItem.Subject &&
                                                       e.HtmlBody == emailQueueItem.HtmlBody &&
                                                       e.PlainTextBody == emailQueueItem.PlainTextBody)),
                    Times.Once);

                mockEmailRepository.Verify(
                    r => r.MarkAsSent(emailQueueItem),
                    Times.Once);
            }
        }
 private string GetAttachmentDirectory(EmailQueueItem item, int attachmentIndex)
 {
     return(string.Format("{0}\\{1}a\\",
                          GetAttachmentDirectory(item),
                          attachmentIndex));
 }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="emailQueueItem"></param>
 /// <param name="message"></param>
 public DequeueListItem(EmailQueueItem emailQueueItem, MailMessage message)
 {
     EmailQueueItem = emailQueueItem;
     Message        = message;
 }
 private string GetAttachmentFileName(EmailQueueItem item, int attachmentIndex, Attachment attachment)
 {
     return(string.Format("{0}\\{1}",
                          GetAttachmentDirectory(item, attachmentIndex),
                          attachment.Name));
 }
Esempio n. 31
0
        public async Task RunAsync([QueueTrigger("email-items", Connection = "EmailServiceStorageCS")] EmailQueueItem emailQueueItem,
                                   [DurableClient] IDurableEntityClient client)
        {
            var stopWatch = Stopwatch.StartNew();

            using (SentrySdk.Init(_configOptions.Value.Sentry.Dsn))
            {
                var entityId = new EntityId(nameof(EmailProvidersStatus), "emailproviderstatus");
                var entity   = await client.ReadEntityStateAsync <EmailProvidersStatus>(entityId);

                await client.SignalEntityAsync <IEmailProvidersStatus>(entityId, s => s.Init());

                string providerToUse;
                // Entity doesn't exist yet, take the first supported provider
                if (!entity.EntityExists)
                {
                    providerToUse = _configOptions.Value.EmailProvidersSettings.SupportedProviders.FirstOrDefault();
                }
                else
                {
                    providerToUse = await entity.EntityState.Get();
                }

                if (string.IsNullOrEmpty(providerToUse))
                {
                    throw new Exception("No Email Providers were found, maybe all providers are disabled because there are unhealthy!. Using retries..");
                }
                using (LogContext.PushProperty("EmailProvider", providerToUse))
                    using (LogContext.PushProperty("Receiver", emailQueueItem.Receiver))
                    {
                        try
                        {
                            var validator         = new EmailQueueItemValidator();
                            var validationResults = await validator.ValidateAsync(emailQueueItem);

                            if (!validationResults.IsValid)
                            {
                                var errorMessage = validationResults.Errors
                                                   .Select(ve => $"{ve.PropertyName} {ve.ErrorMessage}")
                                                   .Aggregate("", (acc, curr) => $"{acc}\n{curr}");
                                _logger.LogError(errorMessage, emailQueueItem);
                                _logger.LogError("The provided queue item is invalid and will be skipped");
                            }
                            else
                            {
                                await _emailProviders[providerToUse].SendEmail(emailQueueItem.Sender, emailQueueItem.Receiver, emailQueueItem.Subject, emailQueueItem.Body);
                            }
                        }
                        catch (Exception ex)
                        {
                            // Capture the exception and send it to Sentry, then rethrow it to retry executing it.
                            SentrySdk.CaptureException(ex);
                            await client.SignalEntityAsync(entityId, "AddFailure", new FailureRequest { ProviderName = providerToUse, HappenedAt = DateTimeOffset.UtcNow });

                            throw ex;
                        }
                        finally
                        {
                            stopWatch.Stop();
                            _logger.LogInformation($"The request processing time was {stopWatch.ElapsedMilliseconds}");
                            _logger.LogInformation($"C# Queue trigger function processed: {JsonConvert.SerializeObject(emailQueueItem)}");
                        }
                    }
            }
        }