Use pointers
This commit is contained in:
parent
308d1b6073
commit
78eaed64d5
11
config.go
11
config.go
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/caarlos0/env/v6"
|
"github.com/caarlos0/env/v6"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -19,15 +20,15 @@ type config struct {
|
||||||
Blacklist []string `env:"BLACKLIST" envSeparator:"," envDefault:"gambling,casino"`
|
Blacklist []string `env:"BLACKLIST" envSeparator:"," envDefault:"gambling,casino"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseConfig() (config, error) {
|
func parseConfig() (*config, error) {
|
||||||
cfg := config{}
|
cfg := &config{}
|
||||||
if err := env.Parse(&cfg); err != nil {
|
if err := env.Parse(cfg); err != nil {
|
||||||
return cfg, errors.New("failed to parse config")
|
return cfg, errors.New("failed to parse config")
|
||||||
}
|
}
|
||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkRequiredConfig(cfg config) bool {
|
func checkRequiredConfig(cfg *config) bool {
|
||||||
if cfg.DefaultRecipient == "" {
|
if cfg.DefaultRecipient == "" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -47,4 +48,4 @@ func checkRequiredConfig(cfg config) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,7 @@ func Test_parseConfig(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_checkRequiredConfig(t *testing.T) {
|
func Test_checkRequiredConfig(t *testing.T) {
|
||||||
validConfig := config{
|
validConfig := &config{
|
||||||
Port: 8080,
|
Port: 8080,
|
||||||
HoneyPots: []string{"_t_email"},
|
HoneyPots: []string{"_t_email"},
|
||||||
DefaultRecipient: "mail@example.com",
|
DefaultRecipient: "mail@example.com",
|
||||||
|
@ -107,44 +107,44 @@ func Test_checkRequiredConfig(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("Default recipient missing", func(t *testing.T) {
|
t.Run("Default recipient missing", func(t *testing.T) {
|
||||||
newConfig := validConfig
|
newConfig := *validConfig
|
||||||
newConfig.DefaultRecipient = ""
|
newConfig.DefaultRecipient = ""
|
||||||
if false != checkRequiredConfig(newConfig) {
|
if false != checkRequiredConfig(&newConfig) {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("Allowed recipients missing", func(t *testing.T) {
|
t.Run("Allowed recipients missing", func(t *testing.T) {
|
||||||
newConfig := validConfig
|
newConfig := *validConfig
|
||||||
newConfig.AllowedRecipients = nil
|
newConfig.AllowedRecipients = nil
|
||||||
if false != checkRequiredConfig(newConfig) {
|
if false != checkRequiredConfig(&newConfig) {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("Sender missing", func(t *testing.T) {
|
t.Run("Sender missing", func(t *testing.T) {
|
||||||
newConfig := validConfig
|
newConfig := *validConfig
|
||||||
newConfig.Sender = ""
|
newConfig.Sender = ""
|
||||||
if false != checkRequiredConfig(newConfig) {
|
if false != checkRequiredConfig(&newConfig) {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("SMTP user missing", func(t *testing.T) {
|
t.Run("SMTP user missing", func(t *testing.T) {
|
||||||
newConfig := validConfig
|
newConfig := *validConfig
|
||||||
newConfig.SmtpUser = ""
|
newConfig.SmtpUser = ""
|
||||||
if false != checkRequiredConfig(newConfig) {
|
if false != checkRequiredConfig(&newConfig) {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("SMTP password missing", func(t *testing.T) {
|
t.Run("SMTP password missing", func(t *testing.T) {
|
||||||
newConfig := validConfig
|
newConfig := *validConfig
|
||||||
newConfig.SmtpPassword = ""
|
newConfig.SmtpPassword = ""
|
||||||
if false != checkRequiredConfig(newConfig) {
|
if false != checkRequiredConfig(&newConfig) {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("SMTP host missing", func(t *testing.T) {
|
t.Run("SMTP host missing", func(t *testing.T) {
|
||||||
newConfig := validConfig
|
newConfig := *validConfig
|
||||||
newConfig.SmtpHost = ""
|
newConfig.SmtpHost = ""
|
||||||
if false != checkRequiredConfig(newConfig) {
|
if false != checkRequiredConfig(&newConfig) {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
27
forms.go
27
forms.go
|
@ -1,10 +1,11 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/microcosm-cc/bluemonday"
|
|
||||||
"html"
|
"html"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/microcosm-cc/bluemonday"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FormValues map[string][]string
|
type FormValues map[string][]string
|
||||||
|
@ -20,7 +21,7 @@ func FormHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = r.ParseForm()
|
_ = r.ParseForm()
|
||||||
sanitizedForm := sanitizeForm(r.PostForm)
|
sanitizedForm := sanitizeForm(&r.PostForm)
|
||||||
go func() {
|
go func() {
|
||||||
if !isBot(sanitizedForm) {
|
if !isBot(sanitizedForm) {
|
||||||
sendForm(sanitizedForm)
|
sendForm(sanitizedForm)
|
||||||
|
@ -30,23 +31,23 @@ func FormHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func sanitizeForm(values url.Values) FormValues {
|
func sanitizeForm(values *url.Values) *FormValues {
|
||||||
p := bluemonday.StrictPolicy()
|
p := bluemonday.StrictPolicy()
|
||||||
sanitizedForm := make(FormValues)
|
sanitizedForm := make(FormValues)
|
||||||
for key, values := range values {
|
for key, values := range *values {
|
||||||
var sanitizedValues []string
|
var sanitizedValues []string
|
||||||
for _, value := range values {
|
for _, value := range values {
|
||||||
sanitizedValues = append(sanitizedValues, html.UnescapeString(p.Sanitize(value)))
|
sanitizedValues = append(sanitizedValues, html.UnescapeString(p.Sanitize(value)))
|
||||||
}
|
}
|
||||||
sanitizedForm[html.UnescapeString(p.Sanitize(key))] = sanitizedValues
|
sanitizedForm[html.UnescapeString(p.Sanitize(key))] = sanitizedValues
|
||||||
}
|
}
|
||||||
return sanitizedForm
|
return &sanitizedForm
|
||||||
}
|
}
|
||||||
|
|
||||||
func isBot(values FormValues) bool {
|
func isBot(values *FormValues) bool {
|
||||||
for _, honeyPot := range appConfig.HoneyPots {
|
for _, honeyPot := range appConfig.HoneyPots {
|
||||||
if len(values[honeyPot]) > 0 {
|
if len((*values)[honeyPot]) > 0 {
|
||||||
for _, value := range values[honeyPot] {
|
for _, value := range (*values)[honeyPot] {
|
||||||
if value != "" {
|
if value != "" {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -56,15 +57,15 @@ func isBot(values FormValues) bool {
|
||||||
return checkValues(values)
|
return checkValues(values)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendResponse(values FormValues, w http.ResponseWriter) {
|
func sendResponse(values *FormValues, w http.ResponseWriter) {
|
||||||
if len(values["_redirectTo"]) == 1 && values["_redirectTo"][0] != "" {
|
if len((*values)["_redirectTo"]) == 1 && (*values)["_redirectTo"][0] != "" {
|
||||||
w.Header().Add("Location", values["_redirectTo"][0])
|
w.Header().Add("Location", (*values)["_redirectTo"][0])
|
||||||
w.WriteHeader(http.StatusSeeOther)
|
w.WriteHeader(http.StatusSeeOther)
|
||||||
_, _ = w.Write([]byte("Go to " + values["_redirectTo"][0]))
|
_, _ = w.Write([]byte("Go to " + (*values)["_redirectTo"][0]))
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
w.WriteHeader(http.StatusCreated)
|
w.WriteHeader(http.StatusCreated)
|
||||||
_, _ = w.Write([]byte("Submitted form"))
|
_, _ = w.Write([]byte("Submitted form"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,9 @@ import (
|
||||||
|
|
||||||
func Test_sanitizeForm(t *testing.T) {
|
func Test_sanitizeForm(t *testing.T) {
|
||||||
t.Run("Sanitize form", func(t *testing.T) {
|
t.Run("Sanitize form", func(t *testing.T) {
|
||||||
result := sanitizeForm(url.Values{"<b>Test</b>": {"<a href=\"https://example.com\">Test</a>"}})
|
result := sanitizeForm(&url.Values{"<b>Test</b>": {"<a href=\"https://example.com\">Test</a>"}})
|
||||||
want := FormValues{"Test": {"Test"}}
|
want := FormValues{"Test": {"Test"}}
|
||||||
if !reflect.DeepEqual(result, want) {
|
if !reflect.DeepEqual(*result, want) {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -52,21 +52,21 @@ func TestFormHandler(t *testing.T) {
|
||||||
func Test_isBot(t *testing.T) {
|
func Test_isBot(t *testing.T) {
|
||||||
t.Run("No bot", func(t *testing.T) {
|
t.Run("No bot", func(t *testing.T) {
|
||||||
os.Clearenv()
|
os.Clearenv()
|
||||||
result := isBot(FormValues{"_t_email": {""}})
|
result := isBot(&FormValues{"_t_email": {""}})
|
||||||
if !reflect.DeepEqual(result, false) {
|
if !reflect.DeepEqual(result, false) {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("No honeypot", func(t *testing.T) {
|
t.Run("No honeypot", func(t *testing.T) {
|
||||||
os.Clearenv()
|
os.Clearenv()
|
||||||
result := isBot(FormValues{})
|
result := isBot(&FormValues{})
|
||||||
if !reflect.DeepEqual(result, false) {
|
if !reflect.DeepEqual(result, false) {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("Bot", func(t *testing.T) {
|
t.Run("Bot", func(t *testing.T) {
|
||||||
os.Clearenv()
|
os.Clearenv()
|
||||||
result := isBot(FormValues{"_t_email": {"Test", ""}})
|
result := isBot(&FormValues{"_t_email": {"Test", ""}})
|
||||||
if !reflect.DeepEqual(result, true) {
|
if !reflect.DeepEqual(result, true) {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ func Test_isBot(t *testing.T) {
|
||||||
|
|
||||||
func Test_sendResponse(t *testing.T) {
|
func Test_sendResponse(t *testing.T) {
|
||||||
t.Run("No redirect", func(t *testing.T) {
|
t.Run("No redirect", func(t *testing.T) {
|
||||||
values := FormValues{}
|
values := &FormValues{}
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
sendResponse(values, w)
|
sendResponse(values, w)
|
||||||
if w.Code != http.StatusCreated {
|
if w.Code != http.StatusCreated {
|
||||||
|
@ -83,7 +83,7 @@ func Test_sendResponse(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("No redirect 2", func(t *testing.T) {
|
t.Run("No redirect 2", func(t *testing.T) {
|
||||||
values := FormValues{
|
values := &FormValues{
|
||||||
"_redirectTo": {""},
|
"_redirectTo": {""},
|
||||||
}
|
}
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
@ -93,7 +93,7 @@ func Test_sendResponse(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("No redirect 3", func(t *testing.T) {
|
t.Run("No redirect 3", func(t *testing.T) {
|
||||||
values := FormValues{
|
values := &FormValues{
|
||||||
"_redirectTo": {"abc", "def"},
|
"_redirectTo": {"abc", "def"},
|
||||||
}
|
}
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
@ -103,7 +103,7 @@ func Test_sendResponse(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("Redirect", func(t *testing.T) {
|
t.Run("Redirect", func(t *testing.T) {
|
||||||
values := FormValues{
|
values := &FormValues{
|
||||||
"_redirectTo": {"https://example.com"},
|
"_redirectTo": {"https://example.com"},
|
||||||
}
|
}
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
@ -115,4 +115,4 @@ func Test_sendResponse(t *testing.T) {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
32
mail.go
32
mail.go
|
@ -10,12 +10,12 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func sendForm(values FormValues) {
|
func sendForm(values *FormValues) {
|
||||||
recipient := findRecipient(values)
|
recipient := findRecipient(values)
|
||||||
sendMail(recipient, buildMessage(recipient, time.Now(), values))
|
sendMail(recipient, buildMessage(recipient, time.Now(), values))
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildMessage(recipient string, date time.Time, values FormValues) string {
|
func buildMessage(recipient string, date time.Time, values *FormValues) string {
|
||||||
var msgBuffer bytes.Buffer
|
var msgBuffer bytes.Buffer
|
||||||
_, _ = fmt.Fprintf(&msgBuffer, "From: Forms <%s>", appConfig.Sender)
|
_, _ = fmt.Fprintf(&msgBuffer, "From: Forms <%s>", appConfig.Sender)
|
||||||
_, _ = fmt.Fprintln(&msgBuffer)
|
_, _ = fmt.Fprintln(&msgBuffer)
|
||||||
|
@ -32,14 +32,14 @@ func buildMessage(recipient string, date time.Time, values FormValues) string {
|
||||||
_, _ = fmt.Fprintln(&msgBuffer)
|
_, _ = fmt.Fprintln(&msgBuffer)
|
||||||
bodyValues := removeMetaValues(values)
|
bodyValues := removeMetaValues(values)
|
||||||
var keys []string
|
var keys []string
|
||||||
for key, _ := range bodyValues {
|
for key := range *bodyValues {
|
||||||
keys = append(keys, key)
|
keys = append(keys, key)
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
_, _ = fmt.Fprint(&msgBuffer, key)
|
_, _ = fmt.Fprint(&msgBuffer, key)
|
||||||
_, _ = fmt.Fprint(&msgBuffer, ": ")
|
_, _ = fmt.Fprint(&msgBuffer, ": ")
|
||||||
_, _ = fmt.Fprintln(&msgBuffer, strings.Join(bodyValues[key], ", "))
|
_, _ = fmt.Fprintln(&msgBuffer, strings.Join((*bodyValues)[key], ", "))
|
||||||
}
|
}
|
||||||
return msgBuffer.String()
|
return msgBuffer.String()
|
||||||
}
|
}
|
||||||
|
@ -52,9 +52,9 @@ func sendMail(to, message string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func findRecipient(values FormValues) string {
|
func findRecipient(values *FormValues) string {
|
||||||
if len(values["_to"]) == 1 && values["_to"][0] != "" {
|
if len((*values)["_to"]) == 1 && (*values)["_to"][0] != "" {
|
||||||
formDefinedRecipient := values["_to"][0]
|
formDefinedRecipient := (*values)["_to"][0]
|
||||||
for _, allowed := range appConfig.AllowedRecipients {
|
for _, allowed := range appConfig.AllowedRecipients {
|
||||||
if formDefinedRecipient == allowed {
|
if formDefinedRecipient == allowed {
|
||||||
return formDefinedRecipient
|
return formDefinedRecipient
|
||||||
|
@ -64,26 +64,26 @@ func findRecipient(values FormValues) string {
|
||||||
return appConfig.DefaultRecipient
|
return appConfig.DefaultRecipient
|
||||||
}
|
}
|
||||||
|
|
||||||
func findFormName(values FormValues) string {
|
func findFormName(values *FormValues) string {
|
||||||
if len(values["_formName"]) == 1 && values["_formName"][0] != "" {
|
if len((*values)["_formName"]) == 1 && (*values)["_formName"][0] != "" {
|
||||||
return values["_formName"][0]
|
return (*values)["_formName"][0]
|
||||||
}
|
}
|
||||||
return "a form"
|
return "a form"
|
||||||
}
|
}
|
||||||
|
|
||||||
func findReplyTo(values FormValues) string {
|
func findReplyTo(values *FormValues) string {
|
||||||
if len(values["_replyTo"]) == 1 && values["_replyTo"][0] != "" {
|
if len((*values)["_replyTo"]) == 1 && (*values)["_replyTo"][0] != "" {
|
||||||
return values["_replyTo"][0]
|
return (*values)["_replyTo"][0]
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeMetaValues(values FormValues) FormValues {
|
func removeMetaValues(values *FormValues) *FormValues {
|
||||||
cleanedValues := FormValues{}
|
cleanedValues := FormValues{}
|
||||||
for key, value := range values {
|
for key, value := range *values {
|
||||||
if !strings.HasPrefix(key, "_") {
|
if !strings.HasPrefix(key, "_") {
|
||||||
cleanedValues[key] = value
|
cleanedValues[key] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cleanedValues
|
return &cleanedValues
|
||||||
}
|
}
|
||||||
|
|
28
mail_test.go
28
mail_test.go
|
@ -17,7 +17,7 @@ func Test_findRecipient(t *testing.T) {
|
||||||
}
|
}
|
||||||
t.Run("No recipient specified", func(t *testing.T) {
|
t.Run("No recipient specified", func(t *testing.T) {
|
||||||
prepare()
|
prepare()
|
||||||
values := FormValues{}
|
values := &FormValues{}
|
||||||
result := findRecipient(values)
|
result := findRecipient(values)
|
||||||
if result != "mail@example.com" {
|
if result != "mail@example.com" {
|
||||||
t.Error()
|
t.Error()
|
||||||
|
@ -25,7 +25,7 @@ func Test_findRecipient(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Multiple recipients specified", func(t *testing.T) {
|
t.Run("Multiple recipients specified", func(t *testing.T) {
|
||||||
prepare()
|
prepare()
|
||||||
values := FormValues{
|
values := &FormValues{
|
||||||
"_to": {"abc@example.com", "def@example.com"},
|
"_to": {"abc@example.com", "def@example.com"},
|
||||||
}
|
}
|
||||||
result := findRecipient(values)
|
result := findRecipient(values)
|
||||||
|
@ -35,7 +35,7 @@ func Test_findRecipient(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Allowed recipient specified", func(t *testing.T) {
|
t.Run("Allowed recipient specified", func(t *testing.T) {
|
||||||
prepare()
|
prepare()
|
||||||
values := FormValues{
|
values := &FormValues{
|
||||||
"_to": {"test@example.com"},
|
"_to": {"test@example.com"},
|
||||||
}
|
}
|
||||||
result := findRecipient(values)
|
result := findRecipient(values)
|
||||||
|
@ -45,7 +45,7 @@ func Test_findRecipient(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Forbidden recipient specified", func(t *testing.T) {
|
t.Run("Forbidden recipient specified", func(t *testing.T) {
|
||||||
prepare()
|
prepare()
|
||||||
values := FormValues{
|
values := &FormValues{
|
||||||
"_to": {"forbidden@example.com"},
|
"_to": {"forbidden@example.com"},
|
||||||
}
|
}
|
||||||
result := findRecipient(values)
|
result := findRecipient(values)
|
||||||
|
@ -57,17 +57,17 @@ func Test_findRecipient(t *testing.T) {
|
||||||
|
|
||||||
func Test_findFormName(t *testing.T) {
|
func Test_findFormName(t *testing.T) {
|
||||||
t.Run("No form name", func(t *testing.T) {
|
t.Run("No form name", func(t *testing.T) {
|
||||||
if "a form" != findFormName(FormValues{}) {
|
if "a form" != findFormName(&FormValues{}) {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("Multiple form names", func(t *testing.T) {
|
t.Run("Multiple form names", func(t *testing.T) {
|
||||||
if "a form" != findFormName(FormValues{"_formName": {"Test", "ABC"}}) {
|
if "a form" != findFormName(&FormValues{"_formName": {"Test", "ABC"}}) {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("Form name", func(t *testing.T) {
|
t.Run("Form name", func(t *testing.T) {
|
||||||
if "Test" != findFormName(FormValues{"_formName": {"Test"}}) {
|
if "Test" != findFormName(&FormValues{"_formName": {"Test"}}) {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -75,17 +75,17 @@ func Test_findFormName(t *testing.T) {
|
||||||
|
|
||||||
func Test_findReplyTo(t *testing.T) {
|
func Test_findReplyTo(t *testing.T) {
|
||||||
t.Run("No replyTo", func(t *testing.T) {
|
t.Run("No replyTo", func(t *testing.T) {
|
||||||
if "" != findReplyTo(FormValues{}) {
|
if "" != findReplyTo(&FormValues{}) {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("Multiple replyTo", func(t *testing.T) {
|
t.Run("Multiple replyTo", func(t *testing.T) {
|
||||||
if "" != findReplyTo(FormValues{"_replyTo": {"test@example.com", "test2@example.com"}}) {
|
if "" != findReplyTo(&FormValues{"_replyTo": {"test@example.com", "test2@example.com"}}) {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("replyTo", func(t *testing.T) {
|
t.Run("replyTo", func(t *testing.T) {
|
||||||
if "test@example.com" != findReplyTo(FormValues{"_replyTo": {"test@example.com"}}) {
|
if "test@example.com" != findReplyTo(&FormValues{"_replyTo": {"test@example.com"}}) {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -93,14 +93,14 @@ func Test_findReplyTo(t *testing.T) {
|
||||||
|
|
||||||
func Test_removeMetaValues(t *testing.T) {
|
func Test_removeMetaValues(t *testing.T) {
|
||||||
t.Run("Remove meta values", func(t *testing.T) {
|
t.Run("Remove meta values", func(t *testing.T) {
|
||||||
result := removeMetaValues(FormValues{
|
result := removeMetaValues(&FormValues{
|
||||||
"_test": {"abc"},
|
"_test": {"abc"},
|
||||||
"test": {"def"},
|
"test": {"def"},
|
||||||
})
|
})
|
||||||
want := FormValues{
|
want := FormValues{
|
||||||
"test": {"def"},
|
"test": {"def"},
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(result, want) {
|
if !reflect.DeepEqual(*result, want) {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -113,7 +113,7 @@ func Test_buildMessage(t *testing.T) {
|
||||||
_ = os.Setenv("ALLOWED_TO", "mail@example.com,test@example.com")
|
_ = os.Setenv("ALLOWED_TO", "mail@example.com,test@example.com")
|
||||||
_ = os.Setenv("EMAIL_FROM", "forms@example.com")
|
_ = os.Setenv("EMAIL_FROM", "forms@example.com")
|
||||||
appConfig, _ = parseConfig()
|
appConfig, _ = parseConfig()
|
||||||
values := FormValues{
|
values := &FormValues{
|
||||||
"_formName": {"Testform"},
|
"_formName": {"Testform"},
|
||||||
"_replyTo": {"reply@example.com"},
|
"_replyTo": {"reply@example.com"},
|
||||||
"Testkey": {"Testvalue"},
|
"Testkey": {"Testvalue"},
|
||||||
|
@ -134,4 +134,4 @@ func Test_buildMessage(t *testing.T) {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
var appConfig config
|
var appConfig *config
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cfg, err := parseConfig()
|
cfg, err := parseConfig()
|
||||||
|
|
19
spamcheck.go
19
spamcheck.go
|
@ -1,16 +1,17 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/google/safebrowsing"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/google/safebrowsing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Returns true when it spam
|
// Returns true when it spam
|
||||||
func checkValues(values FormValues) bool {
|
func checkValues(values *FormValues) bool {
|
||||||
var urlsToCheck []string
|
var urlsToCheck []string
|
||||||
var allValues []string
|
var allValues []string
|
||||||
for _, value := range values {
|
for _, value := range *values {
|
||||||
for _, singleValue := range value {
|
for _, singleValue := range value {
|
||||||
allValues = append(allValues, singleValue)
|
allValues = append(allValues, singleValue)
|
||||||
if strings.Contains(singleValue, "http") {
|
if strings.Contains(singleValue, "http") {
|
||||||
|
@ -21,11 +22,11 @@ func checkValues(values FormValues) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return checkBlacklist(allValues) || checkUrls(urlsToCheck)
|
return checkBlacklist(&allValues) || checkUrls(&urlsToCheck)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkBlacklist(values []string) bool {
|
func checkBlacklist(values *[]string) bool {
|
||||||
for _, value := range values {
|
for _, value := range *values {
|
||||||
for _, blacklistedString := range appConfig.Blacklist {
|
for _, blacklistedString := range appConfig.Blacklist {
|
||||||
if strings.Contains(strings.ToLower(value), strings.ToLower(blacklistedString)) {
|
if strings.Contains(strings.ToLower(value), strings.ToLower(blacklistedString)) {
|
||||||
return true
|
return true
|
||||||
|
@ -38,8 +39,8 @@ func checkBlacklist(values []string) bool {
|
||||||
|
|
||||||
// Only tests when GOOGLE_API_KEY is set
|
// Only tests when GOOGLE_API_KEY is set
|
||||||
// Returns true when it spam
|
// Returns true when it spam
|
||||||
func checkUrls(urlsToCheck []string) bool {
|
func checkUrls(urlsToCheck *[]string) bool {
|
||||||
if len(appConfig.GoogleApiKey) < 1 || len(urlsToCheck) == 0 {
|
if len(appConfig.GoogleApiKey) < 1 || len(*urlsToCheck) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
sb, err := safebrowsing.NewSafeBrowser(safebrowsing.Config{
|
sb, err := safebrowsing.NewSafeBrowser(safebrowsing.Config{
|
||||||
|
@ -49,7 +50,7 @@ func checkUrls(urlsToCheck []string) bool {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
allThreats, err := sb.LookupURLs(urlsToCheck)
|
allThreats, err := sb.LookupURLs(*urlsToCheck)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,13 +13,13 @@ func Test_checkBlacklist(t *testing.T) {
|
||||||
}
|
}
|
||||||
t.Run("Allowed values", func(t *testing.T) {
|
t.Run("Allowed values", func(t *testing.T) {
|
||||||
prepare()
|
prepare()
|
||||||
if checkBlacklist([]string{"Hello", "How are you?"}) == true {
|
if checkBlacklist(&[]string{"Hello", "How are you?"}) == true {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
t.Run("Forbidden values", func(t *testing.T) {
|
t.Run("Forbidden values", func(t *testing.T) {
|
||||||
prepare()
|
prepare()
|
||||||
if checkBlacklist([]string{"How are you?", "Hello TeSt1"}) == false {
|
if checkBlacklist(&[]string{"How are you?", "Hello TeSt1"}) == false {
|
||||||
t.Error()
|
t.Error()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Reference in New Issue