package config import ( "errors" "fmt" "time" ) type SMTPConfig struct { Enable bool Sort int GoroutinePoolNum int Host string Port int Username string Password string } // Validate 驗證 SMTP 配置 func (c *SMTPConfig) Validate() error { if !c.Enable { return nil // 未啟用則不驗證 } if c.Host == "" { return errors.New("smtp host is required") } if c.Port <= 0 || c.Port > 65535 { return fmt.Errorf("smtp port must be between 1 and 65535, got %d", c.Port) } if c.Username == "" { return errors.New("smtp username is required") } if c.Password == "" { return errors.New("smtp password is required") } if c.Sort < 0 { return fmt.Errorf("smtp sort must be >= 0, got %d", c.Sort) } return nil } type AmazonSesSettings struct { Enable bool Sort int PoolSize int Region string Sender string Charset string AccessKey string SecretKey string Token string } // Validate 驗證 AWS SES 配置 func (c *AmazonSesSettings) Validate() error { if !c.Enable { return nil // 未啟用則不驗證 } if c.Region == "" { return errors.New("aws ses region is required") } if c.Sender == "" { return errors.New("aws ses sender is required") } if c.AccessKey == "" { return errors.New("aws ses access key is required") } if c.SecretKey == "" { return errors.New("aws ses secret key is required") } if c.Sort < 0 { return fmt.Errorf("aws ses sort must be >= 0, got %d", c.Sort) } if c.PoolSize < 0 { return fmt.Errorf("aws ses pool size must be >= 0, got %d", c.PoolSize) } return nil } type MitakeSMSSender struct { Enable bool Sort int PoolSize int User string Password string } // Validate 驗證 Mitake SMS 配置 func (c *MitakeSMSSender) Validate() error { if !c.Enable { return nil // 未啟用則不驗證 } if c.User == "" { return errors.New("mitake user is required") } if c.Password == "" { return errors.New("mitake password is required") } if c.Sort < 0 { return fmt.Errorf("mitake sort must be >= 0, got %d", c.Sort) } if c.PoolSize < 0 { return fmt.Errorf("mitake pool size must be >= 0, got %d", c.PoolSize) } return nil } // DeliveryConfig 傳送重試配置 type DeliveryConfig struct { MaxRetries int `json:"max_retries"` // 最大重試次數 InitialDelay time.Duration `json:"initial_delay"` // 初始重試延遲 (100ms) BackoffFactor float64 `json:"backoff_factor"` // 指數退避因子 (2.0) MaxDelay time.Duration `json:"max_delay"` // 最大延遲時間 Timeout time.Duration `json:"timeout"` // 單次發送超時時間 EnableHistory bool `json:"enable_history"` // 是否啟用歷史記錄 } // Validate 驗證 DeliveryConfig 配置 func (c *DeliveryConfig) Validate() error { if c.MaxRetries < 0 { return fmt.Errorf("max_retries must be >= 0, got %d", c.MaxRetries) } if c.MaxRetries > 10 { return fmt.Errorf("max_retries should not exceed 10, got %d", c.MaxRetries) } if c.InitialDelay < 0 { return fmt.Errorf("initial_delay must be >= 0, got %v", c.InitialDelay) } if c.InitialDelay > 10*time.Second { return fmt.Errorf("initial_delay is too large (> 10s), got %v", c.InitialDelay) } if c.BackoffFactor < 1.0 { return fmt.Errorf("backoff_factor must be >= 1.0, got %v", c.BackoffFactor) } if c.BackoffFactor > 10.0 { return fmt.Errorf("backoff_factor is too large (> 10.0), got %v", c.BackoffFactor) } if c.MaxDelay < 0 { return fmt.Errorf("max_delay must be >= 0, got %v", c.MaxDelay) } if c.MaxDelay > 5*time.Minute { return fmt.Errorf("max_delay is too large (> 5m), got %v", c.MaxDelay) } if c.Timeout <= 0 { return fmt.Errorf("timeout must be > 0, got %v", c.Timeout) } if c.Timeout > 5*time.Minute { return fmt.Errorf("timeout is too large (> 5m), got %v", c.Timeout) } // 檢查 InitialDelay 和 MaxDelay 的關係 if c.InitialDelay > c.MaxDelay && c.MaxDelay > 0 { return fmt.Errorf("initial_delay (%v) should not exceed max_delay (%v)", c.InitialDelay, c.MaxDelay) } return nil } // SetDefaults 設置默認值 func (c *DeliveryConfig) SetDefaults() { if c.MaxRetries == 0 { c.MaxRetries = 3 } if c.InitialDelay == 0 { c.InitialDelay = 100 * time.Millisecond } if c.BackoffFactor == 0 { c.BackoffFactor = 2.0 } if c.MaxDelay == 0 { c.MaxDelay = 30 * time.Second } if c.Timeout == 0 { c.Timeout = 30 * time.Second } }