Files
mailgoserver/internal/mailstore/spam_test.go
T

53 lines
1.8 KiB
Go
Raw Normal View History

2026-08-12 21:14:19 +01:00
package mailstore
import (
"net"
"testing"
)
// TestSpamScoreArithmetic exercises SpamScore's own weighting logic with synthetic
// dkimPass/spfPass inputs — CheckDNSBL still runs (it does live DNS), so this only
// asserts the score is monotonically at least as high when signals get worse, rather
// than pinning an exact network-dependent number.
func TestSpamScoreArithmetic(t *testing.T) {
clean := SpamScore("203.0.113.1", map[string]string{"subject": "hello"}, true, true)
noDKIM := SpamScore("203.0.113.1", map[string]string{"subject": "hello"}, false, true)
noSPF := SpamScore("203.0.113.1", map[string]string{"subject": "hello"}, true, false)
keyword := SpamScore("203.0.113.1", map[string]string{"subject": "WIN THE LOTTERY WINNER NOW"}, true, true)
if noDKIM <= clean {
t.Fatalf("missing DKIM should raise the score: clean=%d noDKIM=%d", clean, noDKIM)
}
if noSPF <= clean {
t.Fatalf("failing SPF should raise the score: clean=%d noSPF=%d", clean, noSPF)
}
if keyword <= clean {
t.Fatalf("a spam keyword in the subject should raise the score: clean=%d keyword=%d", clean, keyword)
}
}
func TestEvalSPF(t *testing.T) {
ip := net.ParseIP("203.0.113.10")
other := net.ParseIP("198.51.100.5")
tests := []struct {
name string
record string
ip net.IP
want bool
}{
{"ip4 match passes", "v=spf1 ip4:203.0.113.0/24 -all", ip, true},
{"ip4 no match hard fails", "v=spf1 ip4:203.0.113.0/24 -all", other, false},
{"no all and no match is neutral", "v=spf1 ip4:203.0.113.0/24", other, true},
{"soft fail all is neutral for unmatched ip", "v=spf1 ip4:203.0.113.0/24 ~all", other, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := evalSPF(tt.record, tt.ip, "example.com", 0)
if got != tt.want {
t.Fatalf("evalSPF(%q) = %v, want %v", tt.record, got, tt.want)
}
})
}
}