author | Alberto Bertogli
<albertito@blitiri.com.ar> 2022-01-20 09:55:16 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2022-01-21 12:07:34 UTC |
parent | 67d0064f57595228494fd4b77c260992988b67b8 |
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}},