package email import ( "testing" "github.com/stretchr/testify/assert" "go.uber.org/zap" "go.uber.org/zap/zapcore" "go.uber.org/zap/zaptest/observer" ) // clearAllSMTPEnv zeroes every SMTP-related env var (canonical + deprecated) // so each test starts from a known blank slate. t.Setenv guarantees restore. func clearAllSMTPEnv(t *testing.T) { t.Helper() for _, k := range []string{ "SMTP_HOST", "SMTP_PORT", "SMTP_PASSWORD", "SMTP_USERNAME", "SMTP_FROM", "SMTP_FROM_NAME", "SMTP_USER", "FROM_EMAIL", "FROM_NAME", } { t.Setenv(k, "") } } func TestLoadSMTPConfig_EmptyWhenNothingSet(t *testing.T) { clearAllSMTPEnv(t) cfg := LoadSMTPConfigFromEnv() assert.Empty(t, cfg.Host, "Host must stay empty so callers can log-only") assert.Empty(t, cfg.Port) assert.Empty(t, cfg.Username) assert.Empty(t, cfg.From) assert.Empty(t, cfg.FromName) } func TestLoadSMTPConfig_CanonicalNamesReadDirectly(t *testing.T) { clearAllSMTPEnv(t) t.Setenv("SMTP_HOST", "mailhog") t.Setenv("SMTP_PORT", "1025") t.Setenv("SMTP_USERNAME", "veza-api") t.Setenv("SMTP_PASSWORD", "supersecret") t.Setenv("SMTP_FROM", "no-reply@veza.fm") t.Setenv("SMTP_FROM_NAME", "Veza") cfg := LoadSMTPConfigFromEnv() assert.Equal(t, "mailhog", cfg.Host) assert.Equal(t, "1025", cfg.Port) assert.Equal(t, "veza-api", cfg.Username) assert.Equal(t, "supersecret", cfg.Password) assert.Equal(t, "no-reply@veza.fm", cfg.From) assert.Equal(t, "Veza", cfg.FromName) } func TestLoadSMTPConfig_DeprecatedNamesFallBack(t *testing.T) { clearAllSMTPEnv(t) // Only the pre-v1.0.6 env vars are set. t.Setenv("SMTP_USER", "legacy-user") t.Setenv("FROM_EMAIL", "legacy@veza.fm") t.Setenv("FROM_NAME", "Legacy Veza") core, observed := observer.New(zapcore.WarnLevel) cfg := LoadSMTPConfigFromEnvWithLogger(zap.New(core)) assert.Equal(t, "legacy-user", cfg.Username, "fallback must pick up SMTP_USER when SMTP_USERNAME is empty") assert.Equal(t, "legacy@veza.fm", cfg.From) assert.Equal(t, "Legacy Veza", cfg.FromName) entries := observed.All() assert.Len(t, entries, 3, "one warning per deprecated var in use") seen := map[string]bool{} for _, e := range entries { for _, f := range e.Context { if f.Key == "deprecated" { seen[f.String] = true } } } assert.True(t, seen["SMTP_USER"]) assert.True(t, seen["FROM_EMAIL"]) assert.True(t, seen["FROM_NAME"]) } func TestLoadSMTPConfig_CanonicalWinsOverDeprecated(t *testing.T) { clearAllSMTPEnv(t) t.Setenv("SMTP_USERNAME", "canonical-user") t.Setenv("SMTP_USER", "legacy-user-ignored") t.Setenv("SMTP_FROM", "canonical@veza.fm") t.Setenv("FROM_EMAIL", "legacy@veza.fm") core, observed := observer.New(zapcore.WarnLevel) cfg := LoadSMTPConfigFromEnvWithLogger(zap.New(core)) assert.Equal(t, "canonical-user", cfg.Username) assert.Equal(t, "canonical@veza.fm", cfg.From) assert.Equal(t, 0, observed.Len(), "no warning should fire when canonical is set — deprecated vars are ignored silently") } func TestLoadSMTPConfig_NilLoggerIsAllowed(t *testing.T) { clearAllSMTPEnv(t) t.Setenv("SMTP_USER", "legacy") assert.NotPanics(t, func() { _ = LoadSMTPConfigFromEnv() }) cfg := LoadSMTPConfigFromEnv() assert.Equal(t, "legacy", cfg.Username) }