Compare commits

..

2 commits
2.0.0 ... main

4 changed files with 96 additions and 57 deletions

View file

@ -3,14 +3,12 @@
package main package main
import ( import (
"crypto/tls"
"fmt" "fmt"
"mime" "mime"
"mime/quotedprintable" "mime/quotedprintable"
"net/mail" "net/mail"
"net/smtp" "net/smtp"
"strings" "strings"
"time"
) )
type MailContent struct { type MailContent struct {
@ -49,30 +47,30 @@ type SmtpSettings struct {
Password string `json:"password"` Password string `json:"password"`
} }
func sendNotices(recipient string, notices []*WidNotice, template MailTemplate, auth smtp.Auth, smtpConfig SmtpSettings, cache *map[string][]byte) error { func sendNotices(recipient string, notices []*WidNotice, template MailTemplate, auth smtp.Auth, smtpConfig SmtpSettings, mailContentCache *map[string]*MailContent) error {
logger.debug("Generating and sending mails for recipient " + recipient + " ...") logger.debug("Generating and sending mails for recipient " + recipient + " ...")
cacheHits := 0 cacheHits := 0
cacheMisses := 0 cacheMisses := 0
mails := [][]byte{} mails := []*MailContent{}
for _, n := range notices { for _, n := range notices {
var data []byte var mc *MailContent
cacheResult := (*cache)[n.Uuid] cacheResult := (*mailContentCache)[n.Uuid]
if len(cacheResult) > 0 { if cacheResult != nil {
cacheHits++ cacheHits++
data = cacheResult mc = cacheResult
} else { } else {
cacheMisses++ cacheMisses++
mailContent, err := template.generate(TemplateData{n, Version}) mc_, err := template.generate(TemplateData{n, Version})
if err != nil { if err != nil {
logger.error("Could not create mail from template") logger.error("Could not create mail from template")
logger.error(err) logger.error(err)
} else {
mc = &mc_
// add to cache
(*mailContentCache)[n.Uuid] = mc
} }
// serialize mail
data = mailContent.serializeValidMail(smtpConfig.From, recipient)
// add to cache
(*cache)[n.Uuid] = data
} }
mails = append(mails, data) mails = append(mails, mc)
} }
logger.debug(fmt.Sprintf("%v mail cache hits, %v misses", cacheHits, cacheMisses)) logger.debug(fmt.Sprintf("%v mail cache hits, %v misses", cacheHits, cacheMisses))
err := sendMails( err := sendMails(
@ -86,48 +84,6 @@ func sendNotices(recipient string, notices []*WidNotice, template MailTemplate,
return nil return nil
} }
func sendMails(smtpConf SmtpSettings, auth smtp.Auth, to string, data [][]byte) error {
addr := fmt.Sprintf("%v:%v", smtpConf.ServerHost, smtpConf.ServerPort)
logger.debug("Connecting to mail server at " + addr + " ...")
connection, err := smtp.Dial(addr)
if err != nil { return err }
defer connection.Close()
// can leave out connection.Hello
hasTlsExt, _ := connection.Extension("starttls")
if hasTlsExt {
err = connection.StartTLS(&tls.Config{ServerName: smtpConf.ServerHost})
if err != nil { return err }
logger.debug("Mail Server supports TLS")
} else {
logger.debug("Mail Server doesn't support TLS")
}
logger.debug("Authenticating to mail server ...")
err = connection.Auth(auth)
if err != nil { return err }
if logger.LogLevel >= 3 {
fmt.Printf("DEBUG %v Sending mails to server ", time.Now().Format("2006/01/02 15:04:05.000000"))
}
for _, d := range data {
err = connection.Mail(smtpConf.From)
if err != nil { return err }
err = connection.Rcpt(to)
if err != nil { return err }
writer, err := connection.Data()
if err != nil { return err }
_, err = writer.Write(d)
if err != nil { return err }
err = writer.Close()
if err != nil { return err }
if logger.LogLevel >= 3 {
print(".")
}
}
if logger.LogLevel >= 3 {
print("\n")
}
return connection.Quit()
}
func mailAddressIsValid(address string) bool { func mailAddressIsValid(address string) bool {
_, err := mail.ParseAddress(address); _, err := mail.ParseAddress(address);
return err == nil return err == nil

57
mail_transfer.go Normal file
View file

@ -0,0 +1,57 @@
// +build !debug_mail_transfer
// Copyright (c) 2023 Julian Müller (ChaoticByte)
package main
import (
"crypto/tls"
"fmt"
"net/smtp"
"time"
)
func sendMails(smtpConf SmtpSettings, auth smtp.Auth, to string, mails []*MailContent) error {
addr := fmt.Sprintf("%v:%v", smtpConf.ServerHost, smtpConf.ServerPort)
logger.debug("Connecting to mail server at " + addr + " ...")
connection, err := smtp.Dial(addr)
if err != nil { return err }
defer connection.Close()
// can leave out connection.Hello
hasTlsExt, _ := connection.Extension("starttls")
if hasTlsExt {
err = connection.StartTLS(&tls.Config{ServerName: smtpConf.ServerHost})
if err != nil { return err }
logger.debug("Mail Server supports StartTLS")
} else {
logger.debug("Mail Server doesn't support StartTLS")
}
logger.debug("Authenticating to mail server ...")
err = connection.Auth(auth)
if err != nil { return err }
if logger.LogLevel >= 3 {
fmt.Printf("DEBUG %v Sending mails to server ", time.Now().Format("2006/01/02 15:04:05.000000"))
}
for _, mc := range mails {
// serialize mail
d := mc.serializeValidMail(smtpConf.From, to)
// send mail
err = connection.Mail(smtpConf.From)
if err != nil { return err }
err = connection.Rcpt(to)
if err != nil { return err }
writer, err := connection.Data()
if err != nil { return err }
_, err = writer.Write(d)
if err != nil { return err }
err = writer.Close()
if err != nil { return err }
if logger.LogLevel >= 3 {
print(".")
}
}
if logger.LogLevel >= 3 {
print("\n")
}
return connection.Quit()
}

26
mail_transfer_debug.go Normal file
View file

@ -0,0 +1,26 @@
// +build debug_mail_transfer
// Copyright (c) 2023 Julian Müller (ChaoticByte)
package main
import (
"fmt"
"net/smtp"
)
func sendMails(smtpConf SmtpSettings, auth smtp.Auth, to string, mails []*MailContent) error {
logger.warn("Mail Transfer Debugging is active. Not connecting.")
logger.info("MAIL TRANSFER: \n\n")
for _, mc := range mails {
// serialize mail
d := mc.serializeValidMail(smtpConf.From, to)
// output mail
fmt.Println("MAIL FROM:" + smtpConf.From)
fmt.Println("RCPT TO:" + to)
fmt.Println("DATA")
fmt.Println(string(d))
fmt.Println(".")
}
fmt.Print("\n\n")
return nil
}

View file

@ -98,7 +98,7 @@ func main() {
t1 := time.Now().UnixMilli() t1 := time.Now().UnixMilli()
newNotices := []WidNotice{} newNotices := []WidNotice{}
lastPublished := map[string]time.Time{} // endpoint id : last published timestamp lastPublished := map[string]time.Time{} // endpoint id : last published timestamp
cache := map[string][]byte{} // cache generated emails for reuse cache := map[string]*MailContent{} // cache generated emails for reuse
for _, a := range enabledApiEndpoints { for _, a := range enabledApiEndpoints {
logger.info("Querying endpoint '" + a.Id + "' for new notices ...") logger.info("Querying endpoint '" + a.Id + "' for new notices ...")
n, t, err := a.getNotices(persistent.data.(PersistentData).LastPublished[a.Id]) n, t, err := a.getNotices(persistent.data.(PersistentData).LastPublished[a.Id])