using System.Net.Http.Headers; using System.Text; using System.Text.Json; using Socialize.Api.Infrastructure.Emailer.Configuration; using Socialize.Api.Infrastructure.Emailer.Contracts; using Microsoft.Extensions.Options; namespace Socialize.Api.Infrastructure.Emailer.Services; public class ResendEmailSender : IEmailSender { private static readonly Uri EndpointUri = new("https://api.resend.com/emails"); private readonly HttpClient _httpClient; private readonly EmailerOptions _options; public ResendEmailSender( IHttpClientFactory httpClientFactory, IOptions options) { _httpClient = httpClientFactory.CreateClient(); _options = options.Value; string apiKey = NormalizeApiKey(_options.ApiKey); string fromEmail = _options.FromEmail?.Trim() ?? string.Empty; if (string.IsNullOrWhiteSpace(apiKey)) { throw new InvalidOperationException("Emailer:ApiKey is required when using Resend email delivery."); } if (string.IsNullOrWhiteSpace(fromEmail)) { throw new InvalidOperationException("Emailer:FromEmail is required when using Resend email delivery."); } _options.ApiKey = apiKey; _options.FromEmail = fromEmail; _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey); _httpClient.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json")); } public async Task SendEmailAsync(string toEmail, string subject, string htmlMessage) { var payload = new { from = _options.FromEmail, to = toEmail, subject, html = htmlMessage }; string json = JsonSerializer.Serialize(payload); StringContent content = new(json, Encoding.UTF8, "application/json"); HttpResponseMessage response = await _httpClient.PostAsync(EndpointUri, content); if (!response.IsSuccessStatusCode) { string body = await response.Content.ReadAsStringAsync(); throw new InvalidOperationException( $"Resend email failed: {response.StatusCode} - {body}"); } } private static string NormalizeApiKey(string? apiKey) { string normalized = apiKey?.Trim().Trim('"', '\'') ?? string.Empty; const string bearerPrefix = "Bearer "; if (normalized.StartsWith(bearerPrefix, StringComparison.OrdinalIgnoreCase)) { normalized = normalized[bearerPrefix.Length..].Trim(); } return normalized; } }