namespace foodmarket.Application.Common.Email; /// Отправка одного письма через текущие платформенные SMTP-настройки. /// Конфиг читается из БД (PlatformSettings) на каждой отправке — без рестарта /// сервиса можно поменять SMTP-сервер. Реализация — MailKit. public interface IEmailSender { Task SendAsync(string toEmail, string subject, string body, CancellationToken ct = default); /// HTML-версия с опциональным plain-text fallback. Используется /// шаблонизированными письмами (приглашения, weekly-summary, low-stock). /// Если null — клиент должен сам уметь /// рендерить HTML; для большинства современных clients это не проблема. Task SendHtmlAsync(string toEmail, string subject, string htmlBody, string? textBody = null, CancellationToken ct = default); } /// Бросается когда платформенный SMTP не настроен. Контроллеры должны /// ловить и возвращать понятный 503/400 — не падать в 500. public class EmailNotConfiguredException : Exception { public EmailNotConfiguredException(string message) : base(message) { } }