diff --git a/Oqtane.Server/Infrastructure/Jobs/NotificationJob.cs b/Oqtane.Server/Infrastructure/Jobs/NotificationJob.cs index 7771d8c1..9d320bd9 100644 --- a/Oqtane.Server/Infrastructure/Jobs/NotificationJob.cs +++ b/Oqtane.Server/Infrastructure/Jobs/NotificationJob.cs @@ -42,220 +42,237 @@ namespace Oqtane.Infrastructure { log += "Processing Notifications For Site: " + site.Name + "
"; - // get site settings - var settings = settingRepository.GetSettings(EntityNames.Site, site.SiteId, EntityNames.Host, -1); - - if (!site.IsDeleted && settingRepository.GetSettingValue(settings, "SMTPEnabled", "True") == "True") + List notifications = notificationRepository.GetNotifications(site.SiteId, -1, -1).ToList(); + if (notifications.Count > 0) { - bool valid = true; - if (settingRepository.GetSettingValue(settings, "SMTPAuthentication", "Basic") == "Basic") + // get site settings + var settings = settingRepository.GetSettings(EntityNames.Site, site.SiteId, EntityNames.Host, -1); + + if (!site.IsDeleted && settingRepository.GetSettingValue(settings, "SMTPEnabled", "True") == "True") { - // basic - if (settingRepository.GetSettingValue(settings, "SMTPHost", "") == "" || - settingRepository.GetSettingValue(settings, "SMTPPort", "") == "" || - settingRepository.GetSettingValue(settings, "SMTPSender", "") == "") - { - log += "SMTP Not Configured Properly In Site Settings - Host, Port, And Sender Are All Required" + "
"; - valid = false; - } - } - else - { - // oauth - if (settingRepository.GetSettingValue(settings, "SMTPHost", "") == "" || - settingRepository.GetSettingValue(settings, "SMTPPort", "") == "" || - settingRepository.GetSettingValue(settings, "SMTPAuthority", "") == "" || - settingRepository.GetSettingValue(settings, "SMTPClientId", "") == "" || - settingRepository.GetSettingValue(settings, "SMTPClientSecret", "") == "" || - settingRepository.GetSettingValue(settings, "SMTPScopes", "") == "" || - settingRepository.GetSettingValue(settings, "SMTPSender", "") == "") - { - log += "SMTP Not Configured Properly In Site Settings - Host, Port, Authority, Client ID, Client Secret, Scopes, And Sender Are All Required" + "
"; - valid = false; - } - } - - - if (valid) - { - // construct SMTP Client - using var client = new SmtpClient(); - - var secureSocketOptions = SecureSocketOptions.Auto; - switch (settingRepository.GetSettingValue(settings, "SMTPSSL", "Auto")) - { - case "None": - secureSocketOptions = SecureSocketOptions.None; - break; - case "Auto": - secureSocketOptions = SecureSocketOptions.Auto; - break; - case "StartTls": - secureSocketOptions = SecureSocketOptions.StartTls; - break; - case "SslOnConnect": - case "True": // legacy setting value - secureSocketOptions = SecureSocketOptions.SslOnConnect; - break; - case "StartTlsWhenAvailable": - case "False": // legacy setting value - secureSocketOptions = SecureSocketOptions.StartTlsWhenAvailable; - break; - } - - await client.ConnectAsync(settingRepository.GetSettingValue(settings, "SMTPHost", ""), - int.Parse(settingRepository.GetSettingValue(settings, "SMTPPort", "")), - secureSocketOptions); - + bool valid = true; if (settingRepository.GetSettingValue(settings, "SMTPAuthentication", "Basic") == "Basic") { - // it is possible to use basic without any authentication (not recommended) - if (settingRepository.GetSettingValue(settings, "SMTPUsername", "") != "" && settingRepository.GetSettingValue(settings, "SMTPPassword", "") != "") + // basic + if (settingRepository.GetSettingValue(settings, "SMTPHost", "") == "" || + settingRepository.GetSettingValue(settings, "SMTPPort", "") == "" || + settingRepository.GetSettingValue(settings, "SMTPSender", "") == "") { - await client.AuthenticateAsync(settingRepository.GetSettingValue(settings, "SMTPUsername", ""), - settingRepository.GetSettingValue(settings, "SMTPPassword", "")); + log += "SMTP Not Configured Properly In Site Settings - Host, Port, And Sender Are All Required" + "
"; + valid = false; } } else { - // oauth authentication - var confidentialClientApplication = ConfidentialClientApplicationBuilder.Create(settingRepository.GetSettingValue(settings, "SMTPClientId", "")) - .WithAuthority(settingRepository.GetSettingValue(settings, "SMTPAuthority", "")) - .WithClientSecret(settingRepository.GetSettingValue(settings, "SMTPClientSecret", "")) - .Build(); - try + // oauth + if (settingRepository.GetSettingValue(settings, "SMTPHost", "") == "" || + settingRepository.GetSettingValue(settings, "SMTPPort", "") == "" || + settingRepository.GetSettingValue(settings, "SMTPAuthority", "") == "" || + settingRepository.GetSettingValue(settings, "SMTPClientId", "") == "" || + settingRepository.GetSettingValue(settings, "SMTPClientSecret", "") == "" || + settingRepository.GetSettingValue(settings, "SMTPScopes", "") == "" || + settingRepository.GetSettingValue(settings, "SMTPSender", "") == "") { - var result = await confidentialClientApplication.AcquireTokenForClient(settingRepository.GetSettingValue(settings, "SMTPScopes", "").Split(',')).ExecuteAsync(); - var oauth2 = new SaslMechanismOAuth2(settingRepository.GetSettingValue(settings, "SMTPSender", ""), result.AccessToken); - await client.AuthenticateAsync(oauth2); - } - catch (Exception ex) - { - log += "SMTP Not Configured Properly In Site Settings - OAuth Token Could Not Be Retrieved From Authority - " + ex.Message + "
"; + log += "SMTP Not Configured Properly In Site Settings - Host, Port, Authority, Client ID, Client Secret, Scopes, And Sender Are All Required" + "
"; valid = false; } } if (valid) { - // iterate through undelivered notifications - int sent = 0; - List notifications = notificationRepository.GetNotifications(site.SiteId, -1, -1).ToList(); - foreach (Notification notification in notifications) + // construct SMTP Client + using var client = new SmtpClient(); + + try { - var fromEmail = notification.FromEmail ?? ""; - var fromName = notification.FromDisplayName ?? ""; - var toEmail = notification.ToEmail ?? ""; - var toName = notification.ToDisplayName ?? ""; - - // get sender and receiver information from user information if available - if ((string.IsNullOrEmpty(fromEmail) || string.IsNullOrEmpty(fromName)) && notification.FromUserId != null) + var secureSocketOptions = SecureSocketOptions.Auto; + switch (settingRepository.GetSettingValue(settings, "SMTPSSL", "Auto")) { - var user = userRepository.GetUser(notification.FromUserId.Value); - if (user != null) + case "None": + secureSocketOptions = SecureSocketOptions.None; + break; + case "Auto": + secureSocketOptions = SecureSocketOptions.Auto; + break; + case "StartTls": + secureSocketOptions = SecureSocketOptions.StartTls; + break; + case "SslOnConnect": + case "True": // legacy setting value + secureSocketOptions = SecureSocketOptions.SslOnConnect; + break; + case "StartTlsWhenAvailable": + case "False": // legacy setting value + secureSocketOptions = SecureSocketOptions.StartTlsWhenAvailable; + break; + } + + await client.ConnectAsync(settingRepository.GetSettingValue(settings, "SMTPHost", ""), + int.Parse(settingRepository.GetSettingValue(settings, "SMTPPort", "")), + secureSocketOptions); + } + catch (Exception ex) + { + log += "SMTP Not Configured Properly In Site Settings - Could Not Connect To SMTP Server - " + ex.Message + "
"; + valid = false; + } + + if (valid) + { + if (settingRepository.GetSettingValue(settings, "SMTPAuthentication", "Basic") == "Basic") + { + // it is possible to use basic without any authentication (not recommended) + if (settingRepository.GetSettingValue(settings, "SMTPUsername", "") != "" && settingRepository.GetSettingValue(settings, "SMTPPassword", "") != "") { - fromEmail = string.IsNullOrEmpty(fromEmail) ? user.Email ?? "" : fromEmail; - fromName = string.IsNullOrEmpty(fromName) ? user.DisplayName ?? "" : fromName; + await client.AuthenticateAsync(settingRepository.GetSettingValue(settings, "SMTPUsername", ""), + settingRepository.GetSettingValue(settings, "SMTPPassword", "")); } } - if ((string.IsNullOrEmpty(toEmail) || string.IsNullOrEmpty(toName)) && notification.ToUserId != null) - { - var user = userRepository.GetUser(notification.ToUserId.Value); - if (user != null) - { - toEmail = string.IsNullOrEmpty(toEmail) ? user.Email ?? "" : toEmail; - toName = string.IsNullOrEmpty(toName) ? user.DisplayName ?? "" : toName; - } - } - - // create mailbox addresses - MailboxAddress to = null; - MailboxAddress from = null; - var mailboxAddressValidationError = ""; - - // sender - if (settingRepository.GetSettingValue(settings, "SMTPRelay", "False") != "True") - { - fromEmail = settingRepository.GetSettingValue(settings, "SMTPSender", ""); - fromName = string.IsNullOrEmpty(fromName) ? site.Name : fromName; - } - if (MailboxAddress.TryParse(fromEmail, out from)) - { - from.Name = fromName; - } else { - - mailboxAddressValidationError += $" Invalid Sender: {fromName} <{fromEmail}>"; - } - - // recipient - if (MailboxAddress.TryParse(toEmail, out to)) - { - to.Name = toName; - } - else - { - mailboxAddressValidationError += $" Invalid Recipient: {toName} <{toEmail}>"; - } - - // if mailbox addresses are valid - if (from != null && to != null) - { - // create mail message - MimeMessage mailMessage = new MimeMessage(); - mailMessage.From.Add(from); - mailMessage.To.Add(to); - - // subject - mailMessage.Subject = notification.Subject; - - // body - var bodyText = notification.Body; - - if (!bodyText.Contains('<') || !bodyText.Contains('>')) - { - // plain text messages should convert line breaks to HTML tags to preserve formatting - bodyText = bodyText.Replace("\n", "
"); - } - - mailMessage.Body = new TextPart("html", System.Text.Encoding.UTF8) - { - Text = bodyText - }; - - // send mail + // oauth authentication + var confidentialClientApplication = ConfidentialClientApplicationBuilder.Create(settingRepository.GetSettingValue(settings, "SMTPClientId", "")) + .WithAuthority(settingRepository.GetSettingValue(settings, "SMTPAuthority", "")) + .WithClientSecret(settingRepository.GetSettingValue(settings, "SMTPClientSecret", "")) + .Build(); try { - await client.SendAsync(mailMessage); - sent++; - notification.IsDelivered = true; - notification.DeliveredOn = DateTime.UtcNow; - notificationRepository.UpdateNotification(notification); + var result = await confidentialClientApplication.AcquireTokenForClient(settingRepository.GetSettingValue(settings, "SMTPScopes", "").Split(',')).ExecuteAsync(); + var oauth2 = new SaslMechanismOAuth2(settingRepository.GetSettingValue(settings, "SMTPSender", ""), result.AccessToken); + await client.AuthenticateAsync(oauth2); } catch (Exception ex) { - log += $"Error Sending Notification Id: {notification.NotificationId} - {ex.Message}
"; + log += "SMTP Not Configured Properly In Site Settings - OAuth Token Could Not Be Retrieved From Authority - " + ex.Message + "
"; + valid = false; } } - else - { - // invalid mailbox address - log += $"Notification Id: {notification.NotificationId} Has An {mailboxAddressValidationError} And Has Been Deleted
"; - notification.IsDeleted = true; - notificationRepository.UpdateNotification(notification); - } } - log += "Notifications Delivered: " + sent + "
"; - } + if (valid) + { + // iterate through undelivered notifications + int sent = 0; + foreach (Notification notification in notifications) + { + var fromEmail = notification.FromEmail ?? ""; + var fromName = notification.FromDisplayName ?? ""; + var toEmail = notification.ToEmail ?? ""; + var toName = notification.ToDisplayName ?? ""; - await client.DisconnectAsync(true); + // get sender and receiver information from user information if available + if ((string.IsNullOrEmpty(fromEmail) || string.IsNullOrEmpty(fromName)) && notification.FromUserId != null) + { + var user = userRepository.GetUser(notification.FromUserId.Value); + if (user != null) + { + fromEmail = string.IsNullOrEmpty(fromEmail) ? user.Email ?? "" : fromEmail; + fromName = string.IsNullOrEmpty(fromName) ? user.DisplayName ?? "" : fromName; + } + } + if ((string.IsNullOrEmpty(toEmail) || string.IsNullOrEmpty(toName)) && notification.ToUserId != null) + { + var user = userRepository.GetUser(notification.ToUserId.Value); + if (user != null) + { + toEmail = string.IsNullOrEmpty(toEmail) ? user.Email ?? "" : toEmail; + toName = string.IsNullOrEmpty(toName) ? user.DisplayName ?? "" : toName; + } + } + + // create mailbox addresses + MailboxAddress to = null; + MailboxAddress from = null; + var mailboxAddressValidationError = ""; + + // sender + if (settingRepository.GetSettingValue(settings, "SMTPRelay", "False") != "True") + { + fromEmail = settingRepository.GetSettingValue(settings, "SMTPSender", ""); + fromName = string.IsNullOrEmpty(fromName) ? site.Name : fromName; + } + if (MailboxAddress.TryParse(fromEmail, out from)) + { + from.Name = fromName; + } + else + { + + mailboxAddressValidationError += $" Invalid Sender: {fromName} <{fromEmail}>"; + } + + // recipient + if (MailboxAddress.TryParse(toEmail, out to)) + { + to.Name = toName; + } + else + { + mailboxAddressValidationError += $" Invalid Recipient: {toName} <{toEmail}>"; + } + + // if mailbox addresses are valid + if (from != null && to != null) + { + // create mail message + MimeMessage mailMessage = new MimeMessage(); + mailMessage.From.Add(from); + mailMessage.To.Add(to); + + // subject + mailMessage.Subject = notification.Subject; + + // body + var bodyText = notification.Body; + + if (!bodyText.Contains('<') || !bodyText.Contains('>')) + { + // plain text messages should convert line breaks to HTML tags to preserve formatting + bodyText = bodyText.Replace("\n", "
"); + } + + mailMessage.Body = new TextPart("html", System.Text.Encoding.UTF8) + { + Text = bodyText + }; + + // send mail + try + { + await client.SendAsync(mailMessage); + sent++; + notification.IsDelivered = true; + notification.DeliveredOn = DateTime.UtcNow; + notificationRepository.UpdateNotification(notification); + } + catch (Exception ex) + { + log += $"Error Sending Notification Id: {notification.NotificationId} - {ex.Message}
"; + } + } + else + { + // invalid mailbox address + log += $"Notification Id: {notification.NotificationId} Has An {mailboxAddressValidationError} And Has Been Deleted
"; + notification.IsDeleted = true; + notificationRepository.UpdateNotification(notification); + } + } + + log += "Notifications Delivered: " + sent + "
"; + } + + await client.DisconnectAsync(true); + } + } + else + { + log += "Site Deleted Or SMTP Disabled In Site Settings
"; } } else { - log += "Site Deleted Or SMTP Disabled In Site Settings" + "
"; + log += "No Notifications To Deliver
"; } }