mirror of
https://github.com/phishingclub/phishingclub.git
synced 2026-07-23 12:11:14 +02:00
cac7920f7c
Signed-off-by: RonniSkansing <ronni@phishing.club>
78 lines
2.3 KiB
Go
78 lines
2.3 KiB
Go
package service
|
|
|
|
import (
|
|
"bytes"
|
|
"strings"
|
|
"text/template"
|
|
|
|
"github.com/phishingclub/phishingclub/model"
|
|
"github.com/wneessen/go-mail"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// sanitizeSMTPHeaderValue removes characters that are illegal in a single header
|
|
// line so a header value can never be used to inject additional headers, even if
|
|
// the underlying mail library stops encoding them. It strips all C0 control
|
|
// characters (including carriage return, line feed and NUL) and DEL.
|
|
func sanitizeSMTPHeaderValue(value string) string {
|
|
return strings.Map(func(r rune) rune {
|
|
if r < 0x20 || r == 0x7f {
|
|
return -1
|
|
}
|
|
return r
|
|
}, value)
|
|
}
|
|
|
|
// applyCustomSMTPHeaders sets the configured custom headers on the message.
|
|
//
|
|
// When templateData is not nil each header value is rendered with the same per
|
|
// recipient variables available in the email body and subject (for example
|
|
// {{.rID}} or {{.Email}}), using funcs as the template function map. Paths without
|
|
// a recipient context, such as the SMTP connectivity test, pass nil to send the
|
|
// values verbatim. Every value is sanitized before being set on the message.
|
|
func applyCustomSMTPHeaders(
|
|
msg *mail.Msg,
|
|
headers []*model.SMTPHeader,
|
|
templateData *map[string]any,
|
|
funcs template.FuncMap,
|
|
logger *zap.SugaredLogger,
|
|
) {
|
|
for _, header := range headers {
|
|
key := header.Key.MustGet().String()
|
|
value := header.Value.MustGet().String()
|
|
if templateData != nil {
|
|
value = renderSMTPHeaderValue(key, value, templateData, funcs, logger)
|
|
}
|
|
msg.SetGenHeader(mail.Header(key), sanitizeSMTPHeaderValue(value))
|
|
}
|
|
}
|
|
|
|
// renderSMTPHeaderValue renders a single header value as a template. On any parse
|
|
// or execution error it logs and falls back to the raw value so a broken header
|
|
// template never blocks a send.
|
|
func renderSMTPHeaderValue(
|
|
key string,
|
|
value string,
|
|
templateData *map[string]any,
|
|
funcs template.FuncMap,
|
|
logger *zap.SugaredLogger,
|
|
) string {
|
|
tmpl, err := template.New("smtpHeader").Funcs(funcs).Parse(value)
|
|
if err != nil {
|
|
logger.Warnw("failed to parse custom smtp header template, sending raw value",
|
|
"header", key,
|
|
"error", err,
|
|
)
|
|
return value
|
|
}
|
|
var buf bytes.Buffer
|
|
if err := tmpl.Execute(&buf, templateData); err != nil {
|
|
logger.Warnw("failed to execute custom smtp header template, sending raw value",
|
|
"header", key,
|
|
"error", err,
|
|
)
|
|
return value
|
|
}
|
|
return buf.String()
|
|
}
|