You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
2.8 KiB
Go
100 lines
2.8 KiB
Go
package core
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net/smtp"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
var notifiers = map[string]AbstractNotifier{
|
|
"email": EmailNotifier{},
|
|
}
|
|
|
|
type AbstractNotifier interface {
|
|
New(config interface{}) (AbstractNotifier, error)
|
|
ComposeNotification(box *Box, checks []CheckResult) Notification
|
|
Submit(notification Notification) error
|
|
}
|
|
|
|
type Notification struct {
|
|
body string
|
|
subject string
|
|
}
|
|
|
|
// box config required for the EmailNotifier
|
|
type EmailNotifier struct {
|
|
Recipients []string
|
|
}
|
|
|
|
func (n EmailNotifier) New(config interface{}) (AbstractNotifier, error) {
|
|
// assign configuration to the notifier after ensuring the correct type.
|
|
// lesson of this project: golang requires us to fuck around with type
|
|
// assertions, instead of providing us with proper inheritance.
|
|
|
|
asserted, ok := config.(EmailNotifier)
|
|
if !ok || asserted.Recipients == nil {
|
|
// config did not contain valid options.
|
|
// first try fallback: parse result of viper is a map[string]interface{},
|
|
// which requires a different assertion change
|
|
asserted2, ok := config.(map[string]interface{})
|
|
if ok {
|
|
asserted3, ok := asserted2["recipients"].([]interface{})
|
|
if ok {
|
|
asserted = EmailNotifier{Recipients: []string{}}
|
|
for _, rec := range asserted3 {
|
|
asserted.Recipients = append(asserted.Recipients, rec.(string))
|
|
}
|
|
}
|
|
}
|
|
|
|
if asserted.Recipients == nil {
|
|
return nil, errors.New("Invalid EmailNotifier options")
|
|
}
|
|
}
|
|
|
|
return EmailNotifier{
|
|
Recipients: asserted.Recipients,
|
|
}, nil
|
|
}
|
|
|
|
func (n EmailNotifier) ComposeNotification(box *Box, checks []CheckResult) Notification {
|
|
resultTexts := []string{}
|
|
for _, check := range checks {
|
|
resultTexts = append(resultTexts, check.String())
|
|
}
|
|
|
|
return Notification{
|
|
subject: fmt.Sprintf("Issues with your box \"%s\" on opensensemap.org!", box.Name),
|
|
body: fmt.Sprintf("A check at %s identified the following issue(s) with your box %s:\n\n%s\n\nYou may visit https://opensensemap.org/explore/%s for more details.\n\n--\nSent automatically by osem_notify (https://github.com/noerw/osem_notify)",
|
|
time.Now().Round(time.Minute), box.Name, strings.Join(resultTexts, "\n"), box.Id),
|
|
}
|
|
}
|
|
|
|
func (n EmailNotifier) Submit(notification Notification) error {
|
|
auth := smtp.PlainAuth(
|
|
"",
|
|
viper.GetString("email.user"),
|
|
viper.GetString("email.pass"),
|
|
viper.GetString("email.host"),
|
|
)
|
|
|
|
from := viper.GetString("email.from")
|
|
body := fmt.Sprintf("From: openSenseMap Notifier <%s>\nSubject: %s\nContent-Type: text/plain; charset=\"utf-8\"\n\n%s", from, notification.subject, notification.body)
|
|
|
|
// Connect to the server, authenticate, set the sender and recipient,
|
|
// and send the email all in one step.
|
|
err := smtp.SendMail(
|
|
fmt.Sprintf("%s:%s", viper.GetString("email.host"), viper.GetString("email.port")),
|
|
auth,
|
|
from,
|
|
n.Recipients,
|
|
[]byte(body),
|
|
)
|
|
|
|
return err
|
|
}
|