ITLab.Template.DevPack.Notifications.Email
Email contracts for transactional messaging. The DevPack ships only the contracts (service, renderer, repository) and the typed options; concrete senders, the rendering engine and template storage live in the consumer. See ADR-009.
Componentes
| Tipo | Nome | Responsabilidade |
|---|---|---|
| Interface | IEmailService | Send contract: three SendAsync overloads (single/multi recipient, attachments) plus SendFromTemplateAsync |
| Interface | IEmailTemplateRenderer | Renders a template body against placeholder data, optionally wrapped in a layout |
| Interface | IEmailTemplateRepository | Resolves template content by key, optionally scoped to a tenant |
Related types: Dtos/EmailResult (send outcome), Dtos/EmailAttachment (binary attachment),
AppSettings/EmailOptions (+ SmtpOptions, SendGridOptions).
Como usar
// In the consumer: implement the contracts and select the sender by EmailOptions.Provider.
services.AddOptions<EmailOptions>()
.BindConfiguration(EmailOptions.ConfigSectionPath)
.ValidateOnStart();
services.AddSingleton<IEmailTemplateRenderer, HtmlEmailTemplateRenderer>();
services.AddSingleton<IEmailTemplateRepository, FileSystemEmailTemplateRepository>();
var provider = configuration.GetValue<string>($"{EmailOptions.ConfigSectionPath}:Provider") ?? "Smtp";
if (provider.Equals("SendGrid", StringComparison.OrdinalIgnoreCase))
services.AddScoped<IEmailService, SendGridEmailService>();
else
services.AddScoped<IEmailService, SmtpEmailService>();
// Sending a templated message.
await emailService.SendFromTemplateAsync(
templateKey: "Auth/welcome",
data: new Dictionary<string, object> { ["user.name"] = "Ada" },
subject: "Welcome",
destination: ["ada@example.com"],
ct: cancellationToken);
Tipos de
data:IEmailService.SendFromTemplateAsyncaceitaIDictionary<string, object>(placeholders sempre têm valor). O renderer aceitaIDictionary<string, object?>— a impl do consumidor injeta valores derivados (subject,year, ...) e repassa, tolerandonull.
O que não fazer
- Do not put delivery logic (SMTP clients, SDK calls, retry policies) behind these interfaces in the DevPack — they are contracts only.
- Do not couple the repository to a delivery channel enum; this is an HTML-only email repository.
- Do not block on async work (no
GetAwaiter().GetResult()); select the sender via DI, not a sync factory.
Extensão pelo produto
- Products implement
IEmailService(SMTP/SendGrid/...),IEmailTemplateRenderer(HTML placeholder engine) andIEmailTemplateRepository(file system, database, ...). - Products can scope templates per tenant via the
tenantIdargument, with fallback to a default set.