mirror of
https://github.com/jhillyerd/inbucket.git
synced 2025-12-20 02:57:05 +00:00
Begin work on message retention
- Refactor datastore such that we have a FileDataStore that implements the DataStore interface. - Add in missing SMTP configuration options: max recips, max idle, max message size - Add retention options to config
This commit is contained in:
149
config/config.go
149
config/config.go
@@ -12,9 +12,12 @@ import (
|
||||
// SmtpConfig houses the SMTP server configuration - not using pointers
|
||||
// so that I can pass around copies of the object safely.
|
||||
type SmtpConfig struct {
|
||||
Ip4address net.IP
|
||||
Ip4port int
|
||||
Domain string
|
||||
Ip4address net.IP
|
||||
Ip4port int
|
||||
Domain string
|
||||
MaxRecipients int
|
||||
MaxIdleSeconds int
|
||||
MaxMessageBytes int
|
||||
}
|
||||
|
||||
type WebConfig struct {
|
||||
@@ -25,11 +28,21 @@ type WebConfig struct {
|
||||
PublicDir string
|
||||
}
|
||||
|
||||
var smtpConfig *SmtpConfig
|
||||
type DataStoreConfig struct {
|
||||
Path string
|
||||
RetentionMinutes int
|
||||
RetentionSleep int
|
||||
}
|
||||
|
||||
var webConfig *WebConfig
|
||||
var (
|
||||
// Global goconfig object
|
||||
Config *config.Config
|
||||
|
||||
var Config *config.Config
|
||||
// Parsed specific configs
|
||||
smtpConfig *SmtpConfig
|
||||
webConfig *WebConfig
|
||||
dataStoreConfig *DataStoreConfig
|
||||
)
|
||||
|
||||
// GetSmtpConfig returns a copy of the SmtpConfig object
|
||||
func GetSmtpConfig() SmtpConfig {
|
||||
@@ -41,6 +54,11 @@ func GetWebConfig() WebConfig {
|
||||
return *webConfig
|
||||
}
|
||||
|
||||
// GetDataStoreConfig returns a copy of the DataStoreConfig object
|
||||
func GetDataStoreConfig() DataStoreConfig {
|
||||
return *dataStoreConfig
|
||||
}
|
||||
|
||||
// LoadConfig loads the specified configuration file into inbucket.Config
|
||||
// and performs validations on it.
|
||||
func LoadConfig(filename string) error {
|
||||
@@ -70,12 +88,19 @@ func LoadConfig(filename string) error {
|
||||
requireOption(messages, "smtp", "ip4.address")
|
||||
requireOption(messages, "smtp", "ip4.port")
|
||||
requireOption(messages, "smtp", "domain")
|
||||
requireOption(messages, "smtp", "max.recipients")
|
||||
requireOption(messages, "smtp", "max.idle.seconds")
|
||||
requireOption(messages, "smtp", "max.message.bytes")
|
||||
requireOption(messages, "web", "ip4.address")
|
||||
requireOption(messages, "web", "ip4.port")
|
||||
requireOption(messages, "web", "template.dir")
|
||||
requireOption(messages, "web", "template.cache")
|
||||
requireOption(messages, "web", "public.dir")
|
||||
requireOption(messages, "datastore", "path")
|
||||
requireOption(messages, "datastore", "retention.minutes")
|
||||
requireOption(messages, "datastore", "retention.sleep.millis")
|
||||
|
||||
// Return error if validations failed
|
||||
if messages.Len() > 0 {
|
||||
fmt.Fprintln(os.Stderr, "Error(s) validating configuration:")
|
||||
for e := messages.Front(); e != nil; e = e.Next() {
|
||||
@@ -96,15 +121,17 @@ func LoadConfig(filename string) error {
|
||||
|
||||
// parseLoggingConfig trying to catch config errors early
|
||||
func parseLoggingConfig() error {
|
||||
option := "[logging]level"
|
||||
str, err := Config.String("logging", "level")
|
||||
section := "logging"
|
||||
|
||||
option := "level"
|
||||
str, err := Config.String(section, option)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to parse %v: %v", option, err)
|
||||
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
||||
}
|
||||
switch strings.ToUpper(str) {
|
||||
case "TRACE", "INFO", "WARN", "ERROR":
|
||||
default:
|
||||
return fmt.Errorf("Invalid value provided for %v: %v", option, str)
|
||||
return fmt.Errorf("Invalid value provided for [%v]%v: '%v'", section, option, str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -112,89 +139,135 @@ func parseLoggingConfig() error {
|
||||
// parseSmtpConfig trying to catch config errors early
|
||||
func parseSmtpConfig() error {
|
||||
smtpConfig = new(SmtpConfig)
|
||||
section := "smtp"
|
||||
|
||||
// Parse IP4 address only, error on IP6.
|
||||
option := "[smtp]ip4.address"
|
||||
str, err := Config.String("smtp", "ip4.address")
|
||||
option := "ip4.address"
|
||||
str, err := Config.String(section, option)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to parse %v: %v", option, err)
|
||||
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
||||
}
|
||||
addr := net.ParseIP(str)
|
||||
if addr == nil {
|
||||
return fmt.Errorf("Failed to parse %v '%v'", option, str)
|
||||
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
||||
}
|
||||
addr = addr.To4()
|
||||
if addr == nil {
|
||||
return fmt.Errorf("Failed to parse %v '%v' not IPv4!", option, str)
|
||||
return fmt.Errorf("Failed to parse [%v]%v: '%v' not IPv4!", section, option, err)
|
||||
}
|
||||
smtpConfig.Ip4address = addr
|
||||
|
||||
option = "[smtp]ip4.port"
|
||||
smtpConfig.Ip4port, err = Config.Int("smtp", "ip4.port")
|
||||
option = "ip4.port"
|
||||
smtpConfig.Ip4port, err = Config.Int(section, option)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to parse %v: %v", option, err)
|
||||
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
||||
}
|
||||
|
||||
option = "[smtp]domain"
|
||||
str, err = Config.String("smtp", "domain")
|
||||
option = "domain"
|
||||
str, err = Config.String(section, option)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to parse %v: %v", option, err)
|
||||
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
||||
}
|
||||
smtpConfig.Domain = str
|
||||
|
||||
option = "max.recipients"
|
||||
smtpConfig.MaxRecipients, err = Config.Int(section, option)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
||||
}
|
||||
|
||||
option = "max.idle.seconds"
|
||||
smtpConfig.MaxIdleSeconds, err = Config.Int(section, option)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
||||
}
|
||||
|
||||
option = "max.message.bytes"
|
||||
smtpConfig.MaxMessageBytes, err = Config.Int(section, option)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseWebConfig trying to catch config errors early
|
||||
func parseWebConfig() error {
|
||||
webConfig = new(WebConfig)
|
||||
section := "web"
|
||||
|
||||
// Parse IP4 address only, error on IP6.
|
||||
option := "[web]ip4.address"
|
||||
str, err := Config.String("web", "ip4.address")
|
||||
option := "ip4.address"
|
||||
str, err := Config.String(section, option)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to parse %v: %v", option, err)
|
||||
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
||||
}
|
||||
addr := net.ParseIP(str)
|
||||
if addr == nil {
|
||||
return fmt.Errorf("Failed to parse %v '%v'", option, str)
|
||||
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
||||
}
|
||||
addr = addr.To4()
|
||||
if addr == nil {
|
||||
return fmt.Errorf("Failed to parse %v '%v' not IPv4!", option, str)
|
||||
return fmt.Errorf("Failed to parse [%v]%v: '%v' not IPv4!", section, option, err)
|
||||
}
|
||||
webConfig.Ip4address = addr
|
||||
|
||||
option = "[web]ip4.port"
|
||||
webConfig.Ip4port, err = Config.Int("web", "ip4.port")
|
||||
option = "ip4.port"
|
||||
webConfig.Ip4port, err = Config.Int(section, option)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to parse %v: %v", option, err)
|
||||
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
||||
}
|
||||
|
||||
option = "[web]template.dir"
|
||||
str, err = Config.String("web", "template.dir")
|
||||
option = "template.dir"
|
||||
str, err = Config.String(section, option)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to parse %v: %v", option, err)
|
||||
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
||||
}
|
||||
webConfig.TemplateDir = str
|
||||
|
||||
option = "[web]template.cache"
|
||||
flag, err := Config.Bool("web", "template.cache")
|
||||
option = "template.cache"
|
||||
flag, err := Config.Bool(section, option)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to parse %v: %v", option, err)
|
||||
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
||||
}
|
||||
webConfig.TemplateCache = flag
|
||||
|
||||
option = "[web]public.dir"
|
||||
str, err = Config.String("web", "public.dir")
|
||||
option = "public.dir"
|
||||
str, err = Config.String(section, option)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to parse %v: %v", option, err)
|
||||
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
||||
}
|
||||
webConfig.PublicDir = str
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseDataStoreConfig trying to catch config errors early
|
||||
func parseDataStoreConfig() error {
|
||||
dataStoreConfig = new(DataStoreConfig)
|
||||
section := "datastore"
|
||||
|
||||
option := "path"
|
||||
str, err := Config.String(section, option)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
||||
}
|
||||
dataStoreConfig.Path = str
|
||||
|
||||
option = "retention.minutes"
|
||||
dataStoreConfig.RetentionMinutes, err = Config.Int(section, option)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
||||
}
|
||||
option = "retention.sleep.millis"
|
||||
dataStoreConfig.RetentionSleep, err = Config.Int(section, option)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// requireSection checks that a [section] is defined in the configuration file,
|
||||
// appending a message if not.
|
||||
func requireSection(messages *list.List, section string) {
|
||||
|
||||
Reference in New Issue
Block a user