Update email templates to HTML format and fix EmailApiEmailSender
- Convert email.match.body, email.match.job-search-footer, email.search-results.body, and email.search-results.empty templates from plain text to proper HTML format in InitialSchema migration - Update EmailApiEmailSender.BuildMatchEmailBody() to work with HTML templates instead of plain text - Add WebUtility.HtmlEncode() for security when inserting dynamic content (summary) - Templates now use semantic HTML tags (table, h2, h3, ul, li, p, div, hr, a) instead of plain text with newlines - All 32 email template variants (16 keys × 2 languages) and 8 html.job-search.* templates seeded via migration Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@ using EmailApi.Models.Requests;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Models.Requests;
|
||||
using Models.Settings;
|
||||
using System.Net;
|
||||
|
||||
namespace Api.Services;
|
||||
|
||||
@@ -194,31 +195,35 @@ public sealed class EmailApiEmailSender : IEmailSender
|
||||
/// <inheritdoc />
|
||||
public string BuildMatchEmailBody(string cvDocumentId, JobMatchResponse result, string? jobLabel, string language, string? jobSearchLink = null, int expiryDays = 7)
|
||||
{
|
||||
// Build HTML lists for strengths, gaps, and recommendations
|
||||
var strengths = result.Strengths?.Count > 0
|
||||
? "<ul style=\"color:#495057;padding-left:20px;line-height:1.8\">" +
|
||||
? "<ul style=\"color:#495057;padding-left:20px;line-height:1.8;margin:0\">" +
|
||||
string.Join("", result.Strengths.Select(s => $"<li>{s}</li>")) + "</ul>"
|
||||
: "<p style=\"color:#6c757d\">—</p>";
|
||||
: "<p style=\"color:#6c757d;margin:0\">—</p>";
|
||||
|
||||
var gaps = result.Gaps?.Count > 0
|
||||
? "<ul style=\"color:#495057;padding-left:20px;line-height:1.8\">" +
|
||||
? "<ul style=\"color:#495057;padding-left:20px;line-height:1.8;margin:0\">" +
|
||||
string.Join("", result.Gaps.Select(g => $"<li>{g}</li>")) + "</ul>"
|
||||
: "<p style=\"color:#6c757d\">—</p>";
|
||||
: "<p style=\"color:#6c757d;margin:0\">—</p>";
|
||||
|
||||
var recommendations = result.Recommendations?.Count > 0
|
||||
? "<ul style=\"color:#495057;padding-left:20px;line-height:1.8\">" +
|
||||
? "<ul style=\"color:#495057;padding-left:20px;line-height:1.8;margin:0\">" +
|
||||
string.Join("", result.Recommendations.Select(r => $"<li>{r}</li>")) + "</ul>"
|
||||
: "<p style=\"color:#6c757d\">—</p>";
|
||||
: "<p style=\"color:#6c757d;margin:0\">—</p>";
|
||||
|
||||
// Render the HTML template with substituted values
|
||||
// email.match.body is now stored as HTML in the database
|
||||
var body = _emailTemplates.Render("email.match.body", language,
|
||||
("cvDocumentId", cvDocumentId),
|
||||
("jobLabel", jobLabel ?? "N/A"),
|
||||
("jobUrl", result.JobUrl ?? "N/A"),
|
||||
("score", result.Score.ToString()),
|
||||
("summary", result.Summary ?? string.Empty),
|
||||
("summary", WebUtility.HtmlEncode(result.Summary ?? string.Empty)),
|
||||
("strengths", strengths),
|
||||
("gaps", gaps),
|
||||
("recommendations", recommendations));
|
||||
|
||||
// Append the job search footer if link is provided
|
||||
if (!string.IsNullOrWhiteSpace(jobSearchLink))
|
||||
{
|
||||
body += _emailTemplates.Render("email.match.job-search-footer", language,
|
||||
|
||||
Reference in New Issue
Block a user