From 7de2c8d41fd4faf29f06887a341aaf0cc4996d80 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Thu, 8 Apr 2021 17:34:56 -0700 Subject: [PATCH] Refactor Email and add more logging (cherry picked from sonarr 5301620ecfd6cffb6014e986d1ce5b6bbaace93a) closes #6168 --- .../Notifications/Email/Email.cs | 127 ++++++++++++++++-- .../Notifications/Email/EmailService.cs | 100 -------------- 2 files changed, 118 insertions(+), 109 deletions(-) delete mode 100644 src/NzbDrone.Core/Notifications/Email/EmailService.cs diff --git a/src/NzbDrone.Core/Notifications/Email/Email.cs b/src/NzbDrone.Core/Notifications/Email/Email.cs index 69add44d9..16215dcac 100644 --- a/src/NzbDrone.Core/Notifications/Email/Email.cs +++ b/src/NzbDrone.Core/Notifications/Email/Email.cs @@ -1,18 +1,24 @@ +using System; using System.Collections.Generic; +using System.Linq; using FluentValidation.Results; +using MailKit.Net.Smtp; +using MailKit.Security; +using MimeKit; +using NLog; using NzbDrone.Common.Extensions; namespace NzbDrone.Core.Notifications.Email { public class Email : NotificationBase { - private readonly IEmailService _emailService; + private readonly Logger _logger; public override string Name => "Email"; - public Email(IEmailService emailService) + public Email(Logger logger) { - _emailService = emailService; + _logger = logger; } public override string Link => null; @@ -21,42 +27,145 @@ public override void OnGrab(GrabMessage grabMessage) { var body = $"{grabMessage.Message} sent to queue."; - _emailService.SendEmail(Settings, MOVIE_GRABBED_TITLE_BRANDED, body); + SendEmail(Settings, MOVIE_GRABBED_TITLE_BRANDED, body); } public override void OnDownload(DownloadMessage message) { var body = $"{message.Message} Downloaded and sorted."; - _emailService.SendEmail(Settings, MOVIE_DOWNLOADED_TITLE_BRANDED, body); + SendEmail(Settings, MOVIE_DOWNLOADED_TITLE_BRANDED, body); } public override void OnMovieFileDelete(MovieFileDeleteMessage deleteMessage) { var body = $"{deleteMessage.Message} deleted."; - _emailService.SendEmail(Settings, MOVIE_FILE_DELETED_TITLE_BRANDED, body); + SendEmail(Settings, MOVIE_FILE_DELETED_TITLE_BRANDED, body); } public override void OnMovieDelete(MovieDeleteMessage deleteMessage) { var body = $"{deleteMessage.Message}"; - _emailService.SendEmail(Settings, MOVIE_DELETED_TITLE_BRANDED, body); + SendEmail(Settings, MOVIE_DELETED_TITLE_BRANDED, body); } public override void OnHealthIssue(HealthCheck.HealthCheck message) { - _emailService.SendEmail(Settings, HEALTH_ISSUE_TITLE_BRANDED, message.Message); + SendEmail(Settings, HEALTH_ISSUE_TITLE_BRANDED, message.Message); } public override ValidationResult Test() { var failures = new List(); - failures.AddIfNotNull(_emailService.Test(Settings)); + failures.AddIfNotNull(Test(Settings)); return new ValidationResult(failures); } + + private void SendEmail(EmailSettings settings, string subject, string body, bool htmlBody = false) + { + var email = new MimeMessage(); + + email.From.Add(ParseAddress("From", settings.From)); + email.To.AddRange(settings.To.Select(x => ParseAddress("To", x))); + email.Cc.AddRange(settings.CC.Select(x => ParseAddress("CC", x))); + email.Bcc.AddRange(settings.Bcc.Select(x => ParseAddress("BCC", x))); + + email.Subject = subject; + email.Body = new TextPart(htmlBody ? "html" : "plain") + { + Text = body + }; + + _logger.Debug("Sending email Subject: {0}", subject); + + try + { + Send(email, settings); + _logger.Debug("Email sent. Subject: {0}", subject); + } + catch (Exception ex) + { + _logger.Error("Error sending email. Subject: {0}", email.Subject); + _logger.Debug(ex, ex.Message); + throw; + } + + _logger.Debug("Finished sending email. Subject: {0}", email.Subject); + } + + private void Send(MimeMessage email, EmailSettings settings) + { + using (var client = new SmtpClient()) + { + var serverOption = SecureSocketOptions.Auto; + + if (settings.RequireEncryption) + { + if (settings.Port == 465) + { + serverOption = SecureSocketOptions.SslOnConnect; + } + else + { + serverOption = SecureSocketOptions.StartTls; + } + } + + _logger.Debug("Connecting to mail server"); + + client.Connect(settings.Server, settings.Port, serverOption); + + if (!string.IsNullOrWhiteSpace(settings.Username)) + { + _logger.Debug("Authenticating to mail server"); + + client.Authenticate(settings.Username, settings.Password); + } + + _logger.Debug("Sending to mail server"); + + client.Send(email); + + _logger.Debug("Sent to mail server, disconnecting"); + + client.Disconnect(true); + + _logger.Debug("Disconnecting from mail server"); + } + } + + public ValidationFailure Test(EmailSettings settings) + { + const string body = "Success! You have properly configured your email notification settings"; + + try + { + SendEmail(settings, "Radarr - Test Notification", body); + } + catch (Exception ex) + { + _logger.Error(ex, "Unable to send test email"); + return new ValidationFailure("Server", "Unable to send test email"); + } + + return null; + } + + private MailboxAddress ParseAddress(string type, string address) + { + try + { + return MailboxAddress.Parse(address); + } + catch (Exception ex) + { + _logger.Error(ex, "{0} email address '{1}' invalid", type, address); + throw; + } + } } } diff --git a/src/NzbDrone.Core/Notifications/Email/EmailService.cs b/src/NzbDrone.Core/Notifications/Email/EmailService.cs deleted file mode 100644 index a7ee6e9ba..000000000 --- a/src/NzbDrone.Core/Notifications/Email/EmailService.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System; -using System.Linq; -using FluentValidation.Results; -using MailKit.Net.Smtp; -using MailKit.Security; -using MimeKit; -using NLog; - -namespace NzbDrone.Core.Notifications.Email -{ - public interface IEmailService - { - void SendEmail(EmailSettings settings, string subject, string body, bool htmlBody = false); - ValidationFailure Test(EmailSettings settings); - } - - public class EmailService : IEmailService - { - private readonly Logger _logger; - - public EmailService(Logger logger) - { - _logger = logger; - } - - public void SendEmail(EmailSettings settings, string subject, string body, bool htmlBody = false) - { - var email = new MimeMessage(); - email.From.Add(MailboxAddress.Parse(settings.From)); - - settings.To.ToList().ForEach(x => email.To.Add(MailboxAddress.Parse(x))); - settings.CC.ToList().ForEach(x => email.Cc.Add(MailboxAddress.Parse(x))); - settings.Bcc.ToList().ForEach(x => email.Bcc.Add(MailboxAddress.Parse(x))); - - email.Subject = subject; - email.Body = new TextPart(htmlBody ? "html" : "plain") - { - Text = body - }; - - try - { - Send(email, settings); - } - catch (Exception ex) - { - _logger.Error("Error sending email. Subject: {0}", email.Subject); - _logger.Debug(ex, ex.Message); - throw; - } - } - - private void Send(MimeMessage email, EmailSettings settings) - { - using (var client = new SmtpClient()) - { - var serverOption = SecureSocketOptions.Auto; - - if (settings.RequireEncryption) - { - if (settings.Port == 465) - { - serverOption = SecureSocketOptions.SslOnConnect; - } - else - { - serverOption = SecureSocketOptions.StartTls; - } - } - - client.Connect(settings.Server, settings.Port, serverOption); - - if (!string.IsNullOrWhiteSpace(settings.Username)) - { - client.Authenticate(settings.Username, settings.Password); - } - - client.Send(email); - client.Disconnect(true); - } - } - - public ValidationFailure Test(EmailSettings settings) - { - const string body = "Success! You have properly configured your email notification settings"; - - try - { - SendEmail(settings, "Radarr - Test Notification", body); - } - catch (Exception ex) - { - _logger.Error(ex, "Unable to send test email: " + ex.Message); - return new ValidationFailure("Server", "Unable to send test email"); - } - - return null; - } - } -}