From e1df5ac48725025aea9effebd7be656a483653b6 Mon Sep 17 00:00:00 2001 From: Christopher Ramey Date: Sun, 24 Jan 2021 13:32:39 -0900 Subject: [PATCH] code cleanup --- alarm/alarm.go | 3 +- alarm/alarm_email.go | 241 ------------------------------------------- alarm/email/alarm.go | 72 +++++++++++++ alarm/email/email.go | 82 +++++++++++++++ alarm/email/parse.go | 98 ++++++++++++++++++ 5 files changed, 254 insertions(+), 242 deletions(-) delete mode 100644 alarm/alarm_email.go create mode 100644 alarm/email/alarm.go create mode 100644 alarm/email/email.go create mode 100644 alarm/email/parse.go diff --git a/alarm/alarm.go b/alarm/alarm.go index e82911d..605cc13 100644 --- a/alarm/alarm.go +++ b/alarm/alarm.go @@ -2,6 +2,7 @@ package alarm import ( "fmt" + "alrm/alarm/email" ) type Alarm interface { @@ -12,7 +13,7 @@ type Alarm interface { func NewAlarm(name string, typename string) (Alarm, error) { switch typename { case "email": - return NewAlarmEmail(name), nil + return email.NewAlarmEmail(name), nil default: return nil, fmt.Errorf("unknown alarm name \"%s\"", name) } diff --git a/alarm/alarm_email.go b/alarm/alarm_email.go deleted file mode 100644 index fe02c34..0000000 --- a/alarm/alarm_email.go +++ /dev/null @@ -1,241 +0,0 @@ -package alarm - -import ( - "fmt" - "net/smtp" - "os" - "strings" - "text/template" - "time" -) - -const ( - TK_NONE = iota - TK_TO - TK_SMTP - TK_FROM - TK_USER - TK_PASS - TK_SUBJECT - TK_MESSAGE -) - -type AlarmEmail struct { - Type string - Name string - To []string - From string - SMTP string - User string - Pass string - Subject string - subTemplate *template.Template - Message string - msgTemplate *template.Template - state int -} - -type EmailDetail struct { - Timestamp string - Group string - Host string - Check string - Error error -} - -func NewAlarmEmail(name string) *AlarmEmail { - host, _ := os.Hostname() - if host == "" { - host = "localhost" - } - - al := &AlarmEmail{ - Type: "email", - Name: name, - From: "alrm@" + host, - SMTP: "localhost:25", - Subject: "{{.Host}} failure", - Message: "Check {{.Check}} failed at {{.Timestamp}}: {{.Error}}", - } - al.updateSubject() - al.updateMessage() - return al -} - -func (a *AlarmEmail) updateSubject() error { - t := template.New("email subject") - _, err := t.Parse(a.Subject) - if err != nil { - fmt.Print(err) - return err - } - a.subTemplate = t - return nil -} - -func (a *AlarmEmail) updateMessage() error { - t := template.New("email message") - _, err := t.Parse(a.Message) - if err != nil { - fmt.Print(err) - return err - } - a.msgTemplate = t - return nil -} - -func (a *AlarmEmail) Parse(tk string) (bool, error) { - switch a.state { - case TK_NONE: - switch strings.ToLower(tk) { - case "to": - a.state = TK_TO - case "from": - a.state = TK_FROM - case "smtp": - a.state = TK_SMTP - case "user": - a.state = TK_USER - case "pass": - a.state = TK_PASS - case "subject": - a.state = TK_SUBJECT - case "message": - a.state = TK_MESSAGE - default: - if len(a.To) < 1 { - return false, fmt.Errorf("email alarm requires to address") - } - return false, nil - } - - case TK_FROM: - if strings.TrimSpace(tk) == "" { - return false, fmt.Errorf("from address cannot be empty") - } - a.From = tk - a.state = TK_NONE - - case TK_SMTP: - if strings.TrimSpace(tk) == "" { - return false, fmt.Errorf("smtp server cannot be empty") - } - // If the smtp host doesn't contain a port, add the default - if !strings.Contains(tk, ":") { - tk += ":25" - } - a.SMTP = tk - a.state = TK_NONE - - case TK_TO: - if strings.TrimSpace(tk) == "" { - return false, fmt.Errorf("to address cannot be empty") - } - a.To = append(a.To, tk) - a.state = TK_NONE - - case TK_USER: - if strings.TrimSpace(tk) == "" { - return false, fmt.Errorf("user cannot be empty") - } - a.User = tk - a.state = TK_NONE - - case TK_PASS: - if strings.TrimSpace(tk) == "" { - return false, fmt.Errorf("pass cannot be empty") - } - a.Pass = tk - a.state = TK_NONE - - case TK_SUBJECT: - if strings.TrimSpace(tk) == "" { - return false, fmt.Errorf("subject cannot be empty") - } - a.Subject = tk - err := a.updateSubject() - if err != nil { - return false, err - } - a.state = TK_NONE - - case TK_MESSAGE: - if strings.TrimSpace(tk) == "" { - return false, fmt.Errorf("message cannot be empty") - } - a.Message = tk - err := a.updateMessage() - if err != nil { - return false, err - } - a.state = TK_NONE - - default: - return false, fmt.Errorf("invalid state in alarm_email") - } - return true, nil -} - -func (a *AlarmEmail) Alarm(grp string, hst string, chk string, alerr error) error { - dt := EmailDetail{ - Timestamp: time.Now().Format(time.RFC1123), - Group: grp, - Host: hst, - Check: chk, - Error: alerr, - } - - c, err := smtp.Dial(a.SMTP) - if err != nil { - return err - } - - helo := "localhost" - tspl := strings.Split(a.From, "@") - if len(tspl) > 1 { - helo = tspl[1] - } - - err = c.Hello(helo) - if err != nil { - return err - } - err = c.Mail(a.From) - if err != nil { - return err - } - for _, to := range a.To { - err = c.Rcpt(to) - if err != nil { - return err - } - } - m, err := c.Data() - if err != nil { - return err - } - - fmt.Fprintf(m, "From: %s\r\n", a.From) - fmt.Fprintf(m, "To: %s\r\n", strings.Join(a.To, ";")) - - fmt.Fprintf(m, "Subject: ") - err = a.subTemplate.Execute(m, dt) - if err != nil { - return err - } - fmt.Fprintf(m, "\r\n\r\n") - - err = a.msgTemplate.Execute(m, dt) - if err != nil { - return err - } - err = m.Close() - if err != nil { - return err - } - err = c.Quit() - if err != nil { - return err - } - return nil -} diff --git a/alarm/email/alarm.go b/alarm/email/alarm.go new file mode 100644 index 0000000..defb7b3 --- /dev/null +++ b/alarm/email/alarm.go @@ -0,0 +1,72 @@ +package email + +import ( + "fmt" + "net/smtp" + "strings" + "time" +) + +func (a *AlarmEmail) Alarm(grp string, hst string, chk string, alerr error) error { + dt := EmailDetail{ + Timestamp: time.Now().Format(time.RFC1123), + Group: grp, + Host: hst, + Check: chk, + Error: alerr, + } + + c, err := smtp.Dial(a.SMTP) + if err != nil { + return err + } + + helo := "localhost" + tspl := strings.Split(a.From, "@") + if len(tspl) > 1 { + helo = tspl[1] + } + + err = c.Hello(helo) + if err != nil { + return err + } + err = c.Mail(a.From) + if err != nil { + return err + } + for _, to := range a.To { + err = c.Rcpt(to) + if err != nil { + return err + } + } + m, err := c.Data() + if err != nil { + return err + } + + fmt.Fprintf(m, "From: %s\r\n", a.From) + fmt.Fprintf(m, "To: %s\r\n", strings.Join(a.To, ";")) + + fmt.Fprintf(m, "Subject: ") + err = a.subTemplate.Execute(m, dt) + if err != nil { + return err + } + fmt.Fprintf(m, "\r\n\r\n") + + err = a.msgTemplate.Execute(m, dt) + if err != nil { + return err + } + err = m.Close() + if err != nil { + return err + } + err = c.Quit() + if err != nil { + return err + } + return nil +} diff --git a/alarm/email/email.go b/alarm/email/email.go new file mode 100644 index 0000000..9ff33c4 --- /dev/null +++ b/alarm/email/email.go @@ -0,0 +1,82 @@ +package email + +import ( + "fmt" + "os" + "text/template" +) + +const ( + TK_NONE = iota + TK_TO + TK_SMTP + TK_FROM + TK_USER + TK_PASS + TK_SUBJECT + TK_MESSAGE +) + +type AlarmEmail struct { + Type string + Name string + To []string + From string + SMTP string + User string + Pass string + Subject string + subTemplate *template.Template + Message string + msgTemplate *template.Template + state int +} + +type EmailDetail struct { + Timestamp string + Group string + Host string + Check string + Error error +} + +func NewAlarmEmail(name string) *AlarmEmail { + host, _ := os.Hostname() + if host == "" { + host = "localhost" + } + + al := &AlarmEmail{ + Type: "email", + Name: name, + From: "alrm@" + host, + SMTP: "localhost:25", + Subject: "{{.Host}} failure", + Message: "Check {{.Check}} failed at {{.Timestamp}}: {{.Error}}", + } + al.updateSubject() + al.updateMessage() + return al +} + +func (a *AlarmEmail) updateSubject() error { + t := template.New("email subject") + _, err := t.Parse(a.Subject) + if err != nil { + fmt.Print(err) + return err + } + a.subTemplate = t + return nil +} + +func (a *AlarmEmail) updateMessage() error { + t := template.New("email message") + _, err := t.Parse(a.Message) + if err != nil { + fmt.Print(err) + return err + } + a.msgTemplate = t + return nil +} diff --git a/alarm/email/parse.go b/alarm/email/parse.go new file mode 100644 index 0000000..ecb6d92 --- /dev/null +++ b/alarm/email/parse.go @@ -0,0 +1,98 @@ +package email + +import ( + "fmt" + "strings" +) + +func (a *AlarmEmail) Parse(tk string) (bool, error) { + switch a.state { + case TK_NONE: + switch strings.ToLower(tk) { + case "to": + a.state = TK_TO + case "from": + a.state = TK_FROM + case "smtp": + a.state = TK_SMTP + case "user": + a.state = TK_USER + case "pass": + a.state = TK_PASS + case "subject": + a.state = TK_SUBJECT + case "message": + a.state = TK_MESSAGE + default: + if len(a.To) < 1 { + return false, fmt.Errorf("email alarm requires to address") + } + return false, nil + } + + case TK_FROM: + if strings.TrimSpace(tk) == "" { + return false, fmt.Errorf("from address cannot be empty") + } + a.From = tk + a.state = TK_NONE + + case TK_SMTP: + if strings.TrimSpace(tk) == "" { + return false, fmt.Errorf("smtp server cannot be empty") + } + // If the smtp host doesn't contain a port, add the default + if !strings.Contains(tk, ":") { + tk += ":25" + } + a.SMTP = tk + a.state = TK_NONE + + case TK_TO: + if strings.TrimSpace(tk) == "" { + return false, fmt.Errorf("to address cannot be empty") + } + a.To = append(a.To, tk) + a.state = TK_NONE + + case TK_USER: + if strings.TrimSpace(tk) == "" { + return false, fmt.Errorf("user cannot be empty") + } + a.User = tk + a.state = TK_NONE + + case TK_PASS: + if strings.TrimSpace(tk) == "" { + return false, fmt.Errorf("pass cannot be empty") + } + a.Pass = tk + a.state = TK_NONE + + case TK_SUBJECT: + if strings.TrimSpace(tk) == "" { + return false, fmt.Errorf("subject cannot be empty") + } + a.Subject = tk + err := a.updateSubject() + if err != nil { + return false, err + } + a.state = TK_NONE + + case TK_MESSAGE: + if strings.TrimSpace(tk) == "" { + return false, fmt.Errorf("message cannot be empty") + } + a.Message = tk + err := a.updateMessage() + if err != nil { + return false, err + } + a.state = TK_NONE + + default: + return false, fmt.Errorf("invalid state in alarm_email") + } + return true, nil +}