src/DiyanetCleanArchitecture.Infrastructure.Services.Email projesindedir. İki katmandan oluşur:
EmailService : IEmailService— şablon render (Scriban), ortam bazlı adres yönlendirme, üst-seviye API.ResilientEmailGateway : IResilientEmailGateway— MailKit ile SMTP gönderimi, Polly retry + circuit-breaker.
Arayüz
SendBackground, Task.Run içinde SendAsync’i çağırır; hata olursa loglar ama fırlatmaz — login akışı gibi kullanıcıyı bekletmemesi gereken yerlerde kullanılır.
Şablonlar — Scriban
ŞablonlarTemplates/*.html altında tutulur ve Scriban ile render edilir. Hangi dosyanın kullanılacağı EmailTemplateType enumeration’ı belirler:
Name aynı zamanda dosya adıdır. Render sırasında dosya AppContext.BaseDirectory/Templates/{Name}.html yolundan okunur (Docker/K8s’te path güvenliği için AppContext.BaseDirectory kullanılır):
Şablon HTML dosyalarının çıktıya kopyalanması için
.csproj’da CopyToOutputDirectory ayarı gerekir; aksi halde AppContext.BaseDirectory/Templates altında bulunamaz.Ortam bazlı adres yönlendirme
Production dışı ortamlarda gerçek alıcıya gönderim yapılmaz — gerçek müşterilere yanlışlıkla mail gitmesini engellemek için tüm gönderimServices:Email:Mails[] listesindeki test adreslerine yönlendirilir:
Cc ve Bcc adresleri ise hem çağrıdan gelen hem de config’teki değerlerin birleşiminden (distinct) oluşur.
ResilientEmailGateway — MailKit + Polly
Gerçek gönderiminternal ResilientEmailGateway içinde olur. MailKit SmtpClient ile bağlanır; EnableSsl true ise SslOnConnect, değilse StartTls kullanılır (Brevo için StartTls önerilir):
PolicyWrap içinde çalışır:
Config — Services:Email
string
Brevo SMTP relay (
smtp-relay.brevo.com).int
default:"25"
SMTP portu — Brevo için 587.
bool
true → SslOnConnect, false → StartTls.string
Hem SMTP login hem de gönderen adresi (From) olarak kullanılır.
string
Brevo SMTP Key.
int
default:"2"
Polly retry sayısı (exponential backoff).
string[]
Production dışı ortamlarda tüm mailler bu adreslere yönlendirilir.
DI kaydı
Kullanım
OTP e-postası gönderimi,UserOtpGeneratedDomainEvent dinleyen bir domain event handler içinde yapılır (örn. SendOtpEmailDomainEventHandler). Login gibi kritik akışlarda fire-and-forget tercih edilir:
SMS Servisi
OTP’nin SMS kanalı — NetGSM REST v2.
Domain Events
E-posta gönderimini tetikleyen
UserOtpGenerated event akışı.