Пункт 2 + 3 пакета SMTP-настроек.
Backend:
- IEmailSender (Application/Common/Email) — общий интерфейс отправки
одного письма; EmailNotConfiguredException — для контроллеров чтобы
ловить и отдавать понятный 400 вместо 500.
- MailKitEmailSender (Infrastructure/Email) — реализация:
· регистрируется Singleton, на каждой отправке открывает scope для
свежего AppDbContext (конфиг перечитывается без рестарта);
· читает PlatformSettings из БД, расшифровывает пароль через
IDataProtector("foodmarket.smtp");
· поддержка SmtpUseSsl (implicit TLS / 465) и SmtpStartTls (587);
оба false → открытое соединение (для dev/MailHog);
· бросает EmailNotConfiguredException если host или from-email пусты,
или если расшифровка пароля падает (ключ DataProtection ротировался).
API:
- PlatformSettingsController:
GET /api/super-admin/platform-settings — все поля КРОМЕ пароля
(только has-password флаг + updatedAt).
PUT — принимает Reason (≥10) + все поля + опциональный
NewSmtpPassword. Спец-значение "__clear__" снимает пароль.
Пароль шифруется через DataProtection при записи. Audit-log.
POST /test-send — реальная отправка через текущие настройки;
ловит EmailNotConfiguredException → 400, остальные → 500
с message (SuperAdmin-only, diagnostic-info нужна).
DI:
- AddSingleton<IEmailSender, MailKitEmailSender>;
- AddDataProtection (default file-system key store ASP.NET Core).
Пакеты:
- MailKit 4.10.0 (4.8 имел moderate-severity advisory).
- Microsoft.AspNetCore.DataProtection 8.0.11 (transitive в API уже
был через OpenIddict, но Infrastructure нужен явный reference).
65 lines
3.4 KiB
XML
65 lines
3.4 KiB
XML
<Project>
|
|
<PropertyGroup>
|
|
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
|
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
|
|
</PropertyGroup>
|
|
|
|
<ItemGroup>
|
|
<!-- ASP.NET Core 8 -->
|
|
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.11" />
|
|
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="8.0.11" />
|
|
<PackageVersion Include="Microsoft.AspNetCore.SignalR" Version="1.2.0" />
|
|
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.9.0" />
|
|
|
|
<!-- EF Core 8 + PostgreSQL -->
|
|
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.11" />
|
|
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.11" />
|
|
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.11" />
|
|
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.11" />
|
|
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.10" />
|
|
|
|
<!-- OpenIddict 5 (aligned to .NET 8 LTS) -->
|
|
<PackageVersion Include="OpenIddict.AspNetCore" Version="5.8.0" />
|
|
<PackageVersion Include="OpenIddict.EntityFrameworkCore" Version="5.8.0" />
|
|
|
|
<!-- Identity -->
|
|
<PackageVersion Include="Microsoft.AspNetCore.Identity" Version="2.3.1" />
|
|
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.11" />
|
|
|
|
<!-- App services -->
|
|
<PackageVersion Include="MailKit" Version="4.10.0" />
|
|
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="8.0.11" />
|
|
<PackageVersion Include="MediatR" Version="12.4.1" />
|
|
<PackageVersion Include="FluentValidation" Version="11.11.0" />
|
|
<PackageVersion Include="FluentValidation.DependencyInjectionExtensions" Version="11.11.0" />
|
|
<PackageVersion Include="Mapster" Version="7.4.0" />
|
|
<PackageVersion Include="Mapster.DependencyInjection" Version="1.0.1" />
|
|
<PackageVersion Include="Serilog.AspNetCore" Version="8.0.3" />
|
|
<PackageVersion Include="Serilog.Sinks.Console" Version="6.0.0" />
|
|
<PackageVersion Include="Serilog.Sinks.File" Version="6.0.0" />
|
|
|
|
<!-- Background jobs -->
|
|
<PackageVersion Include="Hangfire.AspNetCore" Version="1.8.17" />
|
|
<PackageVersion Include="Hangfire.PostgreSql" Version="1.20.10" />
|
|
|
|
<!-- POS: local storage + API client -->
|
|
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.11" />
|
|
<PackageVersion Include="Refit" Version="7.2.22" />
|
|
<PackageVersion Include="Refit.HttpClientFactory" Version="7.2.22" />
|
|
<PackageVersion Include="Polly" Version="8.5.0" />
|
|
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
|
|
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
|
<PackageVersion Include="System.IO.Ports" Version="8.0.0" />
|
|
|
|
<!-- Testing -->
|
|
<PackageVersion Include="xunit" Version="2.9.3" />
|
|
<PackageVersion Include="xunit.runner.visualstudio" Version="3.0.1" />
|
|
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
|
<PackageVersion Include="FluentAssertions" Version="7.0.0" />
|
|
<PackageVersion Include="NSubstitute" Version="5.3.0" />
|
|
<PackageVersion Include="coverlet.collector" Version="6.0.3" />
|
|
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.11" />
|
|
<PackageVersion Include="Testcontainers.PostgreSql" Version="4.1.0" />
|
|
</ItemGroup>
|
|
</Project>
|