Przejdź do treści

TailoredApps.Shared.Email

NuGet License: MIT


Opis

Biblioteka dostarcza kompletną abstrakcję do wysyłania wiadomości e-mail w aplikacjach .NET. Opiera się na interfejsie IEmailProvider, który możesz wymieniać w zależności od środowiska — w produkcji używasz SmtpEmailProvider (wysyłka przez SMTP), w lokalnym środowisku deweloperskim EmailServiceToConsoleWriter (wypisuje do konsoli bez wysyłki).

Biblioteka zawiera też system budowania treści emaili oparty na szablonach (IMailMessageBuilder), który obsługuje proste podstawianie tokenów (DefaultMessageBuilder) lub szablony ładowane z pliku z placeholderami {{token}} (TokenReplacingMailMessageBuilder).

Wbudowane zabezpieczenie przed przypadkowym spamem w środowiskach nieprodukcyjnych: kiedy IsProd = false, wszystkie emaile trafiają na adres CatchAll zamiast do prawdziwych odbiorców.


Instalacja

dotnet add package TailoredApps.Shared.Email

Rejestracja w DI

// Program.cs
using TailoredApps.Shared.Email;

// Rejestracja SMTP provider
builder.Services.RegisterSmtpProvider();

// Opcjonalnie: rejestracja buildera szablonów
builder.Services.AddTransient<IMailMessageBuilder, TokenReplacingMailMessageBuilder>();
builder.Services.Configure<TokenReplacingMailMessageBuilderOptions>(options =>
{
    options.Location = Path.Combine(builder.Environment.ContentRootPath, "EmailTemplates");
    options.FileExtension = "html";
});
// Program.cs
builder.Services.RegisterConsoleProvider();

Konfiguracja appsettings.json

{
  "Mail": {
    "Providers": {
      "Smtp": {
        "Host": "smtp.example.com",
        "Port": 587,
        "UserName": "noreply@example.com",
        "Password": "secret",
        "From": "noreply@example.com",
        "EnableSsl": true,
        "IsProd": true,
        "CatchAll": "dev@example.com"
      }
    }
  }
}

Przykład użycia

public class NotificationService
{
    private readonly IEmailProvider _emailProvider;
    private readonly IMailMessageBuilder _messageBuilder;

    public NotificationService(
        IEmailProvider emailProvider,
        IMailMessageBuilder messageBuilder)
    {
        _emailProvider = emailProvider;
        _messageBuilder = messageBuilder;
    }

    public async Task SendWelcomeEmailAsync(string recipientEmail, string userName)
    {
        var body = _messageBuilder.Build(
            templateKey: "welcome.html",
            variables: new Dictionary<string, string>
            {
                { "UserName", userName },
                { "AppUrl", "https://myapp.example.com" }
            },
            templates: null  // załaduje z pliku, jeśli skonfigurowano Location
        );

        var messageId = await _emailProvider.SendMail(
            recipnet: recipientEmail,
            topic: "Witaj w MyApp!",
            messageBody: body,
            attachments: null
        );

        Console.WriteLine($"Email sent, MessageId: {messageId}");
    }

    public async Task SendInvoiceAsync(
        string recipientEmail,
        string subject,
        string htmlBody,
        byte[] pdfBytes)
    {
        await _emailProvider.SendMail(
            recipnet: recipientEmail,
            topic: subject,
            messageBody: htmlBody,
            attachments: new Dictionary<string, byte[]>
            {
                { "faktura.pdf", pdfBytes }
            }
        );
    }
}

Szablon e-mail (welcome.html)

<!DOCTYPE html>
<html>
<body>
  <h1>Witaj, {{UserName}}!</h1>
  <p>Twoje konto zostało założone. <a href="{{AppUrl}}">Kliknij tutaj</a> by się zalogować.</p>
</body>
</html>

API Reference

Typ Rodzaj Opis
IEmailProvider Interfejs Główny kontrakt: SendMail, GetMail
SmtpEmailProvider Klasa Wysyłka przez SMTP; opcje z SmtpEmailServiceOptions
EmailServiceToConsoleWriter Klasa Wypisuje dane emaila do konsoli (dev/test)
SmtpEmailServiceOptions Klasa Konfiguracja SMTP: Host, Port, UserName, Password, From, IsProd, CatchAll
IMailMessageBuilder Interfejs Kontrakt: Build(templateKey, variables, templates)
DefaultMessageBuilder Klasa Podstawia tokeny w słowniku szablonów
TokenReplacingMailMessageBuilder Klasa Ładuje szablony z systemu plików; placeholdery {{token}}
TokenReplacingMailMessageBuilderOptions Klasa Location (ścieżka do katalogu szablonów), FileExtension
SmtpEmailProviderExtensions.RegisterSmtpProvider Metoda ext. Rejestruje SmtpEmailProvider w DI
SmtpEmailProviderExtensions.RegisterConsoleProvider Metoda ext. Rejestruje EmailServiceToConsoleWriter w DI

🤖 AI Agent Prompt

## TailoredApps.Shared.Email — Instrukcja dla agenta AI

Używasz biblioteki TailoredApps.Shared.Email w projekcie .NET.

### Rejestracja
```csharp
// Produkcja (SMTP):
builder.Services.RegisterSmtpProvider();

// Development (konsola):
builder.Services.RegisterConsoleProvider();

// Builder szablonów (opcjonalnie):
builder.Services.AddTransient<IMailMessageBuilder, TokenReplacingMailMessageBuilder>();
builder.Services.Configure<TokenReplacingMailMessageBuilderOptions>(o => {
    o.Location = "EmailTemplates/";
    o.FileExtension = "html";
});

appsettings.json

"Mail": { "Providers": { "Smtp": {
  "Host": "smtp.host.com", "Port": 587, "UserName": "user",
  "Password": "pass", "From": "no-reply@app.com",
  "EnableSsl": true, "IsProd": true, "CatchAll": "dev@app.com"
}}}

Użycie

// Wstrzyknij IEmailProvider + IMailMessageBuilder
var body = _builder.Build("template.html", variables, null);
await _emailProvider.SendMail(email, subject, body, attachments);

Zasady

  • Gdy IsProd=false, wszystkie emaile trafiają na CatchAll — nigdy do prawdziwych odbiorców
  • Do testów wstrzyknij IEmailProvider jako mock lub użyj RegisterConsoleProvider
  • Placeholdery w szablonach TokenReplacing: {{NazwaTokena}}
  • Załączniki: słownik fileName → byte[] ```