Refactor EmailService for use in desktop/server apps

This commit is contained in:
Dennis Reimann 2025-05-30 09:34:33 +02:00
parent b489cd0ec7
commit 7f917a2a92
No known key found for this signature in database
GPG Key ID: 5009E1797F03F8D0
10 changed files with 26 additions and 50 deletions

View File

@ -2,6 +2,6 @@
{
public interface IEmailService
{
Task SendAsync(string subject, string body, string? recipient = null, string? attachFilePath = null);
Task SendAsync(string subject, string body, string recipient, string? attachFilePath = null);
}
}

View File

@ -12,6 +12,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.DataProtection" Version="8.0.11" />
<PackageReference Include="Microsoft.JSInterop" Version="8.0.16" />
<PackageReference Include="Plugin.Fingerprint" Version="3.0.0-beta.1" />
</ItemGroup>

View File

@ -0,0 +1,12 @@
using BTCPayApp.Core.Contracts;
using Microsoft.JSInterop;
namespace BTCPayApp.Desktop.Services;
public class EmailService(IJSRuntime jSRuntime) : IEmailService
{
public async Task SendAsync(string subject, string body, string recipient, string? attachFilePath = null)
{
await jSRuntime.InvokeVoidAsync("Interop.sendEmail", subject, body, recipient);
}
}

View File

@ -1,6 +1,5 @@
using BTCPayApp.Core.Contracts;
using BTCPayApp.Core.Data;
using BTCPayApp.Core.Helpers;
using BTCPayApp.Desktop.Services;
using Microsoft.Extensions.DependencyInjection;
using Plugin.Fingerprint.Abstractions;
@ -15,9 +14,9 @@ public static class StartupExtensions
options.ApplicationDiscriminator = "BTCPayApp";
});
serviceCollection.AddSingleton<IDataDirectoryProvider, DesktopDataDirectoryProvider>();
// serviceCollection.AddSingleton<IConfigProvider, DesktopConfigProvider>();
serviceCollection.AddSingleton<ISecureConfigProvider, DesktopSecureConfigProvider>();
serviceCollection.AddSingleton<IFingerprint, StubFingerprintProvider>();
serviceCollection.AddScoped<IEmailService, EmailService>();
return serviceCollection;
}

View File

@ -29,7 +29,6 @@ public static class MauiProgram
builder.Services.AddBTCPayAppUIServices();
builder.Services.ConfigureBTCPayAppMaui();
builder.Services.ConfigureBTCPayAppCore();
builder.Services.AddSingleton<IEmailService, EmailService>();
var serviceProvider = builder.Services.BuildServiceProvider();
var logger = serviceProvider.GetRequiredService<ILogger<MauiApp>>();

View File

@ -13,24 +13,15 @@ namespace BTCPayApp.Maui.Services
Subject = subject, //"App Log File",
Body = body, //"Attached is the log file for review.",
BodyFormat = EmailBodyFormat.PlainText,
To = new List<string> { recipient }
To = [recipient]
};
if(!string.IsNullOrWhiteSpace(attachFilePath))
if (!string.IsNullOrWhiteSpace(attachFilePath))
{
message.Attachments?.Add(new EmailAttachment(attachFilePath));
}
try
{
await Email.Default.ComposeAsync(message);
}
catch (Exception ex)
{
throw;
}
await Email.Default.ComposeAsync(message);
}
else
{

View File

@ -1,6 +1,4 @@
using BTCPayApp.Core.Contracts;
using BTCPayApp.Core.Data;
using BTCPayApp.Core.Helpers;
using BTCPayApp.Maui.Services;
using Plugin.Fingerprint;
@ -16,6 +14,7 @@ public static class StartupExtensions
serviceCollection.AddSingleton(CrossFingerprint.Current);
serviceCollection.AddSingleton<HostedServiceInitializer>();
serviceCollection.AddSingleton<IMauiInitializeService, HostedServiceInitializer>();
serviceCollection.AddScoped<IEmailService, EmailService>();
return serviceCollection;
}

View File

@ -1,19 +0,0 @@
using BTCPayApp.Core.Contracts;
using Microsoft.JSInterop;
namespace BTCPayApp.Server.Services
{
public class EmailService : IEmailService
{
private readonly IJSRuntime jSRuntime;
public EmailService(IJSRuntime jSRuntime)
{
this.jSRuntime = jSRuntime;
}
public async Task SendAsync(string subject, string body, string? recipient = null, string? attachFilePath = null)
{
await jSRuntime.InvokeVoidAsync("Interop.sendEmail", subject, body, recipient);
}
}
}

View File

@ -1,15 +1,12 @@
@attribute [Route(Routes.AppLogs)]
@using System.Text
@using BTCPayApp.Core.Contracts
@using BTCPayApp.Core.Services
@using BTCPayApp.UI.Components.Layout
@using Serilog.Events
@inject ConfigProvider ConfigProvider
@inject LoggingService LogService
@inject IJSRuntime JS
@inject IEmailService EmailService
<PageTitle>Application Logs</PageTitle>
<SectionContent SectionId="_Layout.Top">
@ -45,6 +42,10 @@
}
@if (HasLogs)
{
<div id="CtaContainer" class="container d-flex flex-column gap-3">
<button type="button" class="btn btn-secondary" data-clipboard-target="#logs">Copy logs</button>
<button type="button" class="btn btn-primary" @onclick="SendLogs">Send via email</button>
</div>
<pre><code id="logs">@_logContent</code></pre>
}
else
@ -53,13 +54,6 @@
<p class="text-muted my-0">There are no logs, yet.</p>
</div>
}
@if (HasLogs)
{
<div id="CtaContainer" class="container d-flex align-items-center justify-content-around">
<button type="button" class="btn btn-primary" data-clipboard-target="#logs">Copy logs</button>
<button type="button" class="btn btn-primary" @onclick="SendLogs">Send logs</button>
</div>
}
</section>
@code {
@ -107,6 +101,6 @@
private async Task SendLogs()
{
await EmailService.SendAsync("App Log File", _logContent!);
await EmailService.SendAsync("App Log File", _logContent!, "app@btcpayserver.org");
}
}

View File

@ -89,7 +89,7 @@ Interop = {
}
},
sendEmail(subject, body, to) {
window.location.href = 'mailto:' + to + '?subject=' + subject + '& body=' + body + ';';
window.location.href = 'mailto:' + to + '?subject=' + subject + '&body=' + body + ';';
},
saveAsFile(filename, data) {
const $link = document.createElement('a');