git » spf » commit 5394931

Implement CheckHostWithSender

author Alberto Bertogli
2019-10-14 12:17:58 UTC
committer Alberto Bertogli
2019-10-14 12:18:21 UTC
parent 77378ca3855628a1d0e9f1b32599b56ddd35a32c

Implement CheckHostWithSender

The current API does not support passing a sender, which will be required
to support macros.

This patch adds a new function, CheckHostWithSender, which takes the
sender as well as the helo domain to use as a fallback in case of
the sender doesn't having a domain set.

spf.go +27 -1

diff --git a/spf.go b/spf.go
index 2edcb6d..a1f88a3 100644
--- a/spf.go
+++ b/spf.go
@@ -109,14 +109,40 @@ var (
 // to determine if `ip` is permitted to send mail for it.
 // Reference: https://tools.ietf.org/html/rfc7208#section-4
 func CheckHost(ip net.IP, domain string) (Result, error) {
-	r := &resolution{ip, 0, nil}
+	r := &resolution{ip, 0, "", nil}
 	return r.Check(domain)
 }
 
+// CheckHostWithSender fetches SPF records for `domain`, parses them, and
+// evaluates them to determine if `ip` is permitted to send mail for it.
+// The sender is used in macro expansion.
+// Reference: https://tools.ietf.org/html/rfc7208#section-4
+func CheckHostWithSender(ip net.IP, helo, sender string) (Result, error) {
+	_, domain := split(sender)
+	if domain == "" {
+		domain = helo
+	}
+
+	r := &resolution{ip, 0, sender, nil}
+	return r.Check(domain)
+}
+
+// split an user@domain address into user and domain.
+func split(addr string) (string, string) {
+	ps := strings.SplitN(addr, "@", 2)
+	if len(ps) != 2 {
+		return addr, ""
+	}
+
+	return ps[0], ps[1]
+}
+
 type resolution struct {
 	ip    net.IP
 	count uint
 
+	sender string
+
 	// Result of doing a reverse lookup for ip (so we only do it once).
 	ipNames []string
 }