Support using a command which returns the password. Update
documentation.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
---
doc/offmap.5.scd | 9 +++++++--
imap/imap.go | 21 ++++++++++++++++++---
2 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/doc/offmap.5.scd b/doc/offmap.5.scd
index f7913d58e2ce..a958c74f0fcf 100644
--- a/doc/offmap.5.scd
+++ b/doc/offmap.5.scd
@@ -35,8 +35,13 @@ password = "my-password"
*username* (required)
The username to login to the IMAP server with.
-*password* (required)
- The password to use for the IMAP server.
+*password* (optional)
+ The password to use for the IMAP server. Either this or *password-cmd*
+ are required.
+
+*password-cmd* (optional)
+ A command to run which returns the password. Either this or *password*
+ are required.
*max-connections* (optional)
The maximum number of IMAP clients to spawn. Some providers limit the
diff --git a/imap/imap.go b/imap/imap.go
index be500ecd4277..626be2f7528a 100644
--- a/imap/imap.go
+++ b/imap/imap.go
@@ -4,6 +4,7 @@ import (
"fmt"
"io"
"os"
+ "os/exec"
"path"
"strconv"
"strings"
@@ -51,11 +52,25 @@ func NewStore(cfg *viper.Viper) (*Store, error) {
if store.username == "" {
return nil, fmt.Errorf("imap: no username set")
}
- // TODO support password commands
- store.password = cfg.GetString("password")
- if store.password == "" {
+
+ switch {
+ case cfg.GetString("password-cmd") != "":
+ cmd := exec.Command("sh", "-c", cfg.GetString("password-cmd"))
+ out, err := cmd.Output()
+ if err != nil {
+ return nil, fmt.Errorf("imap: could not get password: %v", err)
+ }
+ lines := strings.Split(string(out), "\n")
+ if len(lines) < 1 {
+ return nil, fmt.Errorf("imap: no output from password-cmd")
+ }
+ store.password = lines[0]
+ case cfg.GetString("password") != "":
+ store.password = cfg.GetString("password")
+ default:
return nil, fmt.Errorf("imap: no password set")
}
+
store.maxConns = cfg.GetInt("max-connections")
if store.maxConns < 1 {
store.maxConns = 2
--
2.38.1