From 0b60ca68fcb5778d7b9eb1ae23e298458b4ab98d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Skyler=20M=C3=A4ntysaari?= Date: Fri, 23 Apr 2021 02:37:28 +0300 Subject: [PATCH] New: Mailgun connection (cherry picked from commit 55752a6c6213c1d83d347ba0f6870aa6c1cc0770) --- .../Notifications/Mailgun/Mailgun.cs | 58 ++++++++++++++++ .../Notifications/Mailgun/MailgunException.cs | 18 +++++ .../Notifications/Mailgun/MailgunProxy.cs | 66 +++++++++++++++++++ .../Notifications/Mailgun/MailgunSettings.cs | 48 ++++++++++++++ 4 files changed, 190 insertions(+) create mode 100644 src/NzbDrone.Core/Notifications/Mailgun/Mailgun.cs create mode 100644 src/NzbDrone.Core/Notifications/Mailgun/MailgunException.cs create mode 100644 src/NzbDrone.Core/Notifications/Mailgun/MailgunProxy.cs create mode 100644 src/NzbDrone.Core/Notifications/Mailgun/MailgunSettings.cs diff --git a/src/NzbDrone.Core/Notifications/Mailgun/Mailgun.cs b/src/NzbDrone.Core/Notifications/Mailgun/Mailgun.cs new file mode 100644 index 000000000..facb7a56b --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Mailgun/Mailgun.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using FluentValidation.Results; +using NLog; + +namespace NzbDrone.Core.Notifications.Mailgun +{ + public class MailGun : NotificationBase + { + private readonly IMailgunProxy _proxy; + private readonly Logger _logger; + + public MailGun(IMailgunProxy proxy, Logger logger) + { + _proxy = proxy; + _logger = logger; + } + + public override string Name => "Mailgun"; + public override string Link => "https://mailgun.com"; + + public override void OnGrab(GrabMessage grabMessage) + { + _proxy.SendNotification(ALBUM_GRABBED_TITLE, grabMessage.Message, Settings); + } + + public override void OnReleaseImport(AlbumDownloadMessage downloadMessage) + { + _proxy.SendNotification(ALBUM_DOWNLOADED_TITLE, downloadMessage.Message, Settings); + } + + public override void OnHealthIssue(HealthCheck.HealthCheck healthCheckMessage) + { + _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheckMessage.Message, Settings); + } + + public override ValidationResult Test() + { + var failures = new List(); + + try + { + const string title = "Test Notification"; + const string body = "This is a test message from Lidarr, though Mailgun."; + + _proxy.SendNotification(title, body, Settings); + _logger.Info("Successsfully sent email though Mailgun."); + } + catch (Exception ex) + { + _logger.Error(ex, "Unable to send test message though Mailgun."); + failures.Add(new ValidationFailure("", "Unable to send test message though Mailgun.")); + } + + return new ValidationResult(failures); + } + } +} diff --git a/src/NzbDrone.Core/Notifications/Mailgun/MailgunException.cs b/src/NzbDrone.Core/Notifications/Mailgun/MailgunException.cs new file mode 100644 index 000000000..4ddd53814 --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Mailgun/MailgunException.cs @@ -0,0 +1,18 @@ +using System; +using NzbDrone.Common.Exceptions; + +namespace NzbDrone.Core.Notifications.Mailgun +{ + public class MailgunException : NzbDroneException + { + public MailgunException(string message) + : base(message) + { + } + + public MailgunException(string message, Exception innerException, params object[] args) + : base(message, innerException, args) + { + } + } +} diff --git a/src/NzbDrone.Core/Notifications/Mailgun/MailgunProxy.cs b/src/NzbDrone.Core/Notifications/Mailgun/MailgunProxy.cs new file mode 100644 index 000000000..dbbbf2af7 --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Mailgun/MailgunProxy.cs @@ -0,0 +1,66 @@ +using System.Net; +using NLog; +using NzbDrone.Common.Http; +using HttpMethod = NzbDrone.Common.Http.HttpMethod; + +namespace NzbDrone.Core.Notifications.Mailgun +{ + public interface IMailgunProxy + { + void SendNotification(string tittle, string message, MailgunSettings settings); + } + + public class MailgunProxy : IMailgunProxy + { + private const string BaseUrlEu = "https://api.eu.mailgun.net/v3"; + private const string BaseUrlUs = "https://api.mailgun.net/v3"; + private readonly IHttpClient _httpClient; + private readonly Logger _logger; + + public MailgunProxy(IHttpClient httpClient, Logger logger) + { + _httpClient = httpClient; + _logger = logger; + } + + public void SendNotification(string title, string message, MailgunSettings settings) + { + try + { + var request = BuildRequest(settings, $"{settings.SenderDomain}/messages", HttpMethod.POST, title, message).Build(); + _httpClient.Execute(request); + } + catch (HttpException ex) + { + if (ex.Response.StatusCode == HttpStatusCode.Unauthorized) + { + throw new MailgunException("Unauthorised - ApiKey is invalid"); + } + + throw new MailgunException("Unable to connect to Mailgun. Status code: {0}", ex); + } + } + + private HttpRequestBuilder BuildRequest(MailgunSettings settings, string resource, HttpMethod method, string messageSubject, string messageBody) + { + var loginCredentials = new NetworkCredential("api", settings.ApiKey); + var url = settings.UseEuEndpoint ? BaseUrlEu : BaseUrlUs; + var requestBuilder = new HttpRequestBuilder(url).Resource(resource); + + requestBuilder.Method = method; + requestBuilder.NetworkCredential = loginCredentials; + + requestBuilder.AddFormParameter("from", $"{settings.From}"); + + foreach (var recipient in settings.Recipients) + { + requestBuilder.AddFormParameter("to", $"{recipient}"); + } + + requestBuilder.AddFormParameter("subject", $"{messageSubject}"); + requestBuilder.AddFormParameter("text", $"{messageBody}"); + + return requestBuilder; + } + } +} diff --git a/src/NzbDrone.Core/Notifications/Mailgun/MailgunSettings.cs b/src/NzbDrone.Core/Notifications/Mailgun/MailgunSettings.cs new file mode 100644 index 000000000..b09824ac3 --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Mailgun/MailgunSettings.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using FluentValidation; +using NzbDrone.Core.Annotations; +using NzbDrone.Core.ThingiProvider; +using NzbDrone.Core.Validation; + +namespace NzbDrone.Core.Notifications.Mailgun +{ + public class MailGunSettingsValidator : AbstractValidator + { + public MailGunSettingsValidator() + { + RuleFor(c => c.ApiKey).NotEmpty(); + RuleFor(c => c.From).NotEmpty(); + RuleFor(c => c.Recipients).NotEmpty(); + } + } + + public class MailgunSettings : IProviderConfig + { + private static readonly MailGunSettingsValidator Validator = new MailGunSettingsValidator(); + + public MailgunSettings() + { + Recipients = new string[] { }; + } + + [FieldDefinition(0, Label = "API Key", HelpText = "The API key generated from MailGun")] + public string ApiKey { get; set; } + + [FieldDefinition(1, Label = "Use EU Endpoint?", HelpText = "You can choose to use the EU MailGun endpoint with this", Type = FieldType.Checkbox)] + public bool UseEuEndpoint { get; set; } + + [FieldDefinition(2, Label = "From Address")] + public string From { get; set; } + + [FieldDefinition(3, Label = "Sender Domain")] + public string SenderDomain { get; set; } + + [FieldDefinition(4, Label = "Recipient Address(es)", Type = FieldType.Tag)] + public IEnumerable Recipients { get; set; } + + public NzbDroneValidationResult Validate() + { + return new NzbDroneValidationResult(Validator.Validate(this)); + } + } +}