using EmailApi.Models.Requests; using MailKit.Net.Smtp; using MailKit.Security; using Microsoft.Extensions.Options; using MimeKit; using Models.Settings; namespace EmailApi.Services; public sealed class SmtpEmailDispatcher { private readonly SmtpSettings _smtp; private readonly FileStorageSettings _fileStorage; private readonly ILogger _log; private readonly string _environmentName; private static readonly string HtmlShellStart = """

myAi

"""; private static readonly string HtmlShellEnd = """
Automated message from myAi.
"""; public SmtpEmailDispatcher( IOptions smtp, IOptions fileStorage, ILogger log) { _smtp = smtp.Value; _fileStorage = fileStorage.Value; _log = log; _environmentName = Environment.GetEnvironmentVariable("APP_ENVIRONMENT_NAME") ?? "Development"; } public async Task SendAsync(SendEmailRequest req, CancellationToken ct) { if (string.IsNullOrWhiteSpace(_smtp.Host)) { _log.LogWarning("SMTP host not configured — email skipped (to: {To})", string.Join(", ", req.To)); return; } var msg = new MimeMessage(); msg.From.Add(MailboxAddress.Parse(_smtp.Username)); foreach (var to in req.To) msg.To.Add(MailboxAddress.Parse(to)); if (!string.IsNullOrWhiteSpace(req.ReplyTo)) msg.ReplyTo.Add(MailboxAddress.Parse(req.ReplyTo)); msg.Subject = $"[{_environmentName}] {req.Subject}".Trim(); var builder = new BodyBuilder { HtmlBody = HtmlShellStart + req.HtmlBody + HtmlShellEnd }; if (!string.IsNullOrWhiteSpace(req.AttachmentPath)) { var fullPath = Path.Combine(_fileStorage.Path, req.AttachmentPath); if (File.Exists(fullPath)) { builder.Attachments.Add(fullPath); _log.LogDebug("Attachment added: {Path}", fullPath); } else { _log.LogWarning("Attachment not found, skipping: {Path}", fullPath); } } msg.Body = builder.ToMessageBody(); _log.LogInformation("Sending email to {Recipients} subject {Subject}", string.Join(", ", req.To), req.Subject); using var client = new SmtpClient(); var tls = _smtp.UseStartTls ? SecureSocketOptions.StartTls : SecureSocketOptions.Auto; await client.ConnectAsync(_smtp.Host, _smtp.Port, tls, ct); if (!string.IsNullOrWhiteSpace(_smtp.Username)) await client.AuthenticateAsync(_smtp.Username, _smtp.Password, ct); await client.SendAsync(msg, ct); await client.DisconnectAsync(true, ct); _log.LogInformation("Email sent successfully to {Recipients}", string.Join(", ", req.To)); } }