/// <summary> /// Prepare paged queued email list model /// </summary> /// <param name="searchModel">Queued email search model</param> /// <returns> /// A task that represents the asynchronous operation /// The task result contains the queued email list model /// </returns> public virtual async Task <QueuedEmailListModel> PrepareQueuedEmailListModelAsync(QueuedEmailSearchModel searchModel) { if (searchModel == null) { throw new ArgumentNullException(nameof(searchModel)); } //get parameters to filter emails var startDateValue = !searchModel.SearchStartDate.HasValue ? null : (DateTime?)_dateTimeHelper.ConvertToUtcTime(searchModel.SearchStartDate.Value, await _dateTimeHelper.GetCurrentTimeZoneAsync()); var endDateValue = !searchModel.SearchEndDate.HasValue ? null : (DateTime?)_dateTimeHelper.ConvertToUtcTime(searchModel.SearchEndDate.Value, await _dateTimeHelper.GetCurrentTimeZoneAsync()).AddDays(1); //get queued emails var queuedEmails = await _queuedEmailService.SearchEmailsAsync(fromEmail : searchModel.SearchFromEmail, toEmail : searchModel.SearchToEmail, createdFromUtc : startDateValue, createdToUtc : endDateValue, loadNotSentItemsOnly : searchModel.SearchLoadNotSent, loadOnlyItemsToBeSent : false, maxSendTries : searchModel.SearchMaxSentTries, loadNewest : true, pageIndex : searchModel.Page - 1, pageSize : searchModel.PageSize); //prepare list model var model = await new QueuedEmailListModel().PrepareToGridAsync(searchModel, queuedEmails, () => { return(queuedEmails.SelectAwait(async queuedEmail => { //fill in model values from the entity var queuedEmailModel = queuedEmail.ToModel <QueuedEmailModel>(); //little performance optimization: ensure that "Body" is not returned queuedEmailModel.Body = string.Empty; //convert dates to the user time queuedEmailModel.CreatedOn = await _dateTimeHelper.ConvertToUserTimeAsync(queuedEmail.CreatedOnUtc, DateTimeKind.Utc); //fill in additional values (not existing in the entity) var emailAccount = await _emailAccountService.GetEmailAccountByIdAsync(queuedEmail.EmailAccountId); queuedEmailModel.EmailAccountName = GetEmailAccountName(emailAccount); queuedEmailModel.PriorityName = await _localizationService.GetLocalizedEnumAsync(queuedEmail.Priority); if (queuedEmail.DontSendBeforeDateUtc.HasValue) { queuedEmailModel.DontSendBeforeDate = await _dateTimeHelper .ConvertToUserTimeAsync(queuedEmail.DontSendBeforeDateUtc.Value, DateTimeKind.Utc); } if (queuedEmail.SentOnUtc.HasValue) { queuedEmailModel.SentOn = await _dateTimeHelper.ConvertToUserTimeAsync(queuedEmail.SentOnUtc.Value, DateTimeKind.Utc); } return queuedEmailModel; })); }); return(model); }
private async System.Threading.Tasks.Task SendAlertEmailAsync(int orderId, string exceptionMessage) { var failureEmail = _settings.FailureAlertEmail; if (!string.IsNullOrEmpty(failureEmail)) { var defaultEmailAddress = await _emailAccountService.GetEmailAccountByIdAsync( _emailAccountSettings.DefaultEmailAccountId ); var email = new QueuedEmail { Priority = QueuedEmailPriority.High, From = defaultEmailAddress.Email, FromName = defaultEmailAddress.DisplayName, To = failureEmail, Subject = $"ISAM Order Export Failed (#{orderId})", Body = $"More information:\n\n{exceptionMessage}", CreatedOnUtc = DateTime.UtcNow, EmailAccountId = defaultEmailAddress.Id, DontSendBeforeDateUtc = null }; await _queuedEmailService.InsertQueuedEmailAsync(email); } else { await _logger.WarningAsync("No failure alert email provided, will not provide alert notification."); } }
public async Task <IActionResult> DisplayContactUs(ContactUsModel model) { var resultModel = new ContactUsResultModel(); if (_captchaSettings.Enabled) { var gCaptchaResponseValue = model.GRecaptchaResponse; if (StringValues.IsNullOrEmpty(gCaptchaResponseValue)) { return(BadRequest()); } var response = _captchaHttpClient.ValidateCaptchaAsync(gCaptchaResponseValue).Result; if (!response.IsValid) { return(BadRequest()); } } var account = await _emailAccountService.GetEmailAccountByIdAsync(_emailAccountSettings.DefaultEmailAccountId); var ccEmails = new List <string>(_contactUsWidgetSettings.AdditionalEmails.Split(',')); var toAddress = ""; if (model.SelectedStore == "Website") { toAddress = _settings.ContactUsEmail ?? "*****@*****.**"; } else { var shop = _shopRepository.Table.Where(s => s.Name == model.SelectedStore).FirstOrDefault(); toAddress = _shopAbcRepository.Table.Where(sabc => sabc.ShopId == shop.Id).FirstOrDefault().AbcEmail; ccEmails.Add(_settings.ContactUsEmail); } var subject = "Customer " + model.Reason + "- " + model.SelectedStore + "/" + model.Name + " " + model.PhoneNumber; var body = string.Format( @"A request has been submitted with an inquiry from the Contact us page. <br/><br/> Customer Name: {0} <br/> Customer Email: {1} <br/> Customer Phone Number: {2} <br/> Store Location: {3} <br/> Comments: {4}", model.Name ?? "", model.Email ?? "", model.PhoneNumber ?? "", model.SelectedStore ?? "", model.Comments ?? ""); if (_settings.IsEmailSubmissionSkipped) { await _logger.WarningAsync($"AbcContactUs: Email submission skipped - body: {body}"); } else { await _emailSender.SendEmailAsync(account, subject, body, account.Email, account.DisplayName, toAddress, "", replyToAddress : model.Email, cc : ccEmails); } return(Content("")); }
/// <summary> /// moves old energy guides, product specs, and images to archive folders. Deletes pictures attached to deleted products /// </summary> /// <param name="backendConn">connection to the ISAM backend to check valid products</param> public async Task ArchiveProductContentAsync(IDbConnection backendConn) { var allowedItemNumbers = GetAllowedItemNumbers(backendConn); var archivedItemsSet = new HashSet <string>(); var ProcessedImageDirectory = $"{_importSettings.GetLocalPicturesDirectory()}"; ArchiveFiles(allowedItemNumbers, _importSettings.GetEnergyGuidePdfPath(), GetFileNames(_importSettings.GetEnergyGuidePdfPath()), ref archivedItemsSet); ArchiveFiles(allowedItemNumbers, _importSettings.GetSpecificationPdfPath(), GetFileNames(_importSettings.GetSpecificationPdfPath()), ref archivedItemsSet); ArchiveFiles(allowedItemNumbers, ProcessedImageDirectory, GetFileNames(ProcessedImageDirectory, "*_large.*"), ref archivedItemsSet, $"{_importSettings.GetLocalPicturesDirectory()}/Archive"); //deleting old pictures from archived products await _nopDbContext.ExecuteNonQueryAsync(_deleteArchivedProductPictures); var account = await _emailAccountService.GetEmailAccountByIdAsync(_emailAccountSettings.DefaultEmailAccountId); var ccEmails = new List <string>(); if (!string.IsNullOrEmpty(_importSettings.ArchiveTaskCCEmails)) { ccEmails.AddRange(_importSettings.ArchiveTaskCCEmails.Split(',')); } string body; bool hasArchivedItems = archivedItemsSet.Any(); if (hasArchivedItems) { body = "No items were archived"; } else { body = "Files from the following item numbers were archived:"; foreach (var itemNo in archivedItemsSet) { body += $"<br/>{itemNo}"; } } await _emailSender.SendEmailAsync(account, "Archive Task Complete", body, account.Email, account.DisplayName, "*****@*****.**", "", cc : ccEmails); if (hasArchivedItems) { await _logger.InformationAsync($"Archived items: {string.Join(",", archivedItemsSet)}"); } else { await _logger.InformationAsync("No archived items."); } }
/// <summary> /// Uninstall the plugin /// </summary> /// <returns>A task that represents the asynchronous operation</returns> public override async Task UninstallAsync() { //smtp accounts foreach (var store in await _storeService.GetAllStoresAsync()) { var key = $"{nameof(SendinblueSettings)}.{nameof(SendinblueSettings.EmailAccountId)}"; var emailAccountId = await _settingService.GetSettingByKeyAsync <int>(key, storeId : store.Id, loadSharedValueIfNotFound : true); var emailAccount = await _emailAccountService.GetEmailAccountByIdAsync(emailAccountId); if (emailAccount != null) { await _emailAccountService.DeleteEmailAccountAsync(emailAccount); } } //settings if (_widgetSettings.ActiveWidgetSystemNames.Contains(SendinblueDefaults.SystemName)) { _widgetSettings.ActiveWidgetSystemNames.Remove(SendinblueDefaults.SystemName); await _settingService.SaveSettingAsync(_widgetSettings); } await _settingService.DeleteSettingAsync <SendinblueSettings>(); //generic attributes foreach (var store in await _storeService.GetAllStoresAsync()) { var messageTemplates = await _messageTemplateService.GetAllMessageTemplatesAsync(store.Id); foreach (var messageTemplate in messageTemplates) { await _genericAttributeService.SaveAttributeAsync <int?>(messageTemplate, SendinblueDefaults.TemplateIdAttribute, null); } } //schedule task var task = await _scheduleTaskService.GetTaskByTypeAsync(SendinblueDefaults.SynchronizationTask); if (task != null) { await _scheduleTaskService.DeleteTaskAsync(task); } //locales await _localizationService.DeleteLocaleResourcesAsync("Plugins.Misc.Sendinblue"); await base.UninstallAsync(); }
/// <summary> /// Executes a task /// </summary> public virtual async System.Threading.Tasks.Task ExecuteAsync() { var maxTries = 3; var queuedEmails = await _queuedEmailService.SearchEmailsAsync(null, null, null, null, true, true, maxTries, false, 0, 500); foreach (var queuedEmail in queuedEmails) { var bcc = string.IsNullOrWhiteSpace(queuedEmail.Bcc) ? null : queuedEmail.Bcc.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); var cc = string.IsNullOrWhiteSpace(queuedEmail.CC) ? null : queuedEmail.CC.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); try { await _emailSender.SendEmailAsync(await _emailAccountService.GetEmailAccountByIdAsync(queuedEmail.EmailAccountId), queuedEmail.Subject, queuedEmail.Body, queuedEmail.From, queuedEmail.FromName, queuedEmail.To, queuedEmail.ToName, queuedEmail.ReplyTo, queuedEmail.ReplyToName, bcc, cc, queuedEmail.AttachmentFilePath, queuedEmail.AttachmentFileName, queuedEmail.AttachedDownloadId); queuedEmail.SentOnUtc = DateTime.UtcNow; } catch (Exception exc) { await _logger.ErrorAsync($"Error sending e-mail. {exc.Message}", exc); } finally { queuedEmail.SentTries += 1; await _queuedEmailService.UpdateQueuedEmailAsync(queuedEmail); } } }
/// <summary> /// Create a new SMTP client for a specific email account /// </summary> /// <param name="emailAccount">Email account to use. If null, then would be used EmailAccount by default</param> /// <returns> /// A task that represents the asynchronous operation /// The task result contains the an SMTP client that can be used to send email messages /// </returns> public virtual async Task <SmtpClient> BuildAsync(EmailAccount emailAccount = null) { if (emailAccount is null) { emailAccount = await _emailAccountService.GetEmailAccountByIdAsync(_emailAccountSettings.DefaultEmailAccountId) ?? throw new NopException("Email account could not be loaded"); } var client = new SmtpClient { ServerCertificateValidationCallback = ValidateServerCertificate }; try { await client.ConnectAsync( emailAccount.Host, emailAccount.Port, emailAccount.EnableSsl?SecureSocketOptions.SslOnConnect : SecureSocketOptions.StartTlsWhenAvailable); if (emailAccount.UseDefaultCredentials) { await client.AuthenticateAsync(CredentialCache.DefaultNetworkCredentials); } else if (!string.IsNullOrWhiteSpace(emailAccount.Username)) { await client.AuthenticateAsync(new NetworkCredential(emailAccount.Username, emailAccount.Password)); } return(client); } catch (Exception ex) { client.Dispose(); throw new NopException(ex.Message, ex); } }
/// <returns>A task that represents the asynchronous operation</returns> public virtual async Task <IActionResult> MarkAsDefaultEmail(int id) { if (!await _permissionService.AuthorizeAsync(StandardPermissionProvider.ManageEmailAccounts)) { return(AccessDeniedView()); } var defaultEmailAccount = await _emailAccountService.GetEmailAccountByIdAsync(id); if (defaultEmailAccount == null) { return(RedirectToAction("List")); } _emailAccountSettings.DefaultEmailAccountId = defaultEmailAccount.Id; await _settingService.SaveSettingAsync(_emailAccountSettings); return(RedirectToAction("List")); }
/// <summary> /// Prepare SendinblueModel /// </summary> /// <param name="model">Model</param> private async Task PrepareModelAsync(ConfigurationModel model) { //load settings for active store scope var storeId = await _storeContext.GetActiveStoreScopeConfigurationAsync(); var sendinblueSettings = await _settingService.LoadSettingAsync <SendinblueSettings>(storeId); //whether plugin is configured if (string.IsNullOrEmpty(sendinblueSettings.ApiKey)) { return; } //prepare common properties model.ActiveStoreScopeConfiguration = storeId; model.ApiKey = sendinblueSettings.ApiKey; model.ListId = sendinblueSettings.ListId; model.SmtpKey = sendinblueSettings.SmtpKey; model.SenderId = sendinblueSettings.SenderId; model.UseSmsNotifications = sendinblueSettings.UseSmsNotifications; model.SmsSenderName = sendinblueSettings.SmsSenderName; model.StoreOwnerPhoneNumber = sendinblueSettings.StoreOwnerPhoneNumber; model.UseMarketingAutomation = sendinblueSettings.UseMarketingAutomation; model.TrackingScript = sendinblueSettings.TrackingScript; model.HideGeneralBlock = await _genericAttributeService.GetAttributeAsync <bool>(await _workContext.GetCurrentCustomerAsync(), SendinblueDefaults.HideGeneralBlock); model.HideSynchronizationBlock = await _genericAttributeService.GetAttributeAsync <bool>(await _workContext.GetCurrentCustomerAsync(), SendinblueDefaults.HideSynchronizationBlock); model.HideTransactionalBlock = await _genericAttributeService.GetAttributeAsync <bool>(await _workContext.GetCurrentCustomerAsync(), SendinblueDefaults.HideTransactionalBlock); model.HideSmsBlock = await _genericAttributeService.GetAttributeAsync <bool>(await _workContext.GetCurrentCustomerAsync(), SendinblueDefaults.HideSmsBlock); model.HideMarketingAutomationBlock = await _genericAttributeService.GetAttributeAsync <bool>(await _workContext.GetCurrentCustomerAsync(), SendinblueDefaults.HideMarketingAutomationBlock); //prepare nested search models model.MessageTemplateSearchModel.SetGridPageSize(); model.SmsSearchModel.SetGridPageSize(); //prepare add SMS model model.AddSms.AvailablePhoneTypes.Add(new SelectListItem(await _localizationService.GetResourceAsync("Plugins.Misc.Sendinblue.MyPhone"), "0")); model.AddSms.AvailablePhoneTypes.Add(new SelectListItem(await _localizationService.GetResourceAsync("Plugins.Misc.Sendinblue.CustomerPhone"), "1")); model.AddSms.AvailablePhoneTypes.Add(new SelectListItem(await _localizationService.GetResourceAsync("Plugins.Misc.Sendinblue.BillingAddressPhone"), "2")); model.AddSms.DefaultSelectedPhoneTypeId = model.AddSms.AvailablePhoneTypes.First().Value; var stores = await _storeService.GetAllStoresAsync(); var messageTemplates = await _messageTemplateService.GetAllMessageTemplatesAsync(storeId); model.AddSms.AvailableMessages = await messageTemplates.SelectAwait(async messageTemplate => { var name = messageTemplate.Name; if (storeId == 0 && messageTemplate.LimitedToStores) { var storeIds = await _storeMappingService.GetStoresIdsWithAccessAsync(messageTemplate); var storeNames = stores.Where(store => storeIds.Contains(store.Id)).Select(store => store.Name); name = $"{name} ({string.Join(',', storeNames)})"; } return(new SelectListItem(name, messageTemplate.Id.ToString())); }).ToListAsync(); var defaultSelectedMessage = model.AddSms.AvailableMessages.FirstOrDefault(); model.AddSms.DefaultSelectedMessageId = defaultSelectedMessage?.Value ?? "0"; //check whether email account exists if (sendinblueSettings.UseSmtp && await _emailAccountService.GetEmailAccountByIdAsync(sendinblueSettings.EmailAccountId) != null) { model.UseSmtp = sendinblueSettings.UseSmtp; } //get account info var(accountInfo, marketingAutomationEnabled, maKey, accountErrors) = await _sendinblueEmailManager.GetAccountInfoAsync(); model.AccountInfo = accountInfo; model.MarketingAutomationKey = maKey; model.MarketingAutomationDisabled = !marketingAutomationEnabled; if (!string.IsNullOrEmpty(accountErrors)) { _notificationService.ErrorNotification($"{SendinblueDefaults.NotificationMessage} {accountErrors}"); } //prepare overridable settings if (storeId > 0) { model.ListId_OverrideForStore = await _settingService.SettingExistsAsync(sendinblueSettings, settings => settings.ListId, storeId); model.UseSmtp_OverrideForStore = await _settingService.SettingExistsAsync(sendinblueSettings, settings => settings.UseSmtp, storeId); model.SenderId_OverrideForStore = await _settingService.SettingExistsAsync(sendinblueSettings, settings => settings.SenderId, storeId); model.UseSmsNotifications_OverrideForStore = await _settingService.SettingExistsAsync(sendinblueSettings, settings => settings.UseSmsNotifications, storeId); model.SmsSenderName_OverrideForStore = await _settingService.SettingExistsAsync(sendinblueSettings, settings => settings.SmsSenderName, storeId); model.UseMarketingAutomation_OverrideForStore = await _settingService.SettingExistsAsync(sendinblueSettings, settings => settings.UseMarketingAutomation, storeId); } //check SMTP status var(smtpEnabled, smtpErrors) = await _sendinblueEmailManager.SmtpIsEnabledAsync(); if (!string.IsNullOrEmpty(smtpErrors)) { _notificationService.ErrorNotification($"{SendinblueDefaults.NotificationMessage} {smtpErrors}"); } //get available contact lists to synchronize var(lists, listsErrors) = await _sendinblueEmailManager.GetListsAsync(); model.AvailableLists = lists.Select(list => new SelectListItem(list.Name, list.Id)).ToList(); model.AvailableLists.Insert(0, new SelectListItem("Select list", "0")); if (!string.IsNullOrEmpty(listsErrors)) { _notificationService.ErrorNotification($"{SendinblueDefaults.NotificationMessage} {listsErrors}"); } //get available senders of emails from account var(senders, sendersErrors) = await _sendinblueEmailManager.GetSendersAsync(); model.AvailableSenders = senders.Select(list => new SelectListItem(list.Name, list.Id)).ToList(); model.AvailableSenders.Insert(0, new SelectListItem("Select sender", "0")); if (!string.IsNullOrEmpty(sendersErrors)) { _notificationService.ErrorNotification($"{SendinblueDefaults.NotificationMessage} {sendersErrors}"); } //get allowed tokens model.AllowedTokens = string.Join(", ", await _messageTokenProvider.GetListOfAllowedTokensAsync()); //create attributes in account var attributesErrors = await _sendinblueEmailManager.PrepareAttributesAsync(); if (!string.IsNullOrEmpty(attributesErrors)) { _notificationService.ErrorNotification($"{SendinblueDefaults.NotificationMessage} {attributesErrors}"); } }
/// <summary> /// Send email notification by message template /// </summary> /// <param name="messageTemplate">Message template</param> /// <param name="emailAccount">Email account</param> /// <param name="tokens">Tokens</param> /// <param name="toEmailAddress">Recipient email address</param> /// <param name="toName">Recipient name</param> /// <param name="attachmentFilePath">Attachment file path</param> /// <param name="attachmentFileName">Attachment file name</param> /// <param name="replyToEmailAddress">"Reply to" email</param> /// <param name="replyToName">"Reply to" name</param> /// <param name="fromEmail">Sender email. If specified, then it overrides passed "emailAccount" details</param> /// <param name="fromName">Sender name. If specified, then it overrides passed "emailAccount" details</param> /// <param name="subject">Subject. If specified, then it overrides subject of a message template</param> /// <returns> /// A task that represents the asynchronous operation /// The task result contains the queued email identifier /// </returns> private async Task <int?> SendEmailNotificationAsync(MessageTemplate messageTemplate, EmailAccount emailAccount, IEnumerable <Token> tokens, string toEmailAddress, string toName, string attachmentFilePath = null, string attachmentFileName = null, string replyToEmailAddress = null, string replyToName = null, string fromEmail = null, string fromName = null, string subject = null) { //get plugin settings var storeId = (int?)tokens.FirstOrDefault(token => token.Key == "Store.Id")?.Value; var sendinblueSettings = await _settingService.LoadSettingAsync <SendinblueSettings>(storeId ?? 0); //ensure email notifications enabled if (!sendinblueSettings.UseSmtp) { return(null); } //whether to send email by the passed message template var templateId = await _genericAttributeService.GetAttributeAsync <int?>(messageTemplate, SendinblueDefaults.TemplateIdAttribute); var sendEmailForThisMessageTemplate = templateId.HasValue; if (!sendEmailForThisMessageTemplate) { return(null); } //get the specified email account from settings emailAccount = await _emailAccountService.GetEmailAccountByIdAsync(sendinblueSettings.EmailAccountId) ?? emailAccount; //get an email from the template var email = await _sendinblueEmailManager.GetQueuedEmailFromTemplateAsync(templateId.Value) ?? throw new NopException($"There is no template with id {templateId}"); //replace body and subject tokens if (string.IsNullOrEmpty(subject)) { subject = email.Subject; } if (!string.IsNullOrEmpty(subject)) { email.Subject = _tokenizer.Replace(subject, tokens, false); } if (!string.IsNullOrEmpty(email.Body)) { email.Body = _tokenizer.Replace(email.Body, tokens, true); } //set email parameters email.Priority = QueuedEmailPriority.High; email.From = !string.IsNullOrEmpty(fromEmail) ? fromEmail : email.From; email.FromName = !string.IsNullOrEmpty(fromName) ? fromName : email.FromName; email.To = toEmailAddress; email.ToName = CommonHelper.EnsureMaximumLength(toName, 300); email.ReplyTo = replyToEmailAddress; email.ReplyToName = replyToName; email.CC = string.Empty; email.Bcc = messageTemplate.BccEmailAddresses; email.AttachmentFilePath = attachmentFilePath; email.AttachmentFileName = attachmentFileName; email.AttachedDownloadId = messageTemplate.AttachedDownloadId; email.CreatedOnUtc = DateTime.UtcNow; email.EmailAccountId = emailAccount.Id; email.DontSendBeforeDateUtc = messageTemplate.DelayBeforeSend.HasValue ? (DateTime?)(DateTime.UtcNow + TimeSpan.FromHours(messageTemplate.DelayPeriod.ToHours(messageTemplate.DelayBeforeSend.Value))) : null; //queue email await _queuedEmailService.InsertQueuedEmailAsync(email); return(email.Id); }
protected virtual async Task <EmailAccount> GetEmailAccountAsync(int emailAccountId) { return(await _emailAccountService.GetEmailAccountByIdAsync(emailAccountId) ?? await _emailAccountService.GetEmailAccountByIdAsync(_emailAccountSettings.DefaultEmailAccountId) ?? throw new NopException("Email account could not be loaded")); }