207 lines
4.4 KiB
Go
207 lines
4.4 KiB
Go
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
|
|
}
|
|
}
|