// Statup // Copyright (C) 2018. Hunter Long and the project contributors // Written by Hunter Long and the project contributors // // https://github.com/hunterlong/statup // // The licenses for most software and other practical works are designed // to take away your freedom to share and change the works. By contrast, // the GNU General Public License is intended to guarantee your freedom to // share and change all versions of a program--to make sure it remains free // software for all its users. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . package notifiers import ( "bytes" "crypto/tls" "fmt" "github.com/go-mail/mail" "github.com/hunterlong/statup/core/notifier" "github.com/hunterlong/statup/types" "github.com/hunterlong/statup/utils" "html/template" "net/smtp" ) const ( TEMPLATE = ` Statup Email ` ) var ( mailer *mail.Dialer ) type Email struct { *notifier.Notification } var emailer = &Email{¬ifier.Notification{ Method: "email", Title: "Email", Description: "Send emails via SMTP when services are online or offline.", Author: "Hunter Long", AuthorUrl: "https://github.com/hunterlong", Form: []notifier.NotificationForm{{ Type: "text", Title: "SMTP Host", Placeholder: "Insert your SMTP Host here.", DbField: "Host", }, { Type: "text", Title: "SMTP Username", Placeholder: "Insert your SMTP Username here.", DbField: "Username", }, { Type: "password", Title: "SMTP Password", Placeholder: "Insert your SMTP Password here.", DbField: "Password", }, { Type: "number", Title: "SMTP Port", Placeholder: "Insert your SMTP Port here.", DbField: "Port", }, { Type: "text", Title: "Outgoing Email Address", Placeholder: "Insert your Outgoing Email Address", DbField: "Var1", }, { Type: "email", Title: "Send Alerts To", Placeholder: "Email Address", DbField: "Var2", }}, }} func init() { err := notifier.AddNotifier(emailer) if err != nil { panic(err) } } // Send will send the SMTP email with your authentication It accepts type: *EmailOutgoing func (u *Email) Send(msg interface{}) error { email := msg.(*EmailOutgoing) err := u.dialSend(email) if err != nil { utils.Log(3, fmt.Sprintf("Email Notifier could not send email: %v", err)) return err } return nil } type EmailOutgoing struct { To string Subject string Template string From string Data interface{} Source string Sent bool } // OnFailure will trigger failing service func (u *Email) OnFailure(s *types.Service, f *types.Failure) { email := &EmailOutgoing{ To: emailer.GetValue("var2"), Subject: fmt.Sprintf("Service %v is Failing", s.Name), Template: TEMPLATE, Data: interface{}(s), From: emailer.GetValue("var1"), } u.AddQueue(email) u.Online = false } // OnSuccess will trigger successful service func (u *Email) OnSuccess(s *types.Service) { if !u.Online { email := &EmailOutgoing{ To: emailer.GetValue("var2"), Subject: fmt.Sprintf("Service %v is Back Online", s.Name), Template: TEMPLATE, Data: interface{}(s), From: emailer.GetValue("var1"), } u.AddQueue(email) } u.Online = true } func (u *Email) Select() *notifier.Notification { return u.Notification } // OnSave triggers when this notifier has been saved func (u *Email) OnSave() error { utils.Log(1, fmt.Sprintf("Notification %v is receiving updated information.", u.Method)) // Do updating stuff here return nil } // OnTest triggers when this notifier has been saved func (u *Email) OnTest() error { host := fmt.Sprintf("%v:%v", u.Host, u.Port) dial, err := smtp.Dial(host) if err != nil { utils.Log(3, err) return err } auth := smtp.PlainAuth("", u.Username, u.Password, host) return dial.Auth(auth) } func (u *Email) dialSend(email *EmailOutgoing) error { mailer = mail.NewDialer(emailer.Host, emailer.Port, emailer.Username, emailer.Password) mailer.TLSConfig = &tls.Config{InsecureSkipVerify: true} emailSource(email) m := mail.NewMessage() m.SetHeader("From", email.From) m.SetHeader("To", email.To) m.SetHeader("Subject", email.Subject) m.SetBody("text/html", email.Source) if err := mailer.DialAndSend(m); err != nil { utils.Log(3, fmt.Sprintf("Email '%v' sent to: %v using the %v template (size: %v) %v", email.Subject, email.To, email.Template, len([]byte(email.Source)), err)) return err } return nil } func emailSource(email *EmailOutgoing) { source := EmailTemplate(email.Template, email.Data) email.Source = source } func EmailTemplate(contents string, data interface{}) string { t := template.New("email") t, err := t.Parse(contents) if err != nil { utils.Log(3, err) } var tpl bytes.Buffer if err := t.Execute(&tpl, data); err != nil { utils.Log(2, err) } result := tpl.String() return result }