using System.Text; using DigitalData.MessagingService.Application.Common.Dtos; using DigitalData.MessagingService.Application.Common.Interfaces; using DigitalData.MessagingService.Domain.Exceptions; using Limilabs.Client.SMTP; using Limilabs.Mail; using Limilabs.Mail.Headers; using Microsoft.Extensions.Options; namespace DigitalData.MessagingService.Infrastructure.Services; /// /// Email service using Limilabs Mail.dll for SMTP operations (send-only). /// Commercial-grade library with superior Exchange support. /// SMTP configuration is injected via IOptions<EmailAccountDto> from appsettings.json. /// public class LimilabsEmailService( IEncryptionService encryptionService, IOptions smtpConfig) : IEmailService { private readonly EmailAccountDto _smtpAccount = smtpConfig.Value; // Register encoding provider for Limilabs (requires windows-1252 and other code pages) static LimilabsEmailService() { Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); } public async Task SendEmailAsync(string to, string subject, string body, bool isHtml = true, CancellationToken cancellationToken = default) { using var smtp = new Smtp(); try { await ConnectAndAuthenticateSmtpAsync(smtp); var builder = new MailBuilder(); builder.From.Add(new MailBox(_smtpAccount.Username)); builder.To.Add(new MailBox(to)); builder.Subject = subject; if (isHtml) { builder.Html = body; } else { builder.Text = body; } var mail = builder.Create(); var result = smtp.SendMessage(mail); if (result.Status != SendMessageStatus.Success) { throw new InvalidOperationException($"Failed to send email. Status: {result.Status}"); } smtp.Close(); await Task.CompletedTask; // For async consistency } catch (Limilabs.Client.ServerException ex) { DisconnectSafely(smtp); throw new AuthenticationFailedException("SMTP authentication failed. Check credentials or OAuth2 configuration.", ex); } catch (Exception ex) { DisconnectSafely(smtp); throw new InvalidOperationException("Failed to send email via SMTP server.", ex); } } // --- Private Helper Methods --- private async Task ConnectAndAuthenticateSmtpAsync(Smtp smtp) { if (_smtpAccount.SmtpUseSsl) { smtp.ConnectSSL(_smtpAccount.SmtpServer, _smtpAccount.SmtpPort); } else { smtp.Connect(_smtpAccount.SmtpServer, _smtpAccount.SmtpPort); } if (_smtpAccount.UseOAuth2) { throw new NotSupportedException("OAuth2 is not configured for this SMTP account. UseOAuth2 must be false."); } else { var password = _smtpAccount.PasswordEncrypted ? encryptionService.Decrypt(_smtpAccount.Password) : _smtpAccount.Password; smtp.Login(_smtpAccount.Username, password); } await Task.CompletedTask; // For async consistency } private static void DisconnectSafely(Smtp smtp) { try { if (smtp.Connected) smtp.Close(); } catch { /* Ignore disconnect errors */ } } }