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
-196
View File
@@ -1,196 +0,0 @@
using Cfg = System.Configuration.ConfigurationManager;
using Fuchs.intranet;
using MimeKit;
using Newtonsoft.Json;
using Microsoft.Data.SqlClient;
using OCORE.SQL;
using static OCORE.SQL.sql;
namespace Fuchs.intranet;
/// <summary>
/// Email sending helper for Fuchs intranet. Full port of fuchs_fds_email.vb.
/// Uses OCORE.email.Emailcommons.SendEmail_async when settings are available,
/// falls back to MailKit direct send otherwise.
/// </summary>
public static class FuchsFdsEmail
{
private static OCORE.email.EmailServerSettings? _settings;
private static OCORE.email.EmailServerSettings? GetEmailSettings()
{
if (_settings != null) return _settings;
string raw = Cfg.AppSettings["FDS_EmailSettings"] ?? "";
if (string.IsNullOrWhiteSpace(raw)) return null;
// The serialised string is JSON containing a "type" field
string type = "smtp";
try
{
var dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(raw);
if (dic?.TryGetValue("type", out var t) == true)
type = t?.ToString() ?? "smtp";
}
catch { /* keep default type */ }
_settings = new OCORE.email.EmailServerSettings(type, raw);
return _settings;
}
private const string ReplyToName = "Sebastian Fuchs - Bad und Heizung";
private const string ReplyToAddress = "info@sanitaerfuchs.de";
private const string SignatureIntro =
"<p>&nbsp;</p><p style=\"margin:24px 0 16px 0;line-height:140%;\">" +
"Herzliche Gr\u00fc\u00dfe aus D\u00fcsseldorf-Bilk<br/>" +
"Ihr Team der Firma Sebastian Fuchs</p>";
/// <summary>
/// Sends an email and logs the result to the Fuchs FDS database.
/// Returns true on success.
/// </summary>
public static async Task<bool> SendEmail(
string @ref,
string subject,
string html,
string email,
string name,
Dictionary<string, byte[]>? files,
Fuchs_intranet intranet)
{
var errors = new List<string>();
string guid = "";
string config = "";
DateTime sent = default;
if (!IsValidEmail(email))
errors.Add("Die Email-Adresse ist nicht g\u00fcltig.");
if (string.IsNullOrEmpty(html))
errors.Add("Bitte geben Sie eine Nachricht ein.");
if (errors.Count == 0)
{
try
{
var settings = GetEmailSettings();
string body = html + BuildSignature();
if (settings != null)
{
// ── OCORE path ─────────────────────────────────────────
var msg = new OCORE.email.Email(
Mode: OCORE.email.EmailMode.DirectMode,
type: settings.type)
{
EmailSettings = settings,
Subject = subject
};
msg.AddTo(email, name);
msg.AddReplyTo(new MailboxAddress(ReplyToName, ReplyToAddress));
msg.SetBody(body);
if (files != null)
foreach (var kv in files)
msg.AttachFile(filecontent: kv.Value, kv.Key);
var result = await msg.SendAsync(
(dref, ex) => intranet.debug_log(
$"FuchsFdsEmail.SendEmail {dref}", ex));
guid = msg.MessageId ?? "";
config = msg.EmailConfig_serialized;
sent = result.Timestamp;
errors.AddRange(result.ErrorMessages);
}
else
{
// ── MailKit fallback (app settings) ────────────────────
string host = Cfg.AppSettings["smtp_host"] ?? "";
string user = Cfg.AppSettings["smtp_user"] ?? "";
string pass = Cfg.AppSettings["smtp_pass"] ?? "";
string from = Cfg.AppSettings["smtp_from"] ?? user;
string fromName = Cfg.AppSettings["smtp_fromname"] ?? "Sanit\u00e4rFuchs";
int port = int.TryParse(Cfg.AppSettings["smtp_port"], out int p) ? p : 587;
var message = new MimeMessage();
message.From.Add(new MailboxAddress(fromName, from));
message.To.Add(new MailboxAddress(name, email));
message.ReplyTo.Add(new MailboxAddress(ReplyToName, ReplyToAddress));
message.Subject = subject;
var builder = new BodyBuilder { HtmlBody = body };
if (files != null)
foreach (var kv in files)
builder.Attachments.Add(kv.Key, kv.Value);
message.Body = builder.ToMessageBody();
using var client = new MailKit.Net.Smtp.SmtpClient();
await client.ConnectAsync(host, port,
MailKit.Security.SecureSocketOptions.Auto);
if (!string.IsNullOrEmpty(user))
await client.AuthenticateAsync(user, pass);
await client.SendAsync(message);
await client.DisconnectAsync(true);
guid = message.MessageId!;
sent = DateTime.UtcNow;
}
}
catch (Exception ex)
{
errors.Add("Beim Versenden ist ein Fehler aufgetreten.");
intranet.debug_log("FuchsFdsEmail.SendEmail inner", ex, data: errors);
}
}
if (errors.Count > 0)
intranet.debug_log("FuchsFdsEmail.SendEmail",
data: new { @ref, email, errors });
// ── SQL audit log ──────────────────────────────────────────────────
try
{
var pl = new List<SqlParameter>
{
SQL_VarChar("@Ref", @ref),
SQL_VarChar("@guid", guid),
SQL_DateTime("@DateSent", sent == default ? DBNull.Value : (object)sent),
SQL_NVarChar("@config", config, dbNull_IfEmpty: true),
SQL_Bit("@success", errors.Count == 0),
SQL_NVarChar("@log", JsonConvert.SerializeObject(errors))
};
await setSQLValue_async(
"EXECUTE [dbo].[fds__logEmail] @Ref, @guid, @DateSent, @config, @success, @log;",
intranet.Intranet__SQLConnectionString, pl,
Security: intranet.GetDbSecurity());
}
catch (Exception logEx)
{
intranet.debug_log("FuchsFdsEmail.SendEmail log", logEx);
}
return errors.Count == 0;
}
// ── Helpers ────────────────────────────────────────────────────────────────
private static string BuildSignature()
{
try
{
string sigPath = Path.Combine(AppContext.BaseDirectory,
"email_signature", "sanitaerfuchs_email_signature.txt");
if (File.Exists(sigPath))
return SignatureIntro + File.ReadAllText(sigPath);
}
catch { /* signature is optional */ }
return "";
}
private static bool IsValidEmail(string email)
{
try
{
var a = new System.Net.Mail.MailAddress(email);
return string.Equals(a.Address, email, StringComparison.OrdinalIgnoreCase);
}
catch { return false; }
}
}