// 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" "time" ) const ( mainEmailTemplate = ` 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", Icon: "far fa-envelope", 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 { 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: u.Var2, Subject: fmt.Sprintf("Service %v is Failing", s.Name), Template: mainEmailTemplate, Data: interface{}(s), From: u.Var1, } u.AddQueue(s.Id, email) u.Online = false } // OnSuccess will trigger successful service func (u *email) OnSuccess(s *types.Service) { if !u.Online { u.ResetUniqueQueue(s.Id) email := &emailOutgoing{ To: u.Var2, Subject: fmt.Sprintf("Service %v is Back Online", s.Name), Template: mainEmailTemplate, Data: interface{}(s), From: u.Var1, } u.AddQueue(s.Id, 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 { return err } err = dial.StartTLS(&tls.Config{InsecureSkipVerify: true}) if err != nil { return err } auth := smtp.PlainAuth("", u.Username, u.Password, host) err = dial.Auth(auth) if err != nil { return err } testService := &types.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: types.NewNullString("test example"), LastResponse: "this is an example response", CreatedAt: time.Now().Add(-24 * time.Hour), } email := &emailOutgoing{ To: u.Var2, Subject: fmt.Sprintf("Service %v is Back Online", testService.Name), Template: mainEmailTemplate, Data: interface{}(testService), From: u.Var1, } err = u.Send(email) return err } 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 (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(3, err) } var tpl bytes.Buffer if err := t.Execute(&tpl, data); err != nil { utils.Log(2, err) } result := tpl.String() return result }