From abf6ec7f02edbf8721fb32e4e760ebda2c20bc50 Mon Sep 17 00:00:00 2001 From: Robin Jarry Date: Thu, 8 Sep 2022 20:18:31 +0200 Subject: [PATCH] config: keep cache of resolved credential commands outgoing-cred-cmd is used to retrieve the password from a password manager such as UNIX pass or bitwarden CLI. These tools often prompt for a passphrase to secure the passwords and it is annoying having to enter it every time sending an email with aerc. Add a new option outgoing-cred-cmd-cache (default to true) to control whether aerc will keep a cache of the password or run outgoing-cred-cmd every time an email needs to be sent. NB: If the cached password is incorrect, the only way to change it is to restart aerc. Fixes: ca9034385029 ("outgoing-cred-cmd: delay execution until an email needs to be sent") Signed-off-by: Robin Jarry Acked-by: Moritz Poldrack --- CHANGELOG.md | 7 +++++++ config/config.go | 38 ++++++++++++++++++++++++++------------ doc/aerc-config.5.scd | 7 +++++++ 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ce5622..8d8ee53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased](https://git.sr.ht/~rjarry/aerc/log/master) +### Fixed + +- `outgoing-cred-cmd` will no longer be executed every time an email needs to + be sent. The output will be stored until aerc is shut down. This behaviour + can be disabled by setting `outgoing-cred-cmd-cache=false` in + `accounts.conf`. + ## [0.12.0](https://git.sr.ht/~rjarry/aerc/refs/0.12.0) - 2022-09-01 ### Added diff --git a/config/config.go b/config/config.go index 9f2af8f..e7e4de0 100644 --- a/config/config.go +++ b/config/config.go @@ -98,13 +98,15 @@ const ( type RemoteConfig struct { Value string PasswordCmd string + CacheCmd bool + cache string } -func (c RemoteConfig) parseValue() (*url.URL, error) { +func (c *RemoteConfig) parseValue() (*url.URL, error) { return url.Parse(c.Value) } -func (c RemoteConfig) ConnectionString() (string, error) { +func (c *RemoteConfig) ConnectionString() (string, error) { if c.Value == "" || c.PasswordCmd == "" { return c.Value, nil } @@ -124,18 +126,23 @@ func (c RemoteConfig) ConnectionString() (string, error) { return c.Value, nil } - cmd := exec.Command("sh", "-c", c.PasswordCmd) - cmd.Stdin = os.Stdin - output, err := cmd.Output() - if err != nil { - return "", fmt.Errorf("failed to read password: %w", err) + pw := c.cache + + if pw == "" { + cmd := exec.Command("sh", "-c", c.PasswordCmd) + cmd.Stdin = os.Stdin + output, err := cmd.Output() + if err != nil { + return "", fmt.Errorf("failed to read password: %w", err) + } + pw = strings.TrimSpace(string(output)) + } + u.User = url.UserPassword(u.User.Username(), pw) + if c.CacheCmd { + c.cache = pw } - pw := strings.TrimSpace(string(output)) - u.User = url.UserPassword(u.User.Username(), pw) - c.Value = u.String() - - return c.Value, nil + return u.String(), nil } type AccountConfig struct { @@ -314,6 +321,13 @@ func loadAccountConfig(path string, accts []string) ([]AccountConfig, error) { account.Outgoing.Value = val case "outgoing-cred-cmd": account.Outgoing.PasswordCmd = val + case "outgoing-cred-cmd-cache": + cache, err := strconv.ParseBool(val) + if err != nil { + return nil, fmt.Errorf( + "%s=%s %w", key, val, err) + } + account.Outgoing.CacheCmd = cache case "from": account.From = val case "aliases": diff --git a/doc/aerc-config.5.scd b/doc/aerc-config.5.scd index a87cbcc..b9ed0df 100644 --- a/doc/aerc-config.5.scd +++ b/doc/aerc-config.5.scd @@ -657,6 +657,13 @@ Note that many of these configuration options are written for you, such as Default: none +*outgoing-cred-cmd-cache* + By default, the credentials returned by the command will be cached until + aerc is shut down. If set to false, *outgoing-cred-cmd* will be executed + every time an email is to be sent. + + Default: true + *pgp-auto-sign* If true, all outgoing emails from this account will be signed (if a signing key is available)