mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 14:04:26 +01:00
Merge pull request #6987 from NicolasDorier/refact-mails
Refactor: Move email services to the email plugin directory
This commit is contained in:
@@ -104,11 +104,13 @@ namespace BTCPayServer.Abstractions.Extensions
|
|||||||
return pages.Any(page => ActivePageClass(viewData, page.ToString(), page.GetType().ToString(), id) == ACTIVE_CLASS);
|
return pages.Any(page => ActivePageClass(viewData, page.ToString(), page.GetType().ToString(), id) == ACTIVE_CLASS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Obsolete("Use IsCategory instead")]
|
||||||
public static string ActiveCategoryClass<T>(this ViewDataDictionary viewData, T category, object id = null)
|
public static string ActiveCategoryClass<T>(this ViewDataDictionary viewData, T category, object id = null)
|
||||||
{
|
{
|
||||||
return ActiveCategoryClass(viewData, category.ToString(), id);
|
return ActiveCategoryClass(viewData, category.ToString(), id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Obsolete("Use IsCategory instead")]
|
||||||
public static string ActiveCategoryClass(this ViewDataDictionary viewData, string category, object id = null)
|
public static string ActiveCategoryClass(this ViewDataDictionary viewData, string category, object id = null)
|
||||||
{
|
{
|
||||||
return IsCategoryActive(viewData, category, id) ? ACTIVE_CLASS : null;
|
return IsCategoryActive(viewData, category, id) ? ACTIVE_CLASS : null;
|
||||||
|
|||||||
@@ -10,12 +10,10 @@ using System.Threading.Tasks;
|
|||||||
using BTCPayServer.Abstractions.Constants;
|
using BTCPayServer.Abstractions.Constants;
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
using BTCPayServer.Abstractions.Contracts;
|
||||||
using BTCPayServer.Configuration;
|
using BTCPayServer.Configuration;
|
||||||
using BTCPayServer.HostedServices;
|
|
||||||
using BTCPayServer.Hosting;
|
using BTCPayServer.Hosting;
|
||||||
using BTCPayServer.Rating;
|
using BTCPayServer.Rating;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Services.Mails;
|
|
||||||
using BTCPayServer.Services.Rates;
|
using BTCPayServer.Services.Rates;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using BTCPayServer.Tests.Logging;
|
using BTCPayServer.Tests.Logging;
|
||||||
@@ -27,7 +25,6 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
using NBXplorer;
|
using NBXplorer;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ using BTCPayServer.Rating;
|
|||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Apps;
|
using BTCPayServer.Services.Apps;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using BTCPayServer.Services.Notifications;
|
using BTCPayServer.Services.Notifications;
|
||||||
using BTCPayServer.Services.Notifications.Blobs;
|
using BTCPayServer.Services.Notifications.Blobs;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ using BTCPayServer.Services;
|
|||||||
using BTCPayServer.Services.Apps;
|
using BTCPayServer.Services.Apps;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Services.Labels;
|
using BTCPayServer.Services.Labels;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using BTCPayServer.Services.Notifications;
|
using BTCPayServer.Services.Notifications;
|
||||||
using BTCPayServer.Services.Rates;
|
using BTCPayServer.Services.Rates;
|
||||||
using BTCPayServer.Storage.Models;
|
using BTCPayServer.Storage.Models;
|
||||||
|
|||||||
@@ -94,6 +94,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Folder Include="Plugins\Emails\Mails\" />
|
||||||
<Folder Include="wwwroot\vendor\bootstrap" />
|
<Folder Include="wwwroot\vendor\bootstrap" />
|
||||||
<Folder Include="wwwroot\vendor\clipboard.js\" />
|
<Folder Include="wwwroot\vendor\clipboard.js\" />
|
||||||
<Folder Include="wwwroot\vendor\highlightjs\" />
|
<Folder Include="wwwroot\vendor\highlightjs\" />
|
||||||
|
|||||||
@@ -1,17 +1,14 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Constants;
|
using BTCPayServer.Abstractions.Constants;
|
||||||
using BTCPayServer.Abstractions.Extensions;
|
using BTCPayServer.Abstractions.Extensions;
|
||||||
using BTCPayServer.Client;
|
using BTCPayServer.Client;
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Models.ServerViewModels;
|
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Cors;
|
using Microsoft.AspNetCore.Cors;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Controllers.GreenField
|
namespace BTCPayServer.Controllers.GreenField
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using BTCPayServer.Abstractions.Extensions;
|
|||||||
using BTCPayServer.Client;
|
using BTCPayServer.Client;
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Cors;
|
using Microsoft.AspNetCore.Cors;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ using BTCPayServer.Data;
|
|||||||
using BTCPayServer.Plugins.Webhooks.Controllers;
|
using BTCPayServer.Plugins.Webhooks.Controllers;
|
||||||
using BTCPayServer.Security;
|
using BTCPayServer.Security;
|
||||||
using BTCPayServer.Security.Greenfield;
|
using BTCPayServer.Security.Greenfield;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ using BTCPayServer.Filters;
|
|||||||
using BTCPayServer.Logging;
|
using BTCPayServer.Logging;
|
||||||
using BTCPayServer.Models.AccountViewModels;
|
using BTCPayServer.Models.AccountViewModels;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using Fido2NetLib;
|
using Fido2NetLib;
|
||||||
using Microsoft.AspNetCore.Authentication;
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ using BTCPayServer.Fido2;
|
|||||||
using BTCPayServer.Models.ManageViewModels;
|
using BTCPayServer.Models.ManageViewModels;
|
||||||
using BTCPayServer.Security.Greenfield;
|
using BTCPayServer.Security.Greenfield;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ using BTCPayServer.Abstractions.Models;
|
|||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Events;
|
using BTCPayServer.Events;
|
||||||
using BTCPayServer.Models.ServerViewModels;
|
using BTCPayServer.Models.ServerViewModels;
|
||||||
using BTCPayServer.Services;
|
|
||||||
using BTCPayServer.Services.Mails;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ using BTCPayServer.Models.ServerViewModels;
|
|||||||
using BTCPayServer.Models.StoreViewModels;
|
using BTCPayServer.Models.StoreViewModels;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Apps;
|
using BTCPayServer.Services.Apps;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using BTCPayServer.Storage.Services;
|
using BTCPayServer.Storage.Services;
|
||||||
using BTCPayServer.Storage.Services.Providers;
|
using BTCPayServer.Storage.Services.Providers;
|
||||||
|
|||||||
@@ -10,12 +10,9 @@ using BTCPayServer.Data;
|
|||||||
using BTCPayServer.Events;
|
using BTCPayServer.Events;
|
||||||
using BTCPayServer.Models.StoreViewModels;
|
using BTCPayServer.Models.StoreViewModels;
|
||||||
using BTCPayServer.Security;
|
using BTCPayServer.Security;
|
||||||
using BTCPayServer.Services;
|
|
||||||
using BTCPayServer.Services.Mails;
|
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Localization;
|
|
||||||
using NicolasDorier.RateLimits;
|
using NicolasDorier.RateLimits;
|
||||||
using static BTCPayServer.Services.Stores.StoreRepository;
|
using static BTCPayServer.Services.Stores.StoreRepository;
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ using BTCPayServer.Security.Bitpay;
|
|||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Apps;
|
using BTCPayServer.Services.Apps;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using BTCPayServer.Services.Rates;
|
using BTCPayServer.Services.Rates;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using BTCPayServer.Services.Wallets;
|
using BTCPayServer.Services.Wallets;
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ using BTCPayServer.Client.JsonConverters;
|
|||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.JsonConverters;
|
using BTCPayServer.JsonConverters;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using BTCPayServer.Rating;
|
using BTCPayServer.Rating;
|
||||||
using BTCPayServer.Services.Mails;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,11 @@ using System.Net.Http;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Client.Models;
|
|
||||||
using BTCPayServer.Events;
|
using BTCPayServer.Events;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using BTCPayServer.Services.Rates;
|
using BTCPayServer.Services.Rates;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ using BTCPayServer.Services.Apps;
|
|||||||
using BTCPayServer.Services.Fees;
|
using BTCPayServer.Services.Fees;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Services.Labels;
|
using BTCPayServer.Services.Labels;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using BTCPayServer.Services.Notifications;
|
using BTCPayServer.Services.Notifications;
|
||||||
using BTCPayServer.Services.Notifications.Blobs;
|
using BTCPayServer.Services.Notifications.Blobs;
|
||||||
using BTCPayServer.Services.PaymentRequests;
|
using BTCPayServer.Services.PaymentRequests;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ using BTCPayServer.Payments.Bitcoin;
|
|||||||
using BTCPayServer.Payments.Lightning;
|
using BTCPayServer.Payments.Lightning;
|
||||||
using BTCPayServer.Payouts;
|
using BTCPayServer.Payouts;
|
||||||
using BTCPayServer.Plugins.Crowdfund;
|
using BTCPayServer.Plugins.Crowdfund;
|
||||||
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using BTCPayServer.Plugins.PointOfSale;
|
using BTCPayServer.Plugins.PointOfSale;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Apps;
|
using BTCPayServer.Services.Apps;
|
||||||
@@ -593,7 +594,7 @@ namespace BTCPayServer.Hosting
|
|||||||
private async Task MigrateEmailServerDisableTLSCerts()
|
private async Task MigrateEmailServerDisableTLSCerts()
|
||||||
{
|
{
|
||||||
await using var ctx = _DBContextFactory.CreateContext();
|
await using var ctx = _DBContextFactory.CreateContext();
|
||||||
var serverEmailSettings = await _Settings.GetSettingAsync<Services.Mails.EmailSettings>();
|
var serverEmailSettings = await _Settings.GetSettingAsync<EmailSettings>();
|
||||||
if (serverEmailSettings?.Server is String server)
|
if (serverEmailSettings?.Server is String server)
|
||||||
{
|
{
|
||||||
serverEmailSettings.DisableCertificateCheck = Extensions.IsLocalNetwork(server);
|
serverEmailSettings.DisableCertificateCheck = Extensions.IsLocalNetwork(server);
|
||||||
|
|||||||
@@ -5,10 +5,8 @@ using System.Threading.Tasks;
|
|||||||
using BTCPayServer.Abstractions.Constants;
|
using BTCPayServer.Abstractions.Constants;
|
||||||
using BTCPayServer.Abstractions.Extensions;
|
using BTCPayServer.Abstractions.Extensions;
|
||||||
using BTCPayServer.Abstractions.Models;
|
using BTCPayServer.Abstractions.Models;
|
||||||
using BTCPayServer.Client;
|
|
||||||
using BTCPayServer.Plugins.Emails.Views;
|
using BTCPayServer.Plugins.Emails.Views;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using BTCPayServer.Services.Mails;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Localization;
|
using Microsoft.Extensions.Localization;
|
||||||
using MimeKit;
|
using MimeKit;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ using BTCPayServer.Client;
|
|||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Plugins.Emails.Views;
|
using BTCPayServer.Plugins.Emails.Views;
|
||||||
using BTCPayServer.Plugins.Emails.Views.Shared;
|
using BTCPayServer.Plugins.Emails.Views.Shared;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using Dapper;
|
using Dapper;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Constants;
|
using BTCPayServer.Abstractions.Constants;
|
||||||
using BTCPayServer.Abstractions.Extensions;
|
|
||||||
using BTCPayServer.Abstractions.Models;
|
|
||||||
using BTCPayServer.Client;
|
using BTCPayServer.Client;
|
||||||
using BTCPayServer.Plugins.Emails.Views;
|
using BTCPayServer.Plugins.Emails.Views;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Localization;
|
using Microsoft.Extensions.Localization;
|
||||||
|
|||||||
@@ -3,18 +3,12 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Constants;
|
using BTCPayServer.Abstractions.Constants;
|
||||||
using BTCPayServer.Abstractions.Extensions;
|
|
||||||
using BTCPayServer.Abstractions.Models;
|
|
||||||
using BTCPayServer.Client;
|
using BTCPayServer.Client;
|
||||||
using BTCPayServer.Controllers;
|
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Plugins.Emails.Views;
|
using BTCPayServer.Plugins.Emails.Views;
|
||||||
using BTCPayServer.Plugins.Emails.Views.Shared;
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using BTCPayServer.Services.Mails;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Routing;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Localization;
|
using Microsoft.Extensions.Localization;
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using BTCPayServer.Abstractions.Extensions;
|
|||||||
using BTCPayServer.Client;
|
using BTCPayServer.Client;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Plugins.Emails.Views;
|
using BTCPayServer.Plugins.Emails.Views;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Routing;
|
using Microsoft.AspNetCore.Routing;
|
||||||
|
|||||||
@@ -1,18 +1,13 @@
|
|||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Constants;
|
using BTCPayServer.Abstractions.Constants;
|
||||||
using BTCPayServer.Abstractions.Extensions;
|
|
||||||
using BTCPayServer.Abstractions.Models;
|
|
||||||
using BTCPayServer.Client;
|
using BTCPayServer.Client;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Plugins.Emails.Views;
|
using BTCPayServer.Plugins.Emails.Views;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Localization;
|
using Microsoft.Extensions.Localization;
|
||||||
using MimeKit;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.Emails.Controllers;
|
namespace BTCPayServer.Plugins.Emails.Controllers;
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.HostedServices;
|
using BTCPayServer.HostedServices;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using MimeKit;
|
using MimeKit;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|||||||
@@ -8,12 +8,9 @@ using BTCPayServer.Events;
|
|||||||
using BTCPayServer.HostedServices;
|
using BTCPayServer.HostedServices;
|
||||||
using BTCPayServer.Logging;
|
using BTCPayServer.Logging;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Mails;
|
|
||||||
using BTCPayServer.Services.Notifications;
|
using BTCPayServer.Services.Notifications;
|
||||||
using BTCPayServer.Services.Notifications.Blobs;
|
using BTCPayServer.Services.Notifications.Blobs;
|
||||||
using BTCPayServer.Services.Stores;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using QRCoder;
|
using QRCoder;
|
||||||
|
|
||||||
|
|||||||
41
BTCPayServer/Plugins/Emails/Services/EmailSender.cs
Normal file
41
BTCPayServer/Plugins/Emails/Services/EmailSender.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Logging;
|
||||||
|
using BTCPayServer.Services;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using MimeKit;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Plugins.Emails.Services;
|
||||||
|
|
||||||
|
public abstract class EmailSender(IBackgroundJobClient jobClient, EventAggregator eventAggregator, Logs logs) : IEmailSender
|
||||||
|
{
|
||||||
|
public EventAggregator EventAggregator { get; } = eventAggregator;
|
||||||
|
public Logs Logs { get; } = logs;
|
||||||
|
|
||||||
|
public void SendEmail(MailboxAddress email, string subject, string message)
|
||||||
|
{
|
||||||
|
SendEmail(new[] { email }, Array.Empty<MailboxAddress>(), Array.Empty<MailboxAddress>(), subject, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendEmail(MailboxAddress[] email, MailboxAddress[] cc, MailboxAddress[] bcc, string subject, string message)
|
||||||
|
{
|
||||||
|
jobClient.Schedule(async cancellationToken =>
|
||||||
|
{
|
||||||
|
var emailSettings = await GetEmailSettings();
|
||||||
|
if (emailSettings?.IsComplete() is not true)
|
||||||
|
{
|
||||||
|
Logs.Configuration.LogWarning("Should have sent email, but email settings are not configured");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using var smtp = await emailSettings.CreateSmtpClient();
|
||||||
|
var mail = emailSettings.CreateMailMessage(email, cc, bcc, subject, message, true);
|
||||||
|
var response = await smtp.SendAsync(mail, cancellationToken);
|
||||||
|
await smtp.DisconnectAsync(true, cancellationToken);
|
||||||
|
EventAggregator.Publish(new Events.EmailSentEvent(response, mail));
|
||||||
|
}, TimeSpan.Zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Task<EmailSettings?> GetEmailSettings();
|
||||||
|
}
|
||||||
39
BTCPayServer/Plugins/Emails/Services/EmailSenderFactory.cs
Normal file
39
BTCPayServer/Plugins/Emails/Services/EmailSenderFactory.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Logging;
|
||||||
|
using BTCPayServer.Services;
|
||||||
|
using BTCPayServer.Services.Stores;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Plugins.Emails.Services;
|
||||||
|
|
||||||
|
public class EmailSenderFactory(
|
||||||
|
IBackgroundJobClient jobClient,
|
||||||
|
SettingsRepository settingsSettingsRepository,
|
||||||
|
EventAggregator eventAggregator,
|
||||||
|
ISettingsAccessor<PoliciesSettings> policiesSettings,
|
||||||
|
StoreRepository storeRepository,
|
||||||
|
Logs logs)
|
||||||
|
{
|
||||||
|
public Logs Logs { get; } = logs;
|
||||||
|
|
||||||
|
public Task<IEmailSender> GetEmailSender(string? storeId = null)
|
||||||
|
{
|
||||||
|
var serverSender = new ServerEmailSender(settingsSettingsRepository, jobClient, eventAggregator, Logs);
|
||||||
|
if (string.IsNullOrEmpty(storeId))
|
||||||
|
return Task.FromResult<IEmailSender>(serverSender);
|
||||||
|
return Task.FromResult<IEmailSender>(new StoreEmailSender(storeRepository,
|
||||||
|
!policiesSettings.Settings.DisableStoresToUseServerEmailSettings ? serverSender : null, jobClient,
|
||||||
|
eventAggregator, storeId, Logs));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> IsComplete(string? storeId = null)
|
||||||
|
{
|
||||||
|
var settings = await this.GetSettings(storeId);
|
||||||
|
return settings?.IsComplete() is true;
|
||||||
|
}
|
||||||
|
public async Task<EmailSettings?> GetSettings(string? storeId = null)
|
||||||
|
{
|
||||||
|
var sender = await this.GetEmailSender(storeId);
|
||||||
|
return await sender.GetEmailSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
125
BTCPayServer/Plugins/Emails/Services/EmailSettings.cs
Normal file
125
BTCPayServer/Plugins/Emails/Services/EmailSettings.cs
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Client.Models;
|
||||||
|
using BTCPayServer.Validation;
|
||||||
|
using MailKit.Net.Smtp;
|
||||||
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||||
|
using MimeKit;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Plugins.Emails.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Email Settings gets saved to database, and is used by both the server and store settings
|
||||||
|
/// </summary>
|
||||||
|
public class EmailSettings
|
||||||
|
{
|
||||||
|
public string Server { get; set; }
|
||||||
|
public int? Port { get; set; }
|
||||||
|
public string Login { get; set; }
|
||||||
|
public string Password { get; set; }
|
||||||
|
public string From { get; set; }
|
||||||
|
public bool DisableCertificateCheck { get; set; }
|
||||||
|
[JsonIgnore]
|
||||||
|
public bool EnabledCertificateCheck
|
||||||
|
{
|
||||||
|
get => !DisableCertificateCheck;
|
||||||
|
set { DisableCertificateCheck = !value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conversion functions for mapping to and from the client EmailSettingsData model
|
||||||
|
#nullable enable
|
||||||
|
public static EmailSettings FromData(EmailSettingsData data, string? existingPassword)
|
||||||
|
=> new()
|
||||||
|
{
|
||||||
|
Server = data.Server,
|
||||||
|
Port = data.Port,
|
||||||
|
Login = data.Login,
|
||||||
|
// If login was provided but password was not, use the existing password from database
|
||||||
|
Password = !string.IsNullOrEmpty(data.Login) && string.IsNullOrEmpty(data.Password) ?
|
||||||
|
existingPassword : data.Password,
|
||||||
|
From = data.From,
|
||||||
|
DisableCertificateCheck = data.DisableCertificateCheck
|
||||||
|
};
|
||||||
|
|
||||||
|
public T ToData<T>() where T : EmailSettingsData, new()
|
||||||
|
=> new T()
|
||||||
|
{
|
||||||
|
Server = Server,
|
||||||
|
Port = Port,
|
||||||
|
Login = Login,
|
||||||
|
PasswordSet = !string.IsNullOrEmpty(Password),
|
||||||
|
From = From,
|
||||||
|
DisableCertificateCheck = DisableCertificateCheck
|
||||||
|
};
|
||||||
|
#nullable restore
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
public bool IsComplete()
|
||||||
|
{
|
||||||
|
return MailboxAddressValidator.IsMailboxAddress(From)
|
||||||
|
&& !string.IsNullOrWhiteSpace(Server)
|
||||||
|
&& Port != null
|
||||||
|
&& !string.IsNullOrWhiteSpace(From)
|
||||||
|
&& MailboxAddressValidator.IsMailboxAddress(From);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Validate(string prefixKey, ModelStateDictionary modelState)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(From) && !MailboxAddressValidator.IsMailboxAddress(From))
|
||||||
|
{
|
||||||
|
modelState.AddModelError($"{prefixKey}{nameof(From)}", MailboxAddressAttribute.ErrorMessageConst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MimeMessage CreateMailMessage(MailboxAddress to, string subject, string message, bool isHtml) =>
|
||||||
|
CreateMailMessage(new[] { to }, null, null, subject, message, isHtml);
|
||||||
|
public MimeMessage CreateMailMessage(MailboxAddress[] to, MailboxAddress[] cc, MailboxAddress[] bcc, string subject, string message, bool isHtml)
|
||||||
|
{
|
||||||
|
var bodyBuilder = new BodyBuilder();
|
||||||
|
if (isHtml)
|
||||||
|
{
|
||||||
|
bodyBuilder.HtmlBody = message;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bodyBuilder.TextBody = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mm = new MimeMessage();
|
||||||
|
mm.Body = bodyBuilder.ToMessageBody();
|
||||||
|
mm.Subject = subject;
|
||||||
|
mm.From.Add(MailboxAddressValidator.Parse(From));
|
||||||
|
mm.To.AddRange(to);
|
||||||
|
mm.Cc.AddRange(cc ?? System.Array.Empty<InternetAddress>());
|
||||||
|
mm.Bcc.AddRange(bcc ?? System.Array.Empty<InternetAddress>());
|
||||||
|
return mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SmtpClient> CreateSmtpClient()
|
||||||
|
{
|
||||||
|
SmtpClient client = new SmtpClient();
|
||||||
|
using var connectCancel = new CancellationTokenSource(10000);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (DisableCertificateCheck)
|
||||||
|
{
|
||||||
|
client.CheckCertificateRevocation = false;
|
||||||
|
#pragma warning disable CA5359 // Do Not Disable Certificate Validation
|
||||||
|
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
|
||||||
|
#pragma warning restore CA5359 // Do Not Disable Certificate Validation
|
||||||
|
}
|
||||||
|
await client.ConnectAsync(Server, Port.Value, MailKit.Security.SecureSocketOptions.Auto, connectCancel.Token);
|
||||||
|
if ((client.Capabilities & SmtpCapabilities.Authentication) != 0)
|
||||||
|
await client.AuthenticateAsync(Login ?? string.Empty, Password ?? string.Empty, connectCancel.Token);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
client.Dispose();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
BTCPayServer/Plugins/Emails/Services/IEmailSender.cs
Normal file
12
BTCPayServer/Plugins/Emails/Services/IEmailSender.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MimeKit;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Plugins.Emails.Services;
|
||||||
|
|
||||||
|
public interface IEmailSender
|
||||||
|
{
|
||||||
|
void SendEmail(MailboxAddress email, string subject, string message);
|
||||||
|
void SendEmail(MailboxAddress[] email, MailboxAddress[] cc, MailboxAddress[] bcc, string subject, string message);
|
||||||
|
Task<EmailSettings?> GetEmailSettings();
|
||||||
|
}
|
||||||
15
BTCPayServer/Plugins/Emails/Services/ServerEmailSender.cs
Normal file
15
BTCPayServer/Plugins/Emails/Services/ServerEmailSender.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Logging;
|
||||||
|
using BTCPayServer.Services;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Plugins.Emails.Services;
|
||||||
|
|
||||||
|
class ServerEmailSender(SettingsRepository settingsRepository,
|
||||||
|
IBackgroundJobClient backgroundJobClient,
|
||||||
|
EventAggregator eventAggregator,
|
||||||
|
Logs logs) : EmailSender(backgroundJobClient, eventAggregator, logs)
|
||||||
|
{
|
||||||
|
public override Task<EmailSettings?> GetEmailSettings()
|
||||||
|
=> settingsRepository.GetSettingAsync<EmailSettings>();
|
||||||
|
}
|
||||||
48
BTCPayServer/Plugins/Emails/Services/StoreEmailSender.cs
Normal file
48
BTCPayServer/Plugins/Emails/Services/StoreEmailSender.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Data;
|
||||||
|
using BTCPayServer.Logging;
|
||||||
|
using BTCPayServer.Services;
|
||||||
|
using BTCPayServer.Services.Stores;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Plugins.Emails.Services;
|
||||||
|
|
||||||
|
class StoreEmailSender(
|
||||||
|
StoreRepository storeRepository,
|
||||||
|
EmailSender? fallback,
|
||||||
|
IBackgroundJobClient backgroundJobClient,
|
||||||
|
EventAggregator eventAggregator,
|
||||||
|
string storeId,
|
||||||
|
Logs logs)
|
||||||
|
: EmailSender(backgroundJobClient, eventAggregator, logs)
|
||||||
|
{
|
||||||
|
public StoreRepository StoreRepository { get; } = storeRepository;
|
||||||
|
public EmailSender? FallbackSender { get; } = fallback;
|
||||||
|
public string StoreId { get; } = storeId ?? throw new ArgumentNullException(nameof(storeId));
|
||||||
|
|
||||||
|
public override async Task<EmailSettings?> GetEmailSettings()
|
||||||
|
{
|
||||||
|
var store = await StoreRepository.FindStore(StoreId);
|
||||||
|
if (store is null)
|
||||||
|
return null;
|
||||||
|
var emailSettings = GetCustomSettings(store);
|
||||||
|
if (emailSettings is not null)
|
||||||
|
return emailSettings;
|
||||||
|
if (FallbackSender is not null)
|
||||||
|
return await FallbackSender.GetEmailSettings();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public async Task<EmailSettings?> GetCustomSettings()
|
||||||
|
{
|
||||||
|
var store = await StoreRepository.FindStore(StoreId);
|
||||||
|
if (store is null)
|
||||||
|
return null;
|
||||||
|
return GetCustomSettings(store);
|
||||||
|
}
|
||||||
|
EmailSettings? GetCustomSettings(StoreData store)
|
||||||
|
{
|
||||||
|
var emailSettings = store.GetStoreBlob().EmailSettings;
|
||||||
|
return emailSettings?.IsComplete() is true ? emailSettings : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using BTCPayServer.Validation;
|
using BTCPayServer.Validation;
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.Emails.Views;
|
namespace BTCPayServer.Plugins.Emails.Views;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ using BTCPayServer.Plugins.Emails.Views;
|
|||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Apps;
|
using BTCPayServer.Services.Apps;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Plugins.Emails.Services;
|
||||||
using BTCPayServer.Views.UIStoreMembership;
|
using BTCPayServer.Views.UIStoreMembership;
|
||||||
using Dapper;
|
using Dapper;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|||||||
@@ -1,13 +1,7 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Data.Subscriptions;
|
using BTCPayServer.Data.Subscriptions;
|
||||||
using BTCPayServer.Plugins.Emails.Views;
|
using BTCPayServer.Plugins.Emails.Views;
|
||||||
using BTCPayServer.Services.Mails;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Razor;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Views.UIStoreMembership;
|
namespace BTCPayServer.Views.UIStoreMembership;
|
||||||
|
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
#nullable enable
|
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using BTCPayServer.Logging;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using MimeKit;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Services.Mails
|
|
||||||
{
|
|
||||||
public abstract class EmailSender : IEmailSender
|
|
||||||
{
|
|
||||||
public EventAggregator EventAggregator { get; }
|
|
||||||
public Logs Logs { get; }
|
|
||||||
|
|
||||||
readonly IBackgroundJobClient _JobClient;
|
|
||||||
|
|
||||||
public EmailSender(IBackgroundJobClient jobClient, EventAggregator eventAggregator, Logs logs)
|
|
||||||
{
|
|
||||||
EventAggregator = eventAggregator;
|
|
||||||
Logs = logs;
|
|
||||||
_JobClient = jobClient ?? throw new ArgumentNullException(nameof(jobClient));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SendEmail(MailboxAddress email, string subject, string message)
|
|
||||||
{
|
|
||||||
SendEmail(new[] { email }, Array.Empty<MailboxAddress>(), Array.Empty<MailboxAddress>(), subject, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SendEmail(MailboxAddress[] email, MailboxAddress[] cc, MailboxAddress[] bcc, string subject, string message)
|
|
||||||
{
|
|
||||||
_JobClient.Schedule(async cancellationToken =>
|
|
||||||
{
|
|
||||||
var emailSettings = await GetEmailSettings();
|
|
||||||
if (emailSettings?.IsComplete() is not true)
|
|
||||||
{
|
|
||||||
Logs.Configuration.LogWarning("Should have sent email, but email settings are not configured");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
using var smtp = await emailSettings.CreateSmtpClient();
|
|
||||||
var mail = emailSettings.CreateMailMessage(email, cc, bcc, subject, message, true);
|
|
||||||
var response = await smtp.SendAsync(mail, cancellationToken);
|
|
||||||
await smtp.DisconnectAsync(true, cancellationToken);
|
|
||||||
EventAggregator.Publish(new Events.EmailSentEvent(response, mail));
|
|
||||||
}, TimeSpan.Zero);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract Task<EmailSettings?> GetEmailSettings();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
#nullable enable
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using BTCPayServer.HostedServices;
|
|
||||||
using BTCPayServer.Logging;
|
|
||||||
using BTCPayServer.Services.Stores;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Services.Mails
|
|
||||||
{
|
|
||||||
public class EmailSenderFactory
|
|
||||||
{
|
|
||||||
public ISettingsAccessor<PoliciesSettings> PoliciesSettings { get; }
|
|
||||||
public Logs Logs { get; }
|
|
||||||
|
|
||||||
private readonly IBackgroundJobClient _jobClient;
|
|
||||||
private readonly SettingsRepository _settingsRepository;
|
|
||||||
private readonly EventAggregator _eventAggregator;
|
|
||||||
private readonly StoreRepository _storeRepository;
|
|
||||||
|
|
||||||
public EmailSenderFactory(IBackgroundJobClient jobClient,
|
|
||||||
SettingsRepository settingsSettingsRepository,
|
|
||||||
EventAggregator eventAggregator,
|
|
||||||
ISettingsAccessor<PoliciesSettings> policiesSettings,
|
|
||||||
StoreRepository storeRepository,
|
|
||||||
Logs logs)
|
|
||||||
{
|
|
||||||
Logs = logs;
|
|
||||||
_jobClient = jobClient;
|
|
||||||
_settingsRepository = settingsSettingsRepository;
|
|
||||||
_eventAggregator = eventAggregator;
|
|
||||||
PoliciesSettings = policiesSettings;
|
|
||||||
_storeRepository = storeRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<IEmailSender> GetEmailSender(string? storeId = null)
|
|
||||||
{
|
|
||||||
var serverSender = new ServerEmailSender(_settingsRepository, _jobClient, _eventAggregator, Logs);
|
|
||||||
if (string.IsNullOrEmpty(storeId))
|
|
||||||
return Task.FromResult<IEmailSender>(serverSender);
|
|
||||||
return Task.FromResult<IEmailSender>(new StoreEmailSender(_storeRepository,
|
|
||||||
!PoliciesSettings.Settings.DisableStoresToUseServerEmailSettings ? serverSender : null, _jobClient,
|
|
||||||
_eventAggregator, storeId, Logs));
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> IsComplete(string? storeId = null)
|
|
||||||
{
|
|
||||||
var settings = await this.GetSettings(storeId);
|
|
||||||
return settings?.IsComplete() is true;
|
|
||||||
}
|
|
||||||
public async Task<EmailSettings?> GetSettings(string? storeId = null)
|
|
||||||
{
|
|
||||||
var sender = await this.GetEmailSender(storeId);
|
|
||||||
return await sender.GetEmailSettings();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using BTCPayServer.Client.Models;
|
|
||||||
using BTCPayServer.Validation;
|
|
||||||
using MailKit.Net.Smtp;
|
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
|
||||||
using MimeKit;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Services.Mails
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Email Settings gets saved to database, and is used by both the server and store settings
|
|
||||||
/// </summary>
|
|
||||||
public class EmailSettings
|
|
||||||
{
|
|
||||||
public string Server { get; set; }
|
|
||||||
public int? Port { get; set; }
|
|
||||||
public string Login { get; set; }
|
|
||||||
public string Password { get; set; }
|
|
||||||
public string From { get; set; }
|
|
||||||
public bool DisableCertificateCheck { get; set; }
|
|
||||||
[JsonIgnore]
|
|
||||||
public bool EnabledCertificateCheck
|
|
||||||
{
|
|
||||||
get => !DisableCertificateCheck;
|
|
||||||
set { DisableCertificateCheck = !value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Conversion functions for mapping to and from the client EmailSettingsData model
|
|
||||||
#nullable enable
|
|
||||||
public static EmailSettings FromData(EmailSettingsData data, string? existingPassword)
|
|
||||||
=> new()
|
|
||||||
{
|
|
||||||
Server = data.Server,
|
|
||||||
Port = data.Port,
|
|
||||||
Login = data.Login,
|
|
||||||
// If login was provided but password was not, use the existing password from database
|
|
||||||
Password = !string.IsNullOrEmpty(data.Login) && string.IsNullOrEmpty(data.Password) ?
|
|
||||||
existingPassword : data.Password,
|
|
||||||
From = data.From,
|
|
||||||
DisableCertificateCheck = data.DisableCertificateCheck
|
|
||||||
};
|
|
||||||
|
|
||||||
public T ToData<T>() where T : EmailSettingsData, new()
|
|
||||||
=> new T()
|
|
||||||
{
|
|
||||||
Server = Server,
|
|
||||||
Port = Port,
|
|
||||||
Login = Login,
|
|
||||||
PasswordSet = !string.IsNullOrEmpty(Password),
|
|
||||||
From = From,
|
|
||||||
DisableCertificateCheck = DisableCertificateCheck
|
|
||||||
};
|
|
||||||
#nullable restore
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
public bool IsComplete()
|
|
||||||
{
|
|
||||||
return MailboxAddressValidator.IsMailboxAddress(From)
|
|
||||||
&& !string.IsNullOrWhiteSpace(Server)
|
|
||||||
&& Port != null
|
|
||||||
&& !string.IsNullOrWhiteSpace(From)
|
|
||||||
&& MailboxAddressValidator.IsMailboxAddress(From);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Validate(string prefixKey, ModelStateDictionary modelState)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(From) && !MailboxAddressValidator.IsMailboxAddress(From))
|
|
||||||
{
|
|
||||||
modelState.AddModelError($"{prefixKey}{nameof(From)}", MailboxAddressAttribute.ErrorMessageConst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public MimeMessage CreateMailMessage(MailboxAddress to, string subject, string message, bool isHtml) =>
|
|
||||||
CreateMailMessage(new[] { to }, null, null, subject, message, isHtml);
|
|
||||||
public MimeMessage CreateMailMessage(MailboxAddress[] to, MailboxAddress[] cc, MailboxAddress[] bcc, string subject, string message, bool isHtml)
|
|
||||||
{
|
|
||||||
var bodyBuilder = new BodyBuilder();
|
|
||||||
if (isHtml)
|
|
||||||
{
|
|
||||||
bodyBuilder.HtmlBody = message;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bodyBuilder.TextBody = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
var mm = new MimeMessage();
|
|
||||||
mm.Body = bodyBuilder.ToMessageBody();
|
|
||||||
mm.Subject = subject;
|
|
||||||
mm.From.Add(MailboxAddressValidator.Parse(From));
|
|
||||||
mm.To.AddRange(to);
|
|
||||||
mm.Cc.AddRange(cc ?? System.Array.Empty<InternetAddress>());
|
|
||||||
mm.Bcc.AddRange(bcc ?? System.Array.Empty<InternetAddress>());
|
|
||||||
return mm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<SmtpClient> CreateSmtpClient()
|
|
||||||
{
|
|
||||||
SmtpClient client = new SmtpClient();
|
|
||||||
using var connectCancel = new CancellationTokenSource(10000);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (DisableCertificateCheck)
|
|
||||||
{
|
|
||||||
client.CheckCertificateRevocation = false;
|
|
||||||
#pragma warning disable CA5359 // Do Not Disable Certificate Validation
|
|
||||||
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
|
|
||||||
#pragma warning restore CA5359 // Do Not Disable Certificate Validation
|
|
||||||
}
|
|
||||||
await client.ConnectAsync(Server, Port.Value, MailKit.Security.SecureSocketOptions.Auto, connectCancel.Token);
|
|
||||||
if ((client.Capabilities & SmtpCapabilities.Authentication) != 0)
|
|
||||||
await client.AuthenticateAsync(Login ?? string.Empty, Password ?? string.Empty, connectCancel.Token);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
client.Dispose();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#nullable enable
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MimeKit;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Services.Mails
|
|
||||||
{
|
|
||||||
public interface IEmailSender
|
|
||||||
{
|
|
||||||
void SendEmail(MailboxAddress email, string subject, string message);
|
|
||||||
void SendEmail(MailboxAddress[] email, MailboxAddress[] cc, MailboxAddress[] bcc, string subject, string message);
|
|
||||||
Task<EmailSettings?> GetEmailSettings();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using BTCPayServer.Logging;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Services.Mails
|
|
||||||
{
|
|
||||||
class ServerEmailSender : EmailSender
|
|
||||||
{
|
|
||||||
public ServerEmailSender(SettingsRepository settingsRepository,
|
|
||||||
IBackgroundJobClient backgroundJobClient,
|
|
||||||
EventAggregator eventAggregator,
|
|
||||||
Logs logs) : base(backgroundJobClient, eventAggregator, logs)
|
|
||||||
{
|
|
||||||
ArgumentNullException.ThrowIfNull(settingsRepository);
|
|
||||||
SettingsRepository = settingsRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SettingsRepository SettingsRepository { get; }
|
|
||||||
|
|
||||||
public override Task<EmailSettings> GetEmailSettings()
|
|
||||||
{
|
|
||||||
return SettingsRepository.GetSettingAsync<EmailSettings>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
#nullable enable
|
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using BTCPayServer.Data;
|
|
||||||
using BTCPayServer.Logging;
|
|
||||||
using BTCPayServer.Services.Stores;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Services.Mails
|
|
||||||
{
|
|
||||||
class StoreEmailSender : EmailSender
|
|
||||||
{
|
|
||||||
public StoreEmailSender(StoreRepository storeRepository,
|
|
||||||
EmailSender? fallback,
|
|
||||||
IBackgroundJobClient backgroundJobClient,
|
|
||||||
EventAggregator eventAggregator,
|
|
||||||
string storeId,
|
|
||||||
Logs logs) : base(backgroundJobClient, eventAggregator, logs)
|
|
||||||
{
|
|
||||||
StoreId = storeId ?? throw new ArgumentNullException(nameof(storeId));
|
|
||||||
StoreRepository = storeRepository;
|
|
||||||
FallbackSender = fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StoreRepository StoreRepository { get; }
|
|
||||||
public EmailSender? FallbackSender { get; }
|
|
||||||
public string StoreId { get; }
|
|
||||||
|
|
||||||
public override async Task<EmailSettings?> GetEmailSettings()
|
|
||||||
{
|
|
||||||
var store = await StoreRepository.FindStore(StoreId);
|
|
||||||
if (store is null)
|
|
||||||
return null;
|
|
||||||
var emailSettings = GetCustomSettings(store);
|
|
||||||
if (emailSettings is not null)
|
|
||||||
return emailSettings;
|
|
||||||
if (FallbackSender is not null)
|
|
||||||
return await FallbackSender.GetEmailSettings();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
public async Task<EmailSettings?> GetCustomSettings()
|
|
||||||
{
|
|
||||||
var store = await StoreRepository.FindStore(StoreId);
|
|
||||||
if (store is null)
|
|
||||||
return null;
|
|
||||||
return GetCustomSettings(store);
|
|
||||||
}
|
|
||||||
EmailSettings? GetCustomSettings(StoreData store)
|
|
||||||
{
|
|
||||||
var emailSettings = store.GetStoreBlob().EmailSettings;
|
|
||||||
return emailSettings?.IsComplete() is true ? emailSettings : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
@using BTCPayServer.Services
|
@using BTCPayServer.Plugins.Emails.Services
|
||||||
@using BTCPayServer.Services.Mails
|
|
||||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
|
||||||
@model ForgotPasswordViewModel
|
@model ForgotPasswordViewModel
|
||||||
@inject EmailSenderFactory EmailSenderFactory
|
@inject EmailSenderFactory EmailSenderFactory
|
||||||
@{
|
@{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
@using BTCPayServer.Services
|
@using BTCPayServer.Services
|
||||||
@using BTCPayServer.Services.Mails;
|
@using BTCPayServer.Plugins.Emails.Services
|
||||||
@model BTCPayServer.Services.PoliciesSettings
|
@model BTCPayServer.Services.PoliciesSettings
|
||||||
@inject EmailSenderFactory EmailSenderFactory
|
@inject EmailSenderFactory EmailSenderFactory
|
||||||
@inject TransactionLinkProviders TransactionLinkProviders
|
@inject TransactionLinkProviders TransactionLinkProviders
|
||||||
|
|||||||
Reference in New Issue
Block a user