Replaced the `EncryptedPassword` property in `EmailAccountDto` with `Password` and `PasswordEncrypted` to support both plain text and encrypted passwords. Updated `LimilabsEmailService` to use the new properties, checking the `PasswordEncrypted` flag to determine whether decryption is needed.
112 lines
3.4 KiB
C#
112 lines
3.4 KiB
C#
using System.Text;
|
|
using DigitalData.EmailProfiler.Application.Common.Dtos;
|
|
using DigitalData.EmailProfiler.Application.Common.Interfaces;
|
|
using DigitalData.EmailProfiler.Domain.Exceptions;
|
|
using Limilabs.Client.SMTP;
|
|
using Limilabs.Mail;
|
|
using Limilabs.Mail.Headers;
|
|
using Microsoft.Extensions.Options;
|
|
|
|
namespace DigitalData.EmailProfiler.Infrastructure.Services;
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
public class LimilabsEmailService(
|
|
IEncryptionService encryptionService,
|
|
IOptions<EmailAccountDto> 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 */ }
|
|
}
|
|
}
|