feat(policy): case-insensitive address and domain matching
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
// Package policy holds pure enforcement functions: address matching,
|
||||
// inbound filtering, and (in a later phase) outbound checks.
|
||||
package policy
|
||||
|
||||
import (
|
||||
"net/mail"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// NormalizeAddr lower-cases an address and strips any display name/brackets.
|
||||
func NormalizeAddr(addr string) string {
|
||||
addr = strings.TrimSpace(addr)
|
||||
if a, err := mail.ParseAddress(addr); err == nil {
|
||||
return strings.ToLower(a.Address)
|
||||
}
|
||||
return strings.ToLower(strings.Trim(addr, "<> "))
|
||||
}
|
||||
|
||||
// MatchAddress reports whether addr matches any whitelist entry.
|
||||
// Entries beginning with '@' match a whole domain; others match exactly.
|
||||
func MatchAddress(entries []string, addr string) bool {
|
||||
norm := NormalizeAddr(addr)
|
||||
if norm == "" {
|
||||
return false
|
||||
}
|
||||
at := strings.LastIndex(norm, "@")
|
||||
domain := ""
|
||||
if at >= 0 {
|
||||
domain = norm[at:] // includes '@'
|
||||
}
|
||||
for _, e := range entries {
|
||||
e = strings.ToLower(strings.TrimSpace(e))
|
||||
if strings.HasPrefix(e, "@") {
|
||||
if e == domain {
|
||||
return true
|
||||
}
|
||||
continue
|
||||
}
|
||||
if e == norm {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user