From 2af81a7430481b3aec40f6a794db8cde4e1e18e4 Mon Sep 17 00:00:00 2001 From: Tim Culverhouse Date: Tue, 20 Dec 2022 13:25:35 -0600 Subject: pgp: add configurable error level for opportunistic encryption Add a user-configurable error level for when opportunistic encryption is enabled but the message cannot be encrypted. Set the default level to this as "warn". This config option *only* applies when opportunistic encryption is enabled. If a user tries to manually encrypt a message, an error will still be shown. Don't show encryption status until at least one recipient is added. Fixes: https://todo.sr.ht/~rjarry/aerc/95 Signed-off-by: Tim Culverhouse Acked-by: Robin Jarry --- config/accounts.go | 21 +++++++++++++++++++++ doc/aerc-accounts.5.scd | 9 ++++++++- widgets/compose.go | 16 +++++++++++++++- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/config/accounts.go b/config/accounts.go index 6cd30098..cbdf54a8 100644 --- a/config/accounts.go +++ b/config/accounts.go @@ -101,11 +101,18 @@ type AccountConfig struct { PgpKeyId string `ini:"pgp-key-id"` PgpAutoSign bool `ini:"pgp-auto-sign"` PgpOpportunisticEncrypt bool `ini:"pgp-opportunistic-encrypt"` + PgpErrorLevel int `ini:"pgp-error-level"` // AuthRes TrustedAuthRes []string `ini:"trusted-authres" delim:","` } +const ( + PgpErrorLevelNone = iota + PgpErrorLevelWarn + PgpErrorLevelError +) + var Accounts []*AccountConfig func parseAccounts(root string, accts []string) error { @@ -142,6 +149,7 @@ func parseAccounts(root string, accts []string) error { Params: make(map[string]string), EnableFoldersSort: true, CheckMailTimeout: 10 * time.Second, + PgpErrorLevel: PgpErrorLevelWarn, // localizedRe contains a list of known translations for the common Re: LocalizedRe: regexp.MustCompile(`(?i)^((AW|RE|SV|VS|ODP|R): ?)+`), } @@ -182,6 +190,17 @@ func parseAccounts(root string, accts []string) error { return fmt.Errorf("%s=%s %w", key, val, err) } account.LocalizedRe = re + case "pgp-error-level": + switch strings.ToLower(val) { + case "none": + account.PgpErrorLevel = PgpErrorLevelNone + case "warn": + account.PgpErrorLevel = PgpErrorLevelWarn + case "error": + account.PgpErrorLevel = PgpErrorLevelError + default: + return fmt.Errorf("unknown pgp-error-level: %s", val) + } default: backendSpecific := true typ := reflect.TypeOf(account) @@ -201,6 +220,8 @@ func parseAccounts(root string, accts []string) error { case "outgoing-cred-cmd-cache": fallthrough case "subject-re-pattern": + fallthrough + case "pgp-error-level": backendSpecific = false } } diff --git a/doc/aerc-accounts.5.scd b/doc/aerc-accounts.5.scd index 11d4d52c..a078e4bf 100644 --- a/doc/aerc-accounts.5.scd +++ b/doc/aerc-accounts.5.scd @@ -114,6 +114,12 @@ Note that many of these configuration options are written for you, such as Default: _false_ +*pgp-error-level* = _none_|_warn_|_error_ + The level of error to display when opportunistic encryption cannot be + performed. See *pgp-opportunistic-encryption*. + + Default: _warn_ + *pgp-key-id* = __ Specify the key id to use when signing a message. Can be either short or long key id. If unset, aerc will look up the key by email. @@ -121,7 +127,8 @@ Note that many of these configuration options are written for you, such as *pgp-opportunistic-encrypt* = _true_|_false_ If _true_, any outgoing email from this account will be encrypted when all recipients (including Cc and Bcc field) have a public key available in - the keyring. + the keyring. The level of error to display when a message can't be + encrypted can be configured with *pgp-error-level*. Default: _false_ diff --git a/widgets/compose.go b/widgets/compose.go index 1a59bd3a..aad566f5 100644 --- a/widgets/compose.go +++ b/widgets/compose.go @@ -1483,11 +1483,25 @@ func (c *Composer) checkEncryptionKeys(_ string) bool { mk = append(mk, rcpt) } } - if len(mk) > 0 { + switch { + case len(mk) > 0: c.SetEncrypt(false) st := fmt.Sprintf("Cannot encrypt, missing keys: %s", strings.Join(mk, ", ")) + if c.Config().PgpOpportunisticEncrypt { + switch c.Config().PgpErrorLevel { + case config.PgpErrorLevelWarn: + c.aerc.statusline.PushWarning(st) + return false + case config.PgpErrorLevelNone: + return false + case config.PgpErrorLevelError: + // Continue to the default + } + } c.aerc.statusline.PushError(st) return false + case len(rcpts) == 0: + return false } // If callbacks were registered, encrypt will be set when user removes // recipients with missing keys -- cgit