feat(PROJ-28): SMTP-Out Relay — DB-Konfiguration + Admin-Tab
- smtpoutconfig.Store: AES-256-GCM verschlüsseltes Passwort in DB (id=1 Singleton) - Mailer: Reload() für Runtime-Konfigurationswechsel (sync.RWMutex) - API: GET/PUT/DELETE /api/admin/smtp-out + POST /api/admin/smtp-out/test - Admin-Tab: Host, Port, User, Passwort, TLS-Switch, From, Test-Button, Status-Badge - Startup: Lädt DB-Konfiguration und aktiviert Mailer ohne Restart Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -31,6 +31,7 @@ import (
|
||||
ldapcfg "github.com/archivmail/internal/ldapconfig"
|
||||
"github.com/archivmail/internal/mailer"
|
||||
pop3store "github.com/archivmail/internal/pop3"
|
||||
"github.com/archivmail/internal/smtpoutconfig"
|
||||
"github.com/archivmail/internal/smtpd"
|
||||
"github.com/archivmail/internal/storage"
|
||||
tenantstore "github.com/archivmail/internal/tenantstore"
|
||||
@@ -185,6 +186,28 @@ func main() {
|
||||
|
||||
// PROJ-28: Self-Service Onboarding — mailer + token store + FQDN
|
||||
mlr := mailer.New(cfg.SMTPOut)
|
||||
|
||||
// SMTP-Out config store — load from DB, overrides config.yml if present
|
||||
smtpOutSt, err := smtpoutconfig.New(cfg.Database.DSN(), cfg.API.Secret)
|
||||
if err != nil {
|
||||
logger.Error("smtp-out config store init failed", "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer smtpOutSt.Close()
|
||||
srv.SetSMTPOutStore(smtpOutSt)
|
||||
// Override config.yml settings with DB config if available
|
||||
if dbCfg, err := smtpOutSt.GetWithPassword(context.Background()); err == nil && dbCfg != nil && dbCfg.Enabled {
|
||||
mlr.Reload(config.SMTPOutConfig{
|
||||
Host: dbCfg.Host,
|
||||
Port: dbCfg.Port,
|
||||
User: dbCfg.User,
|
||||
Password: dbCfg.Password,
|
||||
TLS: dbCfg.TLS,
|
||||
From: dbCfg.From,
|
||||
})
|
||||
logger.Info("smtp_out: loaded from database")
|
||||
}
|
||||
|
||||
srv.SetMailer(mlr)
|
||||
srv.SetFQDN(cfg.Server.FQDN)
|
||||
if cfg.Server.FQDN == "" {
|
||||
|
||||
Reference in New Issue
Block a user