mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 14:34:23 +01:00
Store Emails (#3611)
* Store Emails * fix test * Update email rules layout * Cleanups * Test cleanups * Add back comments * Update view; add test * Show email rules link even if email settings aren't completed * Validate email addresses * No redirect, display warning * Fix test * Refactoring: Change email argument types to MailAddress * Test fix * Refactoring: Use MailboxAddress * Parse emails properly in controllers and backend Co-authored-by: Dennis Reimann <mail@dennisreimann.de> Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
This commit is contained in:
@@ -1,7 +1,11 @@
|
||||
using System;
|
||||
using System.Net.Mail;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Constants;
|
||||
using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Abstractions.Models;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Models.ServerViewModels;
|
||||
using BTCPayServer.Services.Mails;
|
||||
@@ -12,9 +16,84 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
public partial class UIStoresController
|
||||
{
|
||||
[HttpGet("{storeId}/emails")]
|
||||
public IActionResult StoreEmails(string storeId)
|
||||
{
|
||||
var store = HttpContext.GetStoreData();
|
||||
if (store == null)
|
||||
return NotFound();
|
||||
|
||||
var blob = store.GetStoreBlob();
|
||||
var data = blob.EmailSettings;
|
||||
if (data?.IsComplete() is not true)
|
||||
{
|
||||
TempData.SetStatusMessageModel(new StatusMessageModel
|
||||
{
|
||||
Severity = StatusMessageModel.StatusSeverity.Warning,
|
||||
Html = $"You need to configure email settings before this feature works. <a class='alert-link' href='{Url.Action("StoreEmailSettings", new {storeId})}'>Configure now</a>."
|
||||
});
|
||||
}
|
||||
|
||||
[Route("{storeId}/emails")]
|
||||
public IActionResult Emails()
|
||||
var vm = new StoreEmailRuleViewModel { Rules = blob.EmailRules ?? new List<StoreEmailRule>() };
|
||||
return View(vm);
|
||||
}
|
||||
|
||||
[HttpPost("{storeId}/emails")]
|
||||
public async Task<IActionResult> StoreEmails(string storeId, StoreEmailRuleViewModel vm, string command)
|
||||
{
|
||||
vm.Rules ??= new List<StoreEmailRule>();
|
||||
if (command.StartsWith("remove", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
var item = command[(command.IndexOf(":", StringComparison.InvariantCultureIgnoreCase) + 1)..];
|
||||
var index = int.Parse(item);
|
||||
vm.Rules.RemoveAt(index);
|
||||
|
||||
return View(vm);
|
||||
}
|
||||
|
||||
if (command == "add")
|
||||
{
|
||||
vm.Rules.Add(new StoreEmailRule());
|
||||
|
||||
return View(vm);
|
||||
}
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return View(vm);
|
||||
}
|
||||
|
||||
var store = HttpContext.GetStoreData();
|
||||
if (store == null)
|
||||
return NotFound();
|
||||
var blob = store.GetStoreBlob();
|
||||
blob.EmailRules = vm.Rules;
|
||||
store.SetStoreBlob(blob);
|
||||
await _Repo.UpdateStore(store);
|
||||
TempData.SetStatusMessageModel(new StatusMessageModel
|
||||
{
|
||||
Severity = StatusMessageModel.StatusSeverity.Success,
|
||||
Message = "Store email rules saved"
|
||||
});
|
||||
return RedirectToAction("StoreEmails", new {storeId});
|
||||
}
|
||||
|
||||
public class StoreEmailRuleViewModel
|
||||
{
|
||||
public List<StoreEmailRule> Rules { get; set; }
|
||||
}
|
||||
|
||||
public class StoreEmailRule
|
||||
{
|
||||
[Required]
|
||||
public WebhookEventType Trigger { get; set; }
|
||||
public bool CustomerEmail { get; set; }
|
||||
public string To { get; set; }
|
||||
public string Body { get; set; }
|
||||
public string Subject { get; set; }
|
||||
}
|
||||
|
||||
[HttpGet("{storeId}/email-settings")]
|
||||
public IActionResult StoreEmailSettings()
|
||||
{
|
||||
var store = HttpContext.GetStoreData();
|
||||
if (store == null)
|
||||
@@ -23,13 +102,13 @@ namespace BTCPayServer.Controllers
|
||||
return View(new EmailsViewModel(data));
|
||||
}
|
||||
|
||||
[Route("{storeId}/emails")]
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Emails(string storeId, EmailsViewModel model, string command)
|
||||
[HttpPost("{storeId}/email-settings")]
|
||||
public async Task<IActionResult> StoreEmailSettings(string storeId, EmailsViewModel model, string command)
|
||||
{
|
||||
var store = HttpContext.GetStoreData();
|
||||
if (store == null)
|
||||
return NotFound();
|
||||
|
||||
if (command == "Test")
|
||||
{
|
||||
try
|
||||
@@ -43,11 +122,16 @@ namespace BTCPayServer.Controllers
|
||||
TempData[WellKnownTempData.ErrorMessage] = "Required fields missing";
|
||||
return View(model);
|
||||
}
|
||||
if (!MailboxAddress.TryParse(model.TestEmail, out MailboxAddress testEmail))
|
||||
{
|
||||
TempData[WellKnownTempData.ErrorMessage] = "Invalid test email";
|
||||
return View(model);
|
||||
}
|
||||
using var client = await model.Settings.CreateSmtpClient();
|
||||
var message = model.Settings.CreateMailMessage(new MailboxAddress(model.TestEmail, model.TestEmail), "BTCPay test", "BTCPay test", false);
|
||||
var message = model.Settings.CreateMailMessage(testEmail, "BTCPay test", "BTCPay test", false);
|
||||
await client.SendAsync(message);
|
||||
await client.DisconnectAsync(true);
|
||||
TempData[WellKnownTempData.SuccessMessage] = "Email sent to " + model.TestEmail + ", please, verify you received it";
|
||||
TempData[WellKnownTempData.SuccessMessage] = $"Email sent to {model.TestEmail}. Please verify you received it.";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -55,23 +139,19 @@ namespace BTCPayServer.Controllers
|
||||
}
|
||||
return View(model);
|
||||
}
|
||||
else if (command == "ResetPassword")
|
||||
if (command == "ResetPassword")
|
||||
{
|
||||
var storeBlob = store.GetStoreBlob();
|
||||
storeBlob.EmailSettings.Password = null;
|
||||
store.SetStoreBlob(storeBlob);
|
||||
await _Repo.UpdateStore(store);
|
||||
TempData[WellKnownTempData.SuccessMessage] = "Email server password reset";
|
||||
return RedirectToAction(nameof(Emails), new
|
||||
{
|
||||
storeId
|
||||
});
|
||||
return RedirectToAction(nameof(StoreEmailSettings), new { storeId });
|
||||
}
|
||||
else // if(command == "Save")
|
||||
else // if (command == "Save")
|
||||
{
|
||||
var storeBlob = store.GetStoreBlob();
|
||||
var oldPassword = storeBlob.EmailSettings?.Password;
|
||||
if (new EmailsViewModel(storeBlob.EmailSettings).PasswordSet)
|
||||
if (new EmailsViewModel(storeBlob.EmailSettings).PasswordSet && storeBlob.EmailSettings != null)
|
||||
{
|
||||
model.Settings.Password = storeBlob.EmailSettings.Password;
|
||||
}
|
||||
@@ -79,10 +159,7 @@ namespace BTCPayServer.Controllers
|
||||
store.SetStoreBlob(storeBlob);
|
||||
await _Repo.UpdateStore(store);
|
||||
TempData[WellKnownTempData.SuccessMessage] = "Email settings modified";
|
||||
return RedirectToAction(nameof(Emails), new
|
||||
{
|
||||
storeId
|
||||
});
|
||||
return RedirectToAction(nameof(StoreEmailSettings), new { storeId });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user