Unify email/SMS via ProcessWeb Mailer API, remove legacy

Replaces legacy email/SMS logic with a new IComService abstraction using the ProcessWeb Mailer API for all outbound communication. Removes FuchsFdsEmail, FuchsEmailService, IEmailService, SmtpAccountSettings, and FuchsEmailSettings. Updates controllers to use IComService. Refactors appsettings.json to use a new "Mailer" section. Adds ProcessWebComSettings and a stub for secret management. Removes OCORE.sms.SMS77 and direct SMTP/MailKit usage. Cleans up solution file references to OCORE projects.
This commit is contained in:
Stefan
2026-05-18 08:11:21 +02:00
parent cc2abc91d6
commit b17baca835
15 changed files with 285 additions and 555 deletions
@@ -1,4 +1,5 @@
using Fuchs.intranet;
using Fuchs.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.SqlClient;
using Newtonsoft.Json;
@@ -117,11 +118,11 @@ public partial class IntranetController
frdic.no("InvoiceFile", null!) is byte[] invFile)
remdoc[frdic.nz("InvoiceFileName")] = invFile;
bool sent = await FuchsFdsEmail.SendEmail(
bool sent = await _comService.SendEmailAsync(
$"inv_{remId}",
$"SanitärFuchs - {frdic.nz("subject").ne(frdic.nz("DocumentName"))}",
BuildReminderBody(Convert.ToDouble(frdic.no("amount_open", 0))),
email.Trim(), "", remdoc, _intranet);
email.Trim(), "", remdoc);
if (sent)
{
var pls = StdParamlist(SQL_VarChar("@Id", remId), SQL_Bit("@auto", true));
@@ -175,10 +176,10 @@ public partial class IntranetController
if (!string.IsNullOrEmpty(frdic.nz("InvoiceFileName")) &&
frdic.no("InvoiceFile", null!) is byte[] invFile)
remdoc[frdic.nz("InvoiceFileName")] = invFile;
await FuchsFdsEmail.SendEmail($"rem_{remId}",
await _comService.SendEmailAsync($"rem_{remId}",
$"SanitärFuchs - {frdic.nz("subject").ne(frdic.nz("DocumentName"))}",
BuildReminderBody(Convert.ToDouble(frdic.no("amount_open", 0))),
email.Trim(), "", remdoc, _intranet);
email.Trim(), "", remdoc);
}
return Ok();
}
@@ -1,5 +1,6 @@
using System.Globalization;
using Fuchs.intranet;
using Fuchs.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.SqlClient;
using MFR_RESTClient.generic;
@@ -273,9 +274,9 @@ public partial class IntranetController
double bal = Convert.ToDouble(frdic.no("InvoiceBalance", 0));
string terms = fdInv.PaymentTerms.Replace("wd", " Werktagen").Replace("d", " Tagen").Replace("wk", " Wochen").ne("10 Tagen");
string body = BuildInvoiceBody(bal, terms);
bool sent = await FuchsFdsEmail.SendEmail(
bool sent = await _comService.SendEmailAsync(
$"inv_{invId}", $"Sanit\u00e4rFuchs - {frdic.nz("DocumentName")}",
body, email.Trim(), "", inv, _intranet);
body, email.Trim(), "", inv);
if (sent)
{
var pls = StdParamlist(SQL_VarChar("@Id", invId), SQL_Bit("@auto", true));
@@ -328,11 +329,10 @@ public partial class IntranetController
{
double bal = Convert.ToDouble(frdic.no("InvoiceBalance", 0));
string terms = fdInv.PaymentTerms.Replace("wd", " Werktagen").Replace("d", " Tagen").Replace("wk", " Wochen").ne("10 Tagen");
await FuchsFdsEmail.SendEmail(
await _comService.SendEmailAsync(
$"inv_{invId}", $"Sanit\u00e4rFuchs - {frdic.nz("DocumentName")}",
BuildInvoiceBody(bal, terms), email.Trim(), "",
new Dictionary<string, byte[]> { [frdic.nz("DocumentName")] = filebyte },
_intranet);
new Dictionary<string, byte[]> { [frdic.nz("DocumentName")] = filebyte });
}
return Ok();
}
+10 -12
View File
@@ -1,5 +1,6 @@
using System.Web;
using Fuchs.intranet;
using Fuchs.Services;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
@@ -24,6 +25,7 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
internal readonly Fuchs_intranet _intranet;
internal readonly fds.IFdsMfr _mfr;
private readonly ILogger<IntranetController> _logger;
private readonly IComService _comService;
private readonly List<string> _allowedNonAuth = new() { "spwc", "spw" };
private readonly List<string> _allowedGet = new()
{
@@ -39,11 +41,12 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
public string UserAccountID => UserIdent.UserAccountId;
public string AuthAccount => UserIdent.Email;
public IntranetController(Fuchs_intranet intranet, fds.IFdsMfr mfr, ILogger<IntranetController> logger)
public IntranetController(Fuchs_intranet intranet, fds.IFdsMfr mfr, ILogger<IntranetController> logger, IComService comService)
{
_intranet = intranet;
_mfr = mfr;
_logger = logger;
_comService = comService;
}
// ── Standard param list (pre-populates @authuser) ────────────────────────
@@ -203,12 +206,9 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
row.nz("name").ToLower().Trim() == lastname.ToLower().Trim() &&
row.nz("mobile").Length > 5 && !Request.Host.Host.ToLower().Contains("localhost"))
{
OCORE.sms.SMS77.Settings.APIKey = _intranet.Intranet__SMS_API_key;
using var sms = new OCORE.sms.SMS77.SMS("ProcessWeb");
string totp = OCORE.security.TFA.generateTotp_12h(_intranet.Intranet__TOTPsharedsecret_base);
if (long.TryParse(row.nz("mobile").Replace("+", "00").Replace(" ", ""), out long smsNum))
sms.SendSMS_sync(smsNum,
"Zur Bestätigung des Passwortversands auf sanitarfuchs.de, verwenden Sie bitte folgenden Code:" + totp);
await _comService.SendSmsAsync(row.nz("mobile"),
"Zur Bestätigung des Passwortversands auf sanitarfuchs.de, verwenden Sie bitte folgenden Code:" + totp);
}
return Ok(); // always OK to prevent enumeration
}
@@ -226,10 +226,10 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
var row = await _intranet.GetUserAccountByEmailAsync(email, includePassword: true);
if (row != null && row.nz("email").Length > 5)
{
await FuchsFdsEmail.SendEmail("pw_" + row.nz("email"),
await _comService.SendEmailAsync("pw_" + row.nz("email"),
"sanitaerfuchs.de Intranet Passwort",
$"<p>Guten Tag {row.nz("firstname")} {row.nz("name")},<br/>Ihr Passwort: {HttpUtility.HtmlEncode(row.nz("password"))}</p>",
row.nz("email"), $"{row.nz("firstname")} {row.nz("name")}", null, _intranet);
row.nz("email"), $"{row.nz("firstname")} {row.nz("name")}", null);
}
}
return Ok();
@@ -243,11 +243,9 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
var row = await _intranet.GetUserAccountByEmailAsync(UserIdent.Email, includePassword: true);
if (row != null && row.nz("mobile").Length > 5 && !Request.Host.Host.Contains("localhost"))
{
OCORE.sms.SMS77.Settings.APIKey = _intranet.Intranet__SMS_API_key;
using var sms2 = new OCORE.sms.SMS77.SMS("ProcessWeb");
string totp2 = OCORE.security.TFA.generateTotp_3h(_intranet.Intranet__TOTPsharedsecret_base + "3MDR");
if (long.TryParse(row.nz("mobile").Replace("+", "00").Replace(" ", ""), out long mob2))
sms2.SendSMS_sync(mob2, "Zur Bestätigung der Passwortänderung auf sanitarfuchs.de: " + totp2);
await _comService.SendSmsAsync(row.nz("mobile"),
"Zur Bestätigung der Passwortänderung auf sanitarfuchs.de: " + totp2);
}
return Ok();