mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2024-11-19 01:43:50 +01:00
New API endpoint: Send email using store SMTP (#3181)
Co-authored-by: Kukks <evilkukka@gmail.com>
This commit is contained in:
parent
c15f182377
commit
c36b0c16b0
19
BTCPayServer.Client/BTCPayServerClient.StoreEmail.cs
Normal file
19
BTCPayServer.Client/BTCPayServerClient.StoreEmail.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Client.Models;
|
||||
|
||||
namespace BTCPayServer.Client
|
||||
{
|
||||
public partial class BTCPayServerClient
|
||||
{
|
||||
public virtual async Task SendEmail(string storeId, SendEmailRequest request,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/email/send", bodyPayload: request, method: HttpMethod.Post),
|
||||
token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
}
|
||||
}
|
10
BTCPayServer.Client/Models/SendEmailRequest.cs
Normal file
10
BTCPayServer.Client/Models/SendEmailRequest.cs
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
namespace BTCPayServer.Client.Models
|
||||
{
|
||||
public class SendEmailRequest
|
||||
{
|
||||
public string Email;
|
||||
public string Subject;
|
||||
public string Body;
|
||||
}
|
||||
}
|
@ -2265,6 +2265,24 @@ namespace BTCPayServer.Tests
|
||||
await AssertAPIError("store-user-role-orphaned", async () => await user2Client.RemoveStoreUser(user.StoreId, user2.UserId));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
[Fact(Timeout = 60 * 2 * 1000)]
|
||||
[Trait("Integration", "Integration")]
|
||||
public async Task StoreEmailTests()
|
||||
{
|
||||
using var tester = CreateServerTester();
|
||||
await tester.StartAsync();
|
||||
var admin = tester.NewAccount();
|
||||
await admin.GrantAccessAsync(true);
|
||||
var adminClient = await admin.CreateClient(Policies.Unrestricted);
|
||||
|
||||
await adminClient.SendEmail(admin.StoreId, new SendEmailRequest()
|
||||
{
|
||||
Body = "lol",
|
||||
Subject = "subj",
|
||||
Email = "sdasdas"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Constants;
|
||||
using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Services.Mails;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace BTCPayServer.Controllers.GreenField
|
||||
{
|
||||
[ApiController]
|
||||
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
[EnableCors(CorsPolicies.All)]
|
||||
public class GreenfieldStoreEmailController : Controller
|
||||
{
|
||||
private readonly EmailSenderFactory _emailSenderFactory;
|
||||
|
||||
public GreenfieldStoreEmailController(EmailSenderFactory emailSenderFactory)
|
||||
{
|
||||
_emailSenderFactory = emailSenderFactory;
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
[HttpPost("~/api/v1/stores/{storeId}/email/send")]
|
||||
public async Task<IActionResult> SendEmailFromStore(string storeId,
|
||||
[FromBody] SendEmailRequest request)
|
||||
{
|
||||
var store = HttpContext.GetStoreData();
|
||||
if (store == null)
|
||||
{
|
||||
return this.CreateAPIError(404, "store-not-found", "The store was not found");
|
||||
}
|
||||
var emailSender = await _emailSenderFactory.GetEmailSender(storeId);
|
||||
if (emailSender is null )
|
||||
{
|
||||
return this.CreateAPIError(404,"smtp-not-configured", "Store does not have an SMTP server configured.");
|
||||
}
|
||||
|
||||
emailSender.SendEmail(request.Email, request.Subject, request.Body);
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Controllers.GreenField;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Security.Greenfield;
|
||||
using BTCPayServer.Services.Stores;
|
||||
@ -56,6 +57,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
private readonly GreenfieldPullPaymentController _greenfieldPullPaymentController;
|
||||
private readonly UIHomeController _homeController;
|
||||
private readonly GreenfieldStorePaymentMethodsController _storePaymentMethodsController;
|
||||
private readonly GreenfieldStoreEmailController _greenfieldStoreEmailController;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
public BTCPayServerClientFactory(StoreRepository storeRepository,
|
||||
@ -79,6 +81,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
GreenfieldPullPaymentController greenfieldPullPaymentController,
|
||||
UIHomeController homeController,
|
||||
GreenfieldStorePaymentMethodsController storePaymentMethodsController,
|
||||
GreenfieldStoreEmailController greenfieldStoreEmailController,
|
||||
IServiceProvider serviceProvider)
|
||||
{
|
||||
_storeRepository = storeRepository;
|
||||
@ -102,6 +105,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
_greenfieldPullPaymentController = greenfieldPullPaymentController;
|
||||
_homeController = homeController;
|
||||
_storePaymentMethodsController = storePaymentMethodsController;
|
||||
_greenfieldStoreEmailController = greenfieldStoreEmailController;
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
@ -158,6 +162,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
_greenfieldPullPaymentController,
|
||||
_homeController,
|
||||
_storePaymentMethodsController,
|
||||
_greenfieldStoreEmailController,
|
||||
new LocalHttpContextAccessor() { HttpContext = context }
|
||||
);
|
||||
}
|
||||
@ -188,6 +193,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
private readonly GreenfieldPullPaymentController _greenfieldPullPaymentController;
|
||||
private readonly UIHomeController _homeController;
|
||||
private readonly GreenfieldStorePaymentMethodsController _storePaymentMethodsController;
|
||||
private readonly GreenfieldStoreEmailController _greenfieldStoreEmailController;
|
||||
|
||||
public LocalBTCPayServerClient(
|
||||
IServiceProvider serviceProvider,
|
||||
@ -209,6 +215,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
GreenfieldPullPaymentController greenfieldPullPaymentController,
|
||||
UIHomeController homeController,
|
||||
GreenfieldStorePaymentMethodsController storePaymentMethodsController,
|
||||
GreenfieldStoreEmailController greenfieldStoreEmailController,
|
||||
IHttpContextAccessor httpContextAccessor) : base(new Uri("https://dummy.local"), "", "")
|
||||
{
|
||||
_chainPaymentMethodsController = chainPaymentMethodsController;
|
||||
@ -229,6 +236,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
_greenfieldPullPaymentController = greenfieldPullPaymentController;
|
||||
_homeController = homeController;
|
||||
_storePaymentMethodsController = storePaymentMethodsController;
|
||||
_greenfieldStoreEmailController = greenfieldStoreEmailController;
|
||||
|
||||
var controllers = new[]
|
||||
{
|
||||
@ -236,7 +244,8 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
paymentRequestController, apiKeysController, notificationsController, usersController,
|
||||
storeLightningNetworkPaymentMethodsController, greenFieldInvoiceController, storeWebhooksController,
|
||||
greenFieldServerInfoController, greenfieldPullPaymentController, storesController, homeController,
|
||||
lightningNodeApiController, storeLightningNodeApiController as ControllerBase, storePaymentMethodsController
|
||||
lightningNodeApiController, storeLightningNodeApiController as ControllerBase, storePaymentMethodsController,
|
||||
greenfieldStoreEmailController
|
||||
};
|
||||
|
||||
var authoverride = new DefaultAuthorizationService(
|
||||
@ -999,5 +1008,10 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
ImportKeysToRPC = request.ImportKeysToRPC
|
||||
}));
|
||||
}
|
||||
|
||||
public override async Task SendEmail(string storeId, SendEmailRequest request, CancellationToken token = default)
|
||||
{
|
||||
HandleActionResult(await _greenfieldStoreEmailController.SendEmailFromStore(storeId, request));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,74 @@
|
||||
{
|
||||
"paths": {
|
||||
"/api/v1/stores/{storeId}/email/send": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Stores"
|
||||
],
|
||||
"summary": "Send an email for a store",
|
||||
"description": "Send an email using the store's SMTP server",
|
||||
"requestBody": {
|
||||
"x-name": "request",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/EmailData"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"x-position": 1
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "The email was sent (scheduled) successfully"
|
||||
},
|
||||
"400": {
|
||||
"description": "The store's SMTP is not configured"
|
||||
},
|
||||
"403": {
|
||||
"description": "If you are authenticated but forbidden to add new stores"
|
||||
},
|
||||
"404": {
|
||||
"description": "The store was not found"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"API Key": [
|
||||
"btcpay.store.canmodifystoresettings"
|
||||
],
|
||||
"Basic": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"EmailData": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "Email of the recipient"
|
||||
},
|
||||
"subject": {
|
||||
"type": "string",
|
||||
"description": "Subject of the email"
|
||||
},
|
||||
"body": {
|
||||
"type": "string",
|
||||
"description": "Body of the email to send as plain text."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"name": "Store Email"
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user