// Statping // Copyright (C) 2018. Hunter Long and the project contributors // Written by Hunter Long and the project contributors // // https://github.com/statping/statping // // 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/statping/statping/types/failures" "github.com/statping/statping/types/notifications" "github.com/statping/statping/types/notifier" "github.com/statping/statping/types/null" "github.com/statping/statping/types/services" "github.com/statping/statping/utils" "html/template" "time" ) var _ notifier.Notifier = (*emailer)(nil) const ( mainEmailTemplate = ` Statping email ` ) var ( mailer *mail.Dialer ) type emailer struct { *notifications.Notification } func (e *emailer) Select() *notifications.Notification { return e.Notification } var email = &emailer{¬ifications.Notification{ Method: "email", Title: "email", Description: "Send emails via SMTP when services are online or offline.", Author: "Hunter Long", AuthorUrl: "https://github.com/hunterlong", Icon: "far fa-envelope", Limits: 30, Form: []notifications.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: "outgoing@email.com", DbField: "Var1", }, { Type: "email", Title: "Send Alerts To", Placeholder: "sendto@email.com", DbField: "Var2", }, { Type: "text", Title: "Disable TLS/SSL", Placeholder: "", SmallText: "To Disable TLS/SSL insert 'true'", DbField: "api_key", }}}, } type emailOutgoing struct { To string Subject string Template string From string Data interface{} Source string Sent bool } // OnFailure will trigger failing service func (u *emailer) OnFailure(s *services.Service, f *failures.Failure) error { email := &emailOutgoing{ To: u.Var2, Subject: fmt.Sprintf("Service %v is Failing", s.Name), Template: mainEmailTemplate, Data: interface{}(s), From: u.Var1, } return u.dialSend(email) } // OnSuccess will trigger successful service func (u *emailer) OnSuccess(s *services.Service) error { msg := s.DownText email := &emailOutgoing{ To: u.Var2, Subject: msg, Template: mainEmailTemplate, Data: interface{}(s), From: u.Var1, } return u.dialSend(email) } // OnTest triggers when this notifier has been saved func (u *emailer) OnTest() error { testService := &services.Service{ Id: 1, Name: "Example Service", Domain: "https://www.youtube.com/watch?v=-u6DvRyyKGU", ExpectedStatus: 200, Interval: 30, Type: "http", Method: "GET", Timeout: 20, LastStatusCode: 200, Expected: null.NewNullString("test example"), LastResponse: "this is an example response", CreatedAt: utils.Now().Add(-24 * time.Hour), } email := &emailOutgoing{ To: u.Var2, Subject: fmt.Sprintf("Service %v is Back Online", testService.Name), Template: mainEmailTemplate, Data: testService, From: u.Var1, } return u.dialSend(email) } func (u *emailer) dialSend(email *emailOutgoing) error { mailer = mail.NewDialer(u.Host, u.Port, u.Username, u.Password) emailSource(email) m := mail.NewMessage() // if email setting TLS is Disabled if u.ApiKey == "true" { mailer.SSL = false } else { mailer.TLSConfig = &tls.Config{InsecureSkipVerify: true} } 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.Errorln(fmt.Sprintf("email '%v' sent to: %v (size: %v) %v", email.Subject, email.To, 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.Errorln(err) } var tpl bytes.Buffer if err := t.Execute(&tpl, data); err != nil { utils.Log.Warnln(err) } result := tpl.String() return result }