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:
@@ -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> </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; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user