git » chasquid » commit feb1029

aliases: Skip resolution logic for non-local addresses

author Alberto Bertogli
2022-01-20 09:55:16 UTC
committer Alberto Bertogli
2022-01-21 12:07:34 UTC
parent 67d0064f57595228494fd4b77c260992988b67b8

aliases: Skip resolution logic for non-local addresses

This patch skips the resolution logic if the address is not local.
Today, the resolution logic handles that case transparently, and returns
the original email address, so this should be a no-op.

However, having an explicit early check makes the resolution logic more
robust, and will simplify future patches.

Note this also means that the `alias-resolve` hook is no longer run for
non-local aliases, which should also help simplify their implementation.

internal/aliases/aliases.go +8 -1
internal/aliases/aliases_test.go +16 -7

diff --git a/internal/aliases/aliases.go b/internal/aliases/aliases.go
index 7ba6bf7..1909f2b 100644
--- a/internal/aliases/aliases.go
+++ b/internal/aliases/aliases.go
@@ -145,7 +145,7 @@ func (v *Resolver) Resolve(addr string) ([]Recipient, error) {
 // Exists check that the address exists in the database.
 // It returns the cleaned address, and a boolean indicating the result.
 // The clean address can be used to look it up in other databases, even if it
-// doesn't exist.
+// doesn't exist. It must only be called for local addresses.
 func (v *Resolver) Exists(addr string) (string, bool) {
 	addr = v.cleanIfLocal(addr)
 
@@ -171,6 +171,13 @@ func (v *Resolver) resolve(rcount int, addr string) ([]Recipient, error) {
 		return nil, ErrRecursionLimitExceeded
 	}
 
+	// If the address is not local, we return it as-is, so delivery is
+	// attempted against it.
+	// Example: an alias that resolves to a non-local address.
+	if _, ok := v.domains[envelope.DomainOf(addr)]; !ok {
+		return []Recipient{{addr, EMAIL}}, nil
+	}
+
 	// Drop suffixes and chars to get the "clean" address before resolving.
 	// This also means that we will return the clean version if there's no
 	// match, which our callers can rely upon.
diff --git a/internal/aliases/aliases_test.go b/internal/aliases/aliases_test.go
index 9c778b6..49118de 100644
--- a/internal/aliases/aliases_test.go
+++ b/internal/aliases/aliases_test.go
@@ -13,6 +13,7 @@ type Cases []struct {
 }
 
 func (cases Cases) check(t *testing.T, r *Resolver) {
+	t.Helper()
 	for _, c := range cases {
 		got, err := r.Resolve(c.addr)
 		if err != nil {
@@ -26,6 +27,7 @@ func (cases Cases) check(t *testing.T, r *Resolver) {
 }
 
 func mustExist(t *testing.T, r *Resolver, addrs ...string) {
+	t.Helper()
 	for _, addr := range addrs {
 		if _, ok := r.Exists(addr); !ok {
 			t.Errorf("address %q does not exist, it should", addr)
@@ -34,6 +36,7 @@ func mustExist(t *testing.T, r *Resolver, addrs ...string) {
 }
 
 func mustNotExist(t *testing.T, r *Resolver, addrs ...string) {
+	t.Helper()
 	for _, addr := range addrs {
 		if _, ok := r.Exists(addr); ok {
 			t.Errorf("address %q exists, it should not", addr)
@@ -43,20 +46,22 @@ func mustNotExist(t *testing.T, r *Resolver, addrs ...string) {
 
 func TestBasic(t *testing.T) {
 	resolver := NewResolver()
+	resolver.AddDomain("localA")
+	resolver.AddDomain("localB")
 	resolver.aliases = map[string][]Recipient{
-		"a@b": {{"c@d", EMAIL}, {"e@f", EMAIL}},
-		"e@f": {{"cmd", PIPE}},
-		"cmd": {{"x@y", EMAIL}}, // it's a trap!
+		"a@localA": {{"c@d", EMAIL}, {"e@localB", EMAIL}},
+		"e@localB": {{"cmd", PIPE}},
+		"cmd":      {{"x@y", EMAIL}}, // it's a trap!
 	}
 
 	cases := Cases{
-		{"a@b", []Recipient{{"c@d", EMAIL}, {"cmd", PIPE}}},
-		{"e@f", []Recipient{{"cmd", PIPE}}},
+		{"a@localA", []Recipient{{"c@d", EMAIL}, {"cmd", PIPE}}},
+		{"e@localB", []Recipient{{"cmd", PIPE}}},
 		{"x@y", []Recipient{{"x@y", EMAIL}}},
 	}
 	cases.check(t, resolver)
 
-	mustExist(t, resolver, "a@b", "e@f", "cmd")
+	mustExist(t, resolver, "a@localA", "e@localB", "cmd")
 	mustNotExist(t, resolver, "x@y")
 }
 
@@ -68,6 +73,7 @@ func TestAddrRewrite(t *testing.T) {
 		"abc@def":  {{"x@y", EMAIL}},
 		"ñoño@def": {{"x@y", EMAIL}},
 		"recu@def": {{"ab+cd@p-q.com", EMAIL}},
+		"remo@def": {{"x-@y-z.com", EMAIL}},
 	}
 	resolver.DropChars = ".~"
 	resolver.SuffixSep = "-+"
@@ -96,6 +102,7 @@ func TestAddrRewrite(t *testing.T) {
 		{"x.y@z.com", []Recipient{{"x.y@z.com", EMAIL}}},
 		{"x-@y-z.com", []Recipient{{"x-@y-z.com", EMAIL}}},
 		{"x+blah@y", []Recipient{{"x+blah@y", EMAIL}}},
+		{"remo@def", []Recipient{{"x-@y-z.com", EMAIL}}},
 	}
 	cases.check(t, resolver)
 }
@@ -143,7 +150,9 @@ func TestExistsRewrite(t *testing.T) {
 }
 
 func TestTooMuchRecursion(t *testing.T) {
-	resolver := Resolver{}
+	resolver := NewResolver()
+	resolver.AddDomain("b")
+	resolver.AddDomain("d")
 	resolver.aliases = map[string][]Recipient{
 		"a@b": {{"c@d", EMAIL}},
 		"c@d": {{"a@b", EMAIL}},