💄 Optimized landing email
This commit is contained in:
@ -62,19 +62,45 @@ public class EmailService
|
||||
await client.DisconnectAsync(true);
|
||||
}
|
||||
|
||||
private static string _ConvertHtmlToPlainText(string html)
|
||||
{
|
||||
// Remove style tags and their contents
|
||||
html = System.Text.RegularExpressions.Regex.Replace(html, "<style[^>]*>.*?</style>", "",
|
||||
System.Text.RegularExpressions.RegexOptions.Singleline);
|
||||
|
||||
// Replace header tags with text + newlines
|
||||
html = System.Text.RegularExpressions.Regex.Replace(html, "<h[1-6][^>]*>(.*?)</h[1-6]>", "$1\n\n",
|
||||
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
|
||||
|
||||
// Replace line breaks
|
||||
html = html.Replace("<br>", "\n").Replace("<br/>", "\n").Replace("<br />", "\n");
|
||||
|
||||
// Remove all remaining HTML tags
|
||||
html = System.Text.RegularExpressions.Regex.Replace(html, "<[^>]+>", "");
|
||||
|
||||
// Decode HTML entities
|
||||
html = System.Net.WebUtility.HtmlDecode(html);
|
||||
|
||||
// Remove excess whitespace
|
||||
html = System.Text.RegularExpressions.Regex.Replace(html, @"\s+", " ").Trim();
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
public async Task SendTemplatedEmailAsync<TComponent, TModel>(string? recipientName, string recipientEmail,
|
||||
string subject, TModel model, string fallbackTextBody)
|
||||
string subject, TModel model)
|
||||
where TComponent : IComponent
|
||||
{
|
||||
try
|
||||
{
|
||||
var htmlBody = await _viewRenderer.RenderComponentToStringAsync<TComponent, TModel>(model);
|
||||
var fallbackTextBody = _ConvertHtmlToPlainText(htmlBody);
|
||||
await SendEmailAsync(recipientName, recipientEmail, subject, fallbackTextBody, htmlBody);
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
_logger.LogError(err, "Failed to render email template...");
|
||||
await SendEmailAsync(recipientName, recipientEmail, subject, fallbackTextBody);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
@ -17,23 +17,21 @@ public class RazorViewRenderer(
|
||||
ILogger<RazorViewRenderer> logger
|
||||
)
|
||||
{
|
||||
public async Task<string> RenderComponentToStringAsync<TComponent, TModel>(TModel model)
|
||||
public async Task<string> RenderComponentToStringAsync<TComponent, TModel>(TModel? model)
|
||||
where TComponent : IComponent
|
||||
{
|
||||
await using var htmlRenderer = new HtmlRenderer(serviceProvider, loggerFactory);
|
||||
|
||||
var viewDictionary = new ViewDataDictionary<TModel>(
|
||||
new EmptyModelMetadataProvider(),
|
||||
new ModelStateDictionary())
|
||||
{
|
||||
Model = model
|
||||
};
|
||||
|
||||
|
||||
return await htmlRenderer.Dispatcher.InvokeAsync(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var parameterView = ParameterView.FromDictionary(viewDictionary);
|
||||
var dictionary = model?.GetType().GetProperties()
|
||||
.ToDictionary(
|
||||
prop => prop.Name,
|
||||
prop => prop.GetValue(model, null)
|
||||
) ?? new Dictionary<string, object?>();
|
||||
var parameterView = ParameterView.FromDictionary(dictionary);
|
||||
var output = await htmlRenderer.RenderComponentAsync<TComponent>(parameterView);
|
||||
return output.ToHtmlString();
|
||||
}
|
||||
|
@ -44,9 +44,9 @@ public class MagicSpellService(AppDatabase db, EmailService email, IConfiguratio
|
||||
.FirstOrDefaultAsync();
|
||||
if (contact is null) throw new ArgumentException("Account has no contact method that can use");
|
||||
|
||||
var link = $"${configuration.GetValue<string>("BaseUrl")}/spells/{Uri.EscapeDataString(spell.Spell)}";
|
||||
var link = $"{configuration.GetValue<string>("BaseUrl")}/spells/{Uri.EscapeDataString(spell.Spell)}";
|
||||
|
||||
logger.LogInformation($"Sending magic spell... {link}");
|
||||
logger.LogInformation("Sending magic spell... {Link}", link);
|
||||
|
||||
try
|
||||
{
|
||||
@ -61,8 +61,7 @@ public class MagicSpellService(AppDatabase db, EmailService email, IConfiguratio
|
||||
{
|
||||
Name = contact.Account.Name,
|
||||
VerificationLink = link
|
||||
},
|
||||
$"Thank you for creating an account.\nFor accessing all the features, confirm your registration with the link below:\n\n{link}"
|
||||
}
|
||||
);
|
||||
break;
|
||||
default:
|
||||
|
Reference in New Issue
Block a user