270 lines
6.0 KiB
Go
270 lines
6.0 KiB
Go
package notifiers
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/tls"
|
|
"fmt"
|
|
"github.com/GeertJohan/go.rice"
|
|
"github.com/hunterlong/statup/types"
|
|
"github.com/hunterlong/statup/utils"
|
|
"gopkg.in/gomail.v2"
|
|
"html/template"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
EMAIL_ID int64 = 1
|
|
EMAIL_METHOD = "email"
|
|
)
|
|
|
|
var (
|
|
emailer *Email
|
|
emailArray []string
|
|
emailQueue []*EmailOutgoing
|
|
emailBox *rice.Box
|
|
mailer *gomail.Dialer
|
|
)
|
|
|
|
type Email struct {
|
|
*Notification
|
|
}
|
|
|
|
// DEFINE YOUR NOTIFICATION HERE.
|
|
func init() {
|
|
|
|
emailer = &Email{
|
|
Notification: &Notification{
|
|
Id: EMAIL_ID,
|
|
Method: EMAIL_METHOD,
|
|
Form: []NotificationForm{{
|
|
Id: 1,
|
|
Type: "text",
|
|
Title: "SMTP Host",
|
|
Placeholder: "Insert your SMTP Host here.",
|
|
DbField: "Host",
|
|
}, {
|
|
Id: 1,
|
|
Type: "text",
|
|
Title: "SMTP Username",
|
|
Placeholder: "Insert your SMTP Username here.",
|
|
DbField: "Username",
|
|
}, {
|
|
Id: 1,
|
|
Type: "password",
|
|
Title: "SMTP Password",
|
|
Placeholder: "Insert your SMTP Password here.",
|
|
DbField: "Password",
|
|
}, {
|
|
Id: 1,
|
|
Type: "number",
|
|
Title: "SMTP Port",
|
|
Placeholder: "Insert your SMTP Port here.",
|
|
DbField: "Port",
|
|
}, {
|
|
Id: 1,
|
|
Type: "text",
|
|
Title: "Outgoing Email Address",
|
|
Placeholder: "Insert your Outgoing Email Address",
|
|
DbField: "Var1",
|
|
}, {
|
|
Id: 1,
|
|
Type: "email",
|
|
Title: "Send Alerts To",
|
|
Placeholder: "Email Address",
|
|
DbField: "Var2",
|
|
}},
|
|
}}
|
|
|
|
add(emailer)
|
|
}
|
|
|
|
// Select Obj
|
|
func (u *Email) Select() *Notification {
|
|
return u.Notification
|
|
}
|
|
|
|
// WHEN NOTIFIER LOADS
|
|
func (u *Email) Init() error {
|
|
emailBox = rice.MustFindBox("emails")
|
|
err := u.Install()
|
|
utils.Log(1, fmt.Sprintf("Creating Mailer: %v:%v", u.Notification.Host, u.Notification.Port))
|
|
|
|
if err == nil {
|
|
notifier, _ := SelectNotification(u.Id)
|
|
forms := u.Form
|
|
u.Notification = notifier
|
|
u.Form = forms
|
|
if u.Enabled {
|
|
|
|
utils.Log(1, fmt.Sprintf("Loading SMTP Emailer using host: %v:%v", u.Notification.Host, u.Notification.Port))
|
|
mailer = gomail.NewDialer(u.Notification.Host, u.Notification.Port, u.Notification.Username, u.Notification.Password)
|
|
mailer.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
|
|
|
go u.Run()
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (u *Email) Test() error {
|
|
if u.Enabled {
|
|
email := &EmailOutgoing{
|
|
To: emailer.Var2,
|
|
Subject: "Test Email",
|
|
Template: "message.html",
|
|
Data: nil,
|
|
From: emailer.Var1,
|
|
}
|
|
SendEmail(emailBox, email)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type emailMessage struct {
|
|
Service *types.Service
|
|
}
|
|
|
|
type EmailOutgoing struct {
|
|
To string
|
|
Subject string
|
|
Template string
|
|
From string
|
|
Data interface{}
|
|
Source string
|
|
Sent bool
|
|
}
|
|
|
|
// AFTER NOTIFIER LOADS, IF ENABLED, START A QUEUE PROCESS
|
|
func (u *Email) Run() error {
|
|
var sentAddresses []string
|
|
for _, email := range emailQueue {
|
|
if inArray(sentAddresses, email.To) || email.Sent {
|
|
emailQueue = removeEmail(emailQueue, email)
|
|
continue
|
|
}
|
|
if u.CanSend() {
|
|
err := u.dialSend(email)
|
|
if err == nil {
|
|
email.Sent = true
|
|
sentAddresses = append(sentAddresses, email.To)
|
|
utils.Log(1, fmt.Sprintf("Email '%v' sent to: %v using the %v template (size: %v)", email.Subject, email.To, email.Template, len([]byte(email.Source))))
|
|
emailQueue = removeEmail(emailQueue, email)
|
|
u.Log(fmt.Sprintf("Subject: %v to %v", email.Subject, email.To))
|
|
} else {
|
|
utils.Log(3, fmt.Sprintf("Email Notifier could not send email: %v", err))
|
|
}
|
|
}
|
|
}
|
|
time.Sleep(60 * time.Second)
|
|
if u.Enabled {
|
|
return u.Run()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ON SERVICE FAILURE, DO YOUR OWN FUNCTIONS
|
|
func (u *Email) OnFailure(s *types.Service) error {
|
|
if u.Enabled {
|
|
msg := emailMessage{
|
|
Service: s,
|
|
}
|
|
email := &EmailOutgoing{
|
|
To: emailer.Var2,
|
|
Subject: fmt.Sprintf("Service %v is Failing", s.Name),
|
|
Template: "failure.html",
|
|
Data: msg,
|
|
From: emailer.Var1,
|
|
}
|
|
SendEmail(emailBox, email)
|
|
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ON SERVICE SUCCESS, DO YOUR OWN FUNCTIONS
|
|
func (u *Email) OnSuccess(s *types.Service) error {
|
|
if u.Enabled {
|
|
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ON SAVE OR UPDATE OF THE NOTIFIER FORM
|
|
func (u *Email) OnSave() error {
|
|
utils.Log(1, fmt.Sprintf("Notification %v is receiving updated information.", u.Method))
|
|
|
|
// Do updating stuff here
|
|
|
|
return nil
|
|
}
|
|
|
|
// ON SERVICE FAILURE, DO YOUR OWN FUNCTIONS
|
|
func (u *Email) Install() error {
|
|
inDb, err := emailer.Notification.IsInDatabase()
|
|
if !inDb {
|
|
newNotifer, err := InsertDatabase(u.Notification)
|
|
if err != nil {
|
|
utils.Log(3, err)
|
|
return err
|
|
}
|
|
utils.Log(1, fmt.Sprintf("new notifier #%v installed: %v", newNotifer, u.Method))
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (u *Email) dialSend(email *EmailOutgoing) error {
|
|
m := gomail.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 SendEmail(box *rice.Box, email *EmailOutgoing) {
|
|
source := EmailTemplate(box, email.Template, email.Data)
|
|
email.Source = source
|
|
emailQueue = append(emailQueue, email)
|
|
}
|
|
|
|
func EmailTemplate(box *rice.Box, tmpl string, data interface{}) string {
|
|
emailTpl, err := box.String(tmpl)
|
|
if err != nil {
|
|
utils.Log(3, err)
|
|
}
|
|
t := template.New("email")
|
|
t, err = t.Parse(emailTpl)
|
|
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
|
|
}
|
|
|
|
func removeEmail(emails []*EmailOutgoing, em *EmailOutgoing) []*EmailOutgoing {
|
|
var newArr []*EmailOutgoing
|
|
for _, e := range emails {
|
|
if e != em {
|
|
newArr = append(newArr, e)
|
|
}
|
|
}
|
|
return newArr
|
|
}
|
|
|
|
func inArray(a []string, v string) bool {
|
|
for _, i := range a {
|
|
if i == v {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|