From c1b3d106a0005c62ed40c6d9454cf6484a4975a8 Mon Sep 17 00:00:00 2001 From: ChaoticByte Date: Mon, 16 Jun 2025 17:29:38 +0200 Subject: [PATCH] Fix leak of first recipient to other recipients because mail headers are also cached and re-used --- mail_common.go | 24 ++++++++++++------------ mail_transfer.go | 7 +++++-- mail_transfer_debug.go | 7 +++++-- main.go | 2 +- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/mail_common.go b/mail_common.go index fee72f9..71e29bf 100644 --- a/mail_common.go +++ b/mail_common.go @@ -47,30 +47,30 @@ type SmtpSettings struct { 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 + " ...") cacheHits := 0 cacheMisses := 0 - mails := [][]byte{} + mails := []*MailContent{} for _, n := range notices { - var data []byte - cacheResult := (*cache)[n.Uuid] - if len(cacheResult) > 0 { + var mc *MailContent + cacheResult := (*mailContentCache)[n.Uuid] + if cacheResult != nil { cacheHits++ - data = cacheResult + mc = cacheResult } else { cacheMisses++ - mailContent, err := template.generate(TemplateData{n, Version}) + mc_, err := template.generate(TemplateData{n, Version}) if err != nil { logger.error("Could not create mail from template") 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)) err := sendMails( diff --git a/mail_transfer.go b/mail_transfer.go index 1013f0b..45675d3 100644 --- a/mail_transfer.go +++ b/mail_transfer.go @@ -11,7 +11,7 @@ import ( ) -func sendMails(smtpConf SmtpSettings, auth smtp.Auth, to string, data [][]byte) error { +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) @@ -32,7 +32,10 @@ func sendMails(smtpConf SmtpSettings, auth smtp.Auth, to string, data [][]byte) 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 { + 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) diff --git a/mail_transfer_debug.go b/mail_transfer_debug.go index d3846a3..60fb2bd 100644 --- a/mail_transfer_debug.go +++ b/mail_transfer_debug.go @@ -8,10 +8,13 @@ import ( "net/smtp" ) -func sendMails(smtpConf SmtpSettings, auth smtp.Auth, to string, data [][]byte) error { +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 _, d := range data { + 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") diff --git a/main.go b/main.go index 8fc4ab0..d239bf0 100644 --- a/main.go +++ b/main.go @@ -98,7 +98,7 @@ func main() { t1 := time.Now().UnixMilli() newNotices := []WidNotice{} 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 { logger.info("Querying endpoint '" + a.Id + "' for new notices ...") n, t, err := a.getNotices(persistent.data.(PersistentData).LastPublished[a.Id])