From 4d4454a14c2ceac9637551b20a1eb341359c375d Mon Sep 17 00:00:00 2001 From: Blallo Date: Thu, 6 Feb 2020 18:30:13 +0100 Subject: [PATCH] First CLI implementation. --- main.go | 213 +++++++++++++++++++++++++++++++++++++++++++++++++ test_conf.toml | 50 ++++++++++++ 2 files changed, 263 insertions(+) create mode 100644 main.go create mode 100644 test_conf.toml diff --git a/main.go b/main.go new file mode 100644 index 0000000..9b142d2 --- /dev/null +++ b/main.go @@ -0,0 +1,213 @@ +package main + +import ( + "flag" + "fmt" + "log" + "reflect" + "strings" + + toml "github.com/pelletier/go-toml" + // mail "gopkg.in/gomail.v2" +) + +type ServerConfig struct { + Address string `toml:address,omitempty` + Port int64 `toml:port,omitempty` + Encryption string `toml:encryption,omitempty` + User string `toml:user,omitempty` + Password string `toml:password,omitempty` +} + +func (s ServerConfig) String() string { + return fmt.Sprintf( + "\tAddress: %s\n\tPort: %d\n\tEncryption: %s\n\tUser: %s\n\tPassword: %s\n", + s.Address, + s.Port, + s.Encryption, + s.User, + s.Password, + ) +} + +type Config struct { + Server *ServerConfig `toml:server,omitempty` + From string `toml:from,omitempty` + To []string `toml:to,omitempty` + Cc []string `toml:cc,omitempty` + Bcc []string `toml:bcc,omitempty` + Subject string `toml:subject,omitempty` + Text string `toml:text,omitempty` +} + +func (c Config) String() string { + return fmt.Sprintf( + "From: %s\nTo: %s\nCc: %s\nBcc: %s\nSubject: %s\nText:\n%s\nServer:\n%s", + c.From, + c.To, + c.Cc, + c.Bcc, + c.Subject, + c.Text, + c.Server, + ) +} + +func NewConfig() *Config { + server := &ServerConfig{} + config := &Config{} + config.Server = server + return config +} + +func debug(active bool, fmt string, msg ...interface{}) { + if active { + log.Printf(fmt, msg...) + } +} + +func isPresent(slice []string, val string) bool { + for _, item := range slice { + if item == val { + return true + } + } + return false +} + +func isEmpty(value interface{}) bool { + t := reflect.TypeOf(value) + v := reflect.ValueOf(value) + switch v.Kind() { + case reflect.Slice: + return v.Len() == 1 + default: + return value == reflect.Zero(t).Interface() + } +} + +func readConfig(configPath, section string) *Config { + config := NewConfig() + tree, err := toml.LoadFile(configPath) + if err != nil { + log.Panicln(err) + } + keys := tree.Keys() + + if !isPresent(keys, section) { + return config + } + sub := tree.Get(section).(*toml.Tree) + err = sub.Unmarshal(config) + return config +} + +func (c *Config) Validate() error { + return nil +} + +func merge(key string, value, obj interface{}) { + if isEmpty(value) { + return + } + + var elem reflect.Value + if reflect.TypeOf(obj) != reflect.TypeOf(reflect.Value{}) { + log.Println("Not Value") + elem = reflect.ValueOf(obj).Elem() + } else { + log.Println("Value") + elem = obj.(reflect.Value) + } + field := elem.FieldByName(key) + + if field.CanSet() { + switch field.Kind() { + case reflect.Int64: + field.SetInt(value.(int64)) + case reflect.Bool: + field.SetBool(value.(bool)) + case reflect.String: + field.SetString(value.(string)) + case reflect.Slice: + field.Set(reflect.ValueOf(value)) + default: + merge(key, reflect.ValueOf(value), field) + //merge(key, value, field.Pointer()) + } + } +} + +func (s *ServerConfig) Merge(key string, value interface{}) { + merge(key, value, s) +} + +func (c *Config) Merge(key string, value interface{}) { + merge(key, value, c) +} + +func main() { + //var err error + var configPath, section, serverAddress, encryption, user, password, to, cc, bcc, from, subject string + var dbg bool + var serverPort_ int + var serverPort int64 + flag.StringVar(&configPath, "conf", "/etc/sendmail.toml", "Path to a config file (defaults to /etc/sendmail.toml)") + flag.StringVar(§ion, "section", "default", "Section of the conf to read (defaults to \"default\")") + flag.BoolVar(&dbg, "dbg", false, "Enable debugging output") + flag.StringVar(&serverAddress, "server-address", "", "The SMTP server address") + flag.IntVar(&serverPort_, "server-port", 0, "The SMTP server") + flag.StringVar(&encryption, "encryption", "", "The encryption type (no, starttls, tls)") + flag.StringVar(&user, "user", "", "The user to authenticate with to the server") + flag.StringVar(&password, "password", "", "The password to authenticate with to the server") + flag.StringVar(&to, "to", "", "Comma-separated list of recipient(s)") + flag.StringVar(&cc, "cc", "", "Comma-separated list of carbon-copy recipient(s)") + flag.StringVar(&bcc, "bcc", "", "Comma-separated list of blind carbon-copy recipient(s)") + flag.StringVar(&from, "from", "", "Sender of the mail (used as default account user to log in on the SMTP server)") + flag.StringVar(&subject, "sub", "", "Subject of the mail") + flag.Parse() + + serverPort = int64(serverPort_) + debug( + dbg, + `parameters: + conf: %s + dbg: %t + address: %s + port: %d + encryption: %s + user: %s + password: %s + to: %s + from: %s + subject: %s`, + configPath, + dbg, + serverAddress, + serverPort, + encryption, + user, + password, + to, + from, + subject, + ) + config := readConfig(configPath, section) + debug(dbg, "\n%s", *config) + + // config.Server.Merge("Address", serverAddress) + // config.Server.Merge("Port", serverPort) + // config.Server.Merge("Encryption", encryption) + // config.Server.Merge("User", user) + // config.Server.Merge("Password", password) + config.Merge("Server", &ServerConfig{serverAddress, serverPort, encryption, user, password}) + config.Merge("From", from) + config.Merge("To", strings.Split(to, ",")) + config.Merge("Cc", strings.Split(cc, ",")) + config.Merge("Bcc", strings.Split(bcc, ",")) + config.Merge("Subject", subject) + // config.Merge("Text", text) + + debug(dbg, "\n%s", config) + +} diff --git a/test_conf.toml b/test_conf.toml new file mode 100644 index 0000000..ed169d7 --- /dev/null +++ b/test_conf.toml @@ -0,0 +1,50 @@ +[default] + from = "me@domain.com" + to = ["test@dom.in","test@examle.com"] + cc = ["other@foo.com","name@bar.org"] + bcc = ["forever@alone.com"] + subject = "My favourite topic" + text = ''' + Hello, + I am the crown prince of Nigeria. + I need to launder some money, would you help? + + + Greetings + ''' + + [default.server] + address = "1.3.1.2" + port = 587 + encryption = "tls" + user = "faggiano@uccelli.net" + password = "yougetit" + +[personal] + from = "notme@domain.com" + to = ["test@dom.in","test@examle.com"] + cc = ["other@foo.com","name@bar.org"] + bcc = ["forever@alone.com"] + subject = "My favourite topic" + text = ''' + I am an h4X0r. I infected your computer. + + You will follow this instructions or I will publish your + most personal pictures. + + https://followthewhiterabbit.com + ''' + + [personal.server] + address = "10.13.12.10" + port = 25 + encryption = "starttls" + user = "master@domain.local" + password = "yougetitagain" + +[secret] + [secret.server] + address = "my.server.org" + port = 12345 + encryption = "tls" + user = "me"