Files
hrynco-notification-service/HrynCo.NotificationService.Worker.Services/EmailProcessing/EmailTemplateRenderingService.cs
agrynco 50033a5bd4 fix: escape html notification variables
Encode template variables in HTML bodies while preserving text and subjects.

Ref: IT-1115
2026-08-19 23:04:15 +03:00

51 lines
1.8 KiB
C#

namespace HrynCo.NotificationService.Worker.Services.EmailProcessing;
using System.Net;
using System.Text;
using HrynCo.NotificationService.Contracts.Messages;
using HrynCo.NotificationService.DAL.Abstract.Templates;
internal sealed class EmailTemplateRenderingService : IEmailTemplateRenderingService
{
public RenderedEmail Render(EmailTemplate template, SendEmailMessageData data)
{
string[] missingVariables = template.Variables
.Where(variable => variable.Required)
.Select(variable => variable.Name)
.Where(name => !data.Variables.TryGetValue(name, out string? value) || string.IsNullOrWhiteSpace(value))
.ToArray();
if (missingVariables.Length > 0)
{
throw new InvalidDataException(
$"Required template variables are missing: {string.Join(", ", missingVariables)}.");
}
return new RenderedEmail(
Interpolate(template.Subject, data.Variables),
InterpolateHtml(template.HtmlBody, data.Variables),
Interpolate(template.TextBody, data.Variables));
}
private static string InterpolateHtml(string text, IReadOnlyDictionary<string, string> variables)
{
return Interpolate(text, variables, WebUtility.HtmlEncode);
}
private static string Interpolate(string text, IReadOnlyDictionary<string, string> variables)
{
return Interpolate(text, variables, static value => value);
}
private static string Interpolate(
string text,
IReadOnlyDictionary<string, string> variables,
Func<string, string> encodeValue)
{
var sb = new StringBuilder(text);
foreach (var (key, value) in variables)
sb.Replace($"{{{{{key}}}}}", encodeValue(value));
return sb.ToString();
}
}