Improve config file structure by combining multiple recipients into lists (breaking)
This commit is contained in:
parent
ef24503214
commit
295ceec3de
4 changed files with 67 additions and 46 deletions
21
README.md
21
README.md
|
@ -34,27 +34,28 @@ Example:
|
|||
```json
|
||||
{
|
||||
"api_fetch_interval": 600,
|
||||
"datafile": "data.json",
|
||||
"enabled_api_endpoints": [
|
||||
"bay",
|
||||
"bund"
|
||||
],
|
||||
"datafile": "data.json",
|
||||
"loglevel": 2,
|
||||
"recipients": [
|
||||
"lists": [
|
||||
{
|
||||
"address": "guenther@example.org",
|
||||
"include": [
|
||||
{"classification": "kritisch"},
|
||||
{"title_contains": "jQuery"}
|
||||
"name": "Example List",
|
||||
"recipients": ["someone@example.org"],
|
||||
"filter": [
|
||||
{"classification": "hoch", "title_contains": "Microsoft"},
|
||||
{"classification": "kritisch"}
|
||||
]
|
||||
}
|
||||
],
|
||||
"smtp": {
|
||||
"from": "from@example.org",
|
||||
"host": "example.org",
|
||||
"from": "user@localhost",
|
||||
"host": "127.0.0.1",
|
||||
"port": 587,
|
||||
"user": "from@example.org",
|
||||
"password": "SiEhAbEnMiChInSgEsIcHtGeFiLmTdAsDüRfEnSiEnIcHt"
|
||||
"user": "user@localhost",
|
||||
"password": "change me :)"
|
||||
},
|
||||
"template": {
|
||||
"subject": "",
|
||||
|
|
36
config.go
36
config.go
|
@ -11,7 +11,7 @@ type Config struct {
|
|||
EnabledApiEndpoints []string `json:"enabled_api_endpoints"`
|
||||
PersistentDataFilePath string `json:"datafile"`
|
||||
LogLevel int `json:"loglevel"`
|
||||
Recipients []Recipient `json:"recipients"`
|
||||
Lists *[]NotifyList `json:"lists"`
|
||||
SmtpConfiguration SmtpSettings `json:"smtp"`
|
||||
Template MailTemplateConfig `json:"template"`
|
||||
}
|
||||
|
@ -23,12 +23,16 @@ func NewConfig() Config {
|
|||
EnabledApiEndpoints: []string{"bay", "bund"},
|
||||
PersistentDataFilePath: "data.json",
|
||||
LogLevel: 2,
|
||||
Recipients: []Recipient{},
|
||||
Lists: &[]NotifyList{
|
||||
{ Name: "Example List",
|
||||
Recipients: []string{},
|
||||
Filter: []Filter{},},
|
||||
},
|
||||
SmtpConfiguration: SmtpSettings{
|
||||
From: "from@example.org",
|
||||
User: "from@example.org",
|
||||
Password: "SiEhAbEnMiChInSgEsIcHtGeFiLmTdAsDüRfEnSiEnIcHt",
|
||||
ServerHost: "example.org",
|
||||
From: "user@localhost",
|
||||
User: "user@localhost",
|
||||
Password: "change me :)",
|
||||
ServerHost: "127.0.0.1",
|
||||
ServerPort: 587},
|
||||
Template: MailTemplateConfig{
|
||||
SubjectTemplate: "",
|
||||
|
@ -39,18 +43,20 @@ func NewConfig() Config {
|
|||
}
|
||||
|
||||
func checkConfig(config Config) {
|
||||
if len(config.Recipients) < 1 {
|
||||
if len(*config.Lists) < 1 {
|
||||
logger.error("Configuration is incomplete")
|
||||
panic(errors.New("no recipients are configured"))
|
||||
panic(errors.New("no lists are configured"))
|
||||
}
|
||||
for _, r := range config.Recipients {
|
||||
if !mailAddressIsValid(r.Address) {
|
||||
logger.error("Configuration includes invalid data")
|
||||
panic(errors.New("'" + r.Address + "' is not a valid e-mail address"))
|
||||
}
|
||||
if len(r.Filters) < 1 {
|
||||
for _, l := range *config.Lists {
|
||||
if len(l.Filter) < 1 {
|
||||
logger.error("Configuration is incomplete")
|
||||
panic(errors.New("recipient " + r.Address + " has no filter defined - at least {'any': true/false} should be configured"))
|
||||
panic(errors.New("list " + l.Name + " has no filter defined - at least [{'any': true/false}] should be configured"))
|
||||
}
|
||||
for _, r := range l.Recipients {
|
||||
if !mailAddressIsValid(r) {
|
||||
logger.error("Configuration includes invalid data")
|
||||
panic(errors.New("'" + r + "' is not a valid e-mail address"))
|
||||
}
|
||||
}
|
||||
}
|
||||
if !mailAddressIsValid(config.SmtpConfiguration.From) {
|
||||
|
|
21
mail.go
21
mail.go
|
@ -23,21 +23,22 @@ func (c MailContent) serializeValidMail(from string, to string) []byte {
|
|||
// and I'm too lazy to encode ä into =E4 and so on
|
||||
subjectEncoded := base64.StdEncoding.EncodeToString([]byte(c.Subject))
|
||||
bodyEncoded := base64.StdEncoding.EncodeToString([]byte(c.Body))
|
||||
data := []byte(fmt.Sprintf(
|
||||
data := fmt.Appendf(nil,
|
||||
"Content-Type: text/plain; charset=\"utf-8\"\r\nContent-Transfer-Encoding: base64\r\nFrom: %v%vTo: %v%vSubject: =?utf-8?b?%v?=%v%v%v",
|
||||
from, MAIL_LINE_SEP,
|
||||
to, MAIL_LINE_SEP,
|
||||
subjectEncoded, MAIL_LINE_SEP,
|
||||
MAIL_LINE_SEP,
|
||||
bodyEncoded))
|
||||
bodyEncoded)
|
||||
// done, I guess
|
||||
return data
|
||||
}
|
||||
|
||||
type Recipient struct {
|
||||
Address string `json:"address"`
|
||||
type NotifyList struct {
|
||||
Name string `json:"name"`
|
||||
Recipients []string `json:"recipients"`
|
||||
// Must be a configured filter id
|
||||
Filters []Filter `json:"include"`
|
||||
Filter []Filter `json:"filter"`
|
||||
}
|
||||
|
||||
type SmtpSettings struct {
|
||||
|
@ -48,8 +49,8 @@ type SmtpSettings struct {
|
|||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
func (r Recipient) sendNotices(notices []WidNotice, template MailTemplate, auth smtp.Auth, smtpConfig SmtpSettings, cache *map[string][]byte) error {
|
||||
logger.debug("Generating and sending mails to " + r.Address + " ...")
|
||||
func sendNotices(recipient string, notices []WidNotice, template MailTemplate, auth smtp.Auth, smtpConfig SmtpSettings, cache *map[string][]byte) error {
|
||||
logger.debug("Generating and sending mails for recipient " + recipient + " ...")
|
||||
cacheHits := 0
|
||||
cacheMisses := 0
|
||||
mails := [][]byte{}
|
||||
|
@ -67,7 +68,7 @@ func (r Recipient) sendNotices(notices []WidNotice, template MailTemplate, auth
|
|||
logger.error(err)
|
||||
}
|
||||
// serialize mail
|
||||
data = mailContent.serializeValidMail(smtpConfig.From, r.Address)
|
||||
data = mailContent.serializeValidMail(smtpConfig.From, recipient)
|
||||
// add to cache
|
||||
(*cache)[n.Uuid] = data
|
||||
}
|
||||
|
@ -77,11 +78,11 @@ func (r Recipient) sendNotices(notices []WidNotice, template MailTemplate, auth
|
|||
err := sendMails(
|
||||
smtpConfig,
|
||||
auth,
|
||||
r.Address,
|
||||
recipient,
|
||||
mails,
|
||||
)
|
||||
if err != nil { return err }
|
||||
logger.debug("Successfully sent all mails to " + r.Address)
|
||||
logger.debug("Successfully sent all mails to " + recipient)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
35
main.go
35
main.go
|
@ -120,22 +120,35 @@ func main() {
|
|||
logger.debug(fmt.Sprintf("Got %v new notices", len(newNotices)))
|
||||
if len(newNotices) > 0 {
|
||||
logger.info("Sending email notifications ...")
|
||||
// mail recipient : pointer to slice of wid notices to be sent
|
||||
noticesToBeSent := map[string][]WidNotice{}
|
||||
recipientsNotified := 0
|
||||
var err error
|
||||
for _, r := range config.Recipients {
|
||||
// Filter notices for this recipient
|
||||
filteredNotices := []WidNotice{}
|
||||
for _, f := range r.Filters {
|
||||
for _, l := range *config.Lists {
|
||||
// Filter notices for this list
|
||||
for _, f := range l.Filter {
|
||||
for _, n := range f.filter(newNotices) {
|
||||
if !noticeSliceContains(filteredNotices, n) {
|
||||
filteredNotices = append(filteredNotices, n)
|
||||
for _, r := range l.Recipients {
|
||||
if !noticeSliceContains(noticesToBeSent[r], n) {
|
||||
noticesToBeSent[r] = append(noticesToBeSent[r], n)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
slices.Reverse(filteredNotices)
|
||||
logger.debug(fmt.Sprintf("Including %v of %v notices for recipient %v", len(filteredNotices), len(newNotices), r.Address))
|
||||
// Send notices
|
||||
err = r.sendNotices(filteredNotices, mailTemplate, mailAuth, config.SmtpConfiguration, &cache)
|
||||
}
|
||||
for r, notices := range noticesToBeSent {
|
||||
// sort by publish date
|
||||
slices.SortFunc(notices, func(a WidNotice, b WidNotice) int {
|
||||
if a.Published == b.Published {
|
||||
return 0
|
||||
} else if a.Published.After(b.Published) {
|
||||
return 1
|
||||
} else {
|
||||
return -1
|
||||
}
|
||||
})
|
||||
// send
|
||||
err = sendNotices(r, notices, mailTemplate, mailAuth, config.SmtpConfiguration, &cache)
|
||||
if err != nil {
|
||||
logger.error(err)
|
||||
} else {
|
||||
|
@ -149,7 +162,7 @@ func main() {
|
|||
persistent.data.(PersistentData).LastPublished[id] = t
|
||||
persistent.save()
|
||||
}
|
||||
logger.info(fmt.Sprintf("Email notifications sent to %v of %v recipients", recipientsNotified, len(config.Recipients)))
|
||||
logger.info(fmt.Sprintf("Email notifications sent to %v of %v recipients", recipientsNotified, len(noticesToBeSent)))
|
||||
}
|
||||
}
|
||||
dt := int(time.Now().UnixMilli() - t1)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue