// 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 ( MESSAGE = "\n\n\n \n \n Sample Email\n\n\n\n\n\n \n \n \n
\n \n\n \n \n \n
\n \n\n \n \n \n
\n

Looks Like Emails Work!

\n

\n Since you got this email, it confirms that your Statup Status Page email system is working correctly.\n

\n

\n

\n Enjoy using Statup!\n
Statup.io Team

\n\n \n\n
\n
\n
\n
\n\n" FAILURE = "\n\n\n \n \n Sample Email\n\n\n\n\n\n \n \n \n
\n \n\n \n \n \n
\n \n\n \n \n \n
\n

{{ .Service.Name }} is Offline!

\n

\n Your Statup service '{{.Service.Name}}' has been triggered with a HTTP status code of '{{.Service.LastStatusCode}}' and is currently offline based on your requirements. This failure was created on {{.Service.CreatedAt}}.\n

\n\n {{if .Service.LastResponse }}\n

Last Response

\n

\n {{ .Service.LastResponse }}\n

\n {{end}}\n\n \n \n \n
\n View Service\n \n Statup Dashboard\n
\n
\n
\n
\n\n" SUCCESS = "\n\n\n \n \n Sample Email\n\n\n\n\n\n \n \n \n
\n \n\n \n \n \n
\n \n\n \n \n \n
\n

{{ .Service.Name }} is Offline!

\n

\n Your Statup service '{{.Service.Name}}' has been triggered with a HTTP status code of '{{.Service.LastStatusCode}}' and is currently offline based on your requirements. This failure was created on {{.Service.CreatedAt}}.\n

\n\n {{if .Service.LastResponse }}\n

Last Response

\n

\n {{ .Service.LastResponse }}\n

\n {{end}}\n\n \n \n \n
\n View Service\n \n Statup Dashboard\n
\n
\n
\n
\n\n" ) var ( mailer *mail.Dialer ) type Email struct { *notifier.Notification } var emailer = &Email{¬ifier.Notification{ Method: "email", Title: "Email", Description: "Send emails via SMTP when notification 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: FAILURE, 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: SUCCESS, 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 }