author | Alberto Bertogli
<albertito@blitiri.com.ar> 2022-01-20 09:36:58 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2022-01-21 12:07:34 UTC |
parent | fa1db7d81aff54c67c54cc505fb71851a54c0f6f |
docs/aliases.md | +4 | -4 |
docs/hooks.md | +0 | -14 |
internal/aliases/aliases.go | +15 | -47 |
internal/smtpsrv/server.go | +0 | -1 |
test/t-04-aliases/alias-exists-hook | +0 | -15 |
test/t-04-aliases/run.sh | +0 | -3 |
diff --git a/docs/aliases.md b/docs/aliases.md index 68081ca..f4ad31a 100644 --- a/docs/aliases.md +++ b/docs/aliases.md @@ -85,11 +85,11 @@ aliases. ## Hooks -There are two hooks that allow more sophisticated aliases resolution: -`alias-exists` and `alias-resolve`. +There is a hook that allows more sophisticated aliases resolution: +`alias-resolve`. -If they exist, they are invoked as part of the resolution process and the -results are merged with the file-based resolution results. +If it exists, it is invoked as part of the resolution process, and the results +are merged with the file-based resolution results. See the [hooks](hooks.md) documentation for more details. diff --git a/docs/hooks.md b/docs/hooks.md index cc469bc..14300e2 100644 --- a/docs/hooks.md +++ b/docs/hooks.md @@ -73,17 +73,3 @@ without emitting any output. There is a 5 second timeout for hook execution. If the hook exits with an error, including timeout, delivery will fail. - - -## Alias exists hook - -When chasquid needs to check whether an alias exists or not, it will run the -command at `$config_dir/hooks/alias-exists` (if the file exists). - -The address to check will be passed as the single argument. - -If the commands exits successfuly (exit code 0), then the alias exists; any -other exit code signals that the alias does not exist. - -There is a 5 second timeout for hook execution. If the hook times out, the -alias will be assumed not to exist. diff --git a/internal/aliases/aliases.go b/internal/aliases/aliases.go index 897659f..7ba6bf7 100644 --- a/internal/aliases/aliases.go +++ b/internal/aliases/aliases.go @@ -112,8 +112,7 @@ type Resolver struct { // Characters to drop from the user part. DropChars string - // Path to resolve and exist hooks. - ExistsHook string + // Path to the resolve hook. ResolveHook string // Map of domain -> alias files for that domain. @@ -148,16 +147,23 @@ func (v *Resolver) Resolve(addr string) ([]Recipient, error) { // The clean address can be used to look it up in other databases, even if it // doesn't exist. func (v *Resolver) Exists(addr string) (string, bool) { - v.mu.Lock() addr = v.cleanIfLocal(addr) - _, ok := v.aliases[addr] + + rcpts, _ := v.lookup(addr) + return addr, len(rcpts) > 0 +} + +func (v *Resolver) lookup(addr string) ([]Recipient, error) { + v.mu.Lock() + rcpts := v.aliases[addr] v.mu.Unlock() - if ok { - return addr, true + // Augment with the hook results. + hr, err := v.runResolveHook(addr) + if err != nil { + return nil, err } - - return addr, v.runExistsHook(addr) + return append(rcpts, hr...), nil } func (v *Resolver) resolve(rcount int, addr string) ([]Recipient, error) { @@ -171,16 +177,10 @@ func (v *Resolver) resolve(rcount int, addr string) ([]Recipient, error) { addr = v.cleanIfLocal(addr) // Lookup in the aliases database. - v.mu.Lock() - rcpts := v.aliases[addr] - v.mu.Unlock() - - // Augment with the hook results. - hr, err := v.runResolveHook(addr) + rcpts, err := v.lookup(addr) if err != nil { return nil, err } - rcpts = append(rcpts, hr...) if len(rcpts) == 0 { return []Recipient{{addr, EMAIL}}, nil @@ -435,35 +435,3 @@ func (v *Resolver) runResolveHook(addr string) ([]Recipient, error) { hookResults.Add("resolve:success", 1) return rs, nil } - -func (v *Resolver) runExistsHook(addr string) bool { - if v.ExistsHook == "" { - hookResults.Add("exists:notset", 1) - return false - } - // TODO: check if the file is executable. - if _, err := os.Stat(v.ExistsHook); os.IsNotExist(err) { - hookResults.Add("exists:skip", 1) - return false - } - - // TODO: this should be done via a context propagated all the way through. - tr := trace.New("Hook.Alias-Exists", addr) - defer tr.Finish() - - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - cmd := exec.CommandContext(ctx, v.ExistsHook, addr) - - out, err := cmd.CombinedOutput() - tr.Debugf("output: %q", string(out)) - if err != nil { - tr.Debugf("not exists: %v", err) - hookResults.Add("exists:false", 1) - return false - } - - tr.Debugf("exists") - hookResults.Add("exists:true", 1) - return true -} diff --git a/internal/smtpsrv/server.go b/internal/smtpsrv/server.go index 422cf55..b4a5509 100644 --- a/internal/smtpsrv/server.go +++ b/internal/smtpsrv/server.go @@ -134,7 +134,6 @@ func (s *Server) SetAliasesConfig(suffixSep, dropChars string) { s.aliasesR.SuffixSep = suffixSep s.aliasesR.DropChars = dropChars s.aliasesR.ResolveHook = path.Join(s.HookPath, "alias-resolve") - s.aliasesR.ExistsHook = path.Join(s.HookPath, "alias-exists") } // InitDomainInfo initializes the domain info database. diff --git a/test/t-04-aliases/alias-exists-hook b/test/t-04-aliases/alias-exists-hook deleted file mode 100755 index 770937c..0000000 --- a/test/t-04-aliases/alias-exists-hook +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -case "$1" in -"vicuña@testserver") - exit 0 - ;; -"ñandú@testserver") - exit 0 - ;; -"roto@testserver") - exit 0 - ;; -esac - -exit 1 diff --git a/test/t-04-aliases/run.sh b/test/t-04-aliases/run.sh index 2656dc3..c500c31 100755 --- a/test/t-04-aliases/run.sh +++ b/test/t-04-aliases/run.sh @@ -25,7 +25,6 @@ function send_and_check() { # Remove the hooks that could be left over from previous failed tests. rm -f config/hooks/alias-resolve -rm -f config/hooks/alias-exists # Test email aliases. send_and_check pepe jose @@ -46,7 +45,6 @@ mail_diff content .data/pipe_alias_worked # Set up the hooks. mkdir -p config/hooks/ -cp alias-exists-hook config/hooks/alias-exists cp alias-resolve-hook config/hooks/alias-resolve # Test email aliases. @@ -70,6 +68,5 @@ fi # Remove the hooks, leave a clean state. rm -f config/hooks/alias-resolve -rm -f config/hooks/alias-exists success