Add command 'check' which reports capabilities which will be used by
offmap.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
---
cmd/check.go | 39 +++++++++++++++++++++++++++++++++++++++
cmd/offmap.go | 1 +
go.mod | 1 +
go.sum | 2 ++
imap/capability.go | 40 ++++++++++++++++++++++++++++++++++++++++
imap/client.go | 9 ++++++++-
6 files changed, 91 insertions(+), 1 deletion(-)
create mode 100644 cmd/check.go
create mode 100644 imap/capability.go
diff --git a/cmd/check.go b/cmd/check.go
new file mode 100644
index 000000000000..b7cba265136c
--- /dev/null
+++ b/cmd/check.go
@@ -0,0 +1,39 @@
+package main
+
+import (
+ "fmt"
+
+ "git.sr.ht/~rockorager/offmap"
+ "git.sr.ht/~rockorager/offmap/imap"
+ "github.com/spf13/cobra"
+)
+
+func newCheckCommand() *cobra.Command {
+ cmd := &cobra.Command{
+ Use: "check",
+ Short: "check reports which capabilities of the imap server will be used",
+ RunE: check,
+ }
+ cmd.Flags().StringSliceP("account", "a", nil, "only sync the specified account(s)")
+ return cmd
+}
+
+func check(cmd *cobra.Command, args []string) error {
+ accts, err := cmd.Flags().GetStringSlice("account")
+ if err != nil {
+ return fmt.Errorf("offmap: could not parse account: %v", err)
+ }
+ cfgs, err := offmap.LoadConfig(accts)
+ if err != nil {
+ return fmt.Errorf("could not read config: %v", err)
+ }
+ for _, cfg := range cfgs {
+ fmt.Printf("Account %s\n", cfg.Name)
+ remote, err := imap.NewStore(cfg)
+ if err != nil {
+ return fmt.Errorf("could not create store: %v", err)
+ }
+ remote.Capabilities()
+ }
+ return nil
+}
diff --git a/cmd/offmap.go b/cmd/offmap.go
index 8a2176f28164..3fff3ccd4490 100644
--- a/cmd/offmap.go
+++ b/cmd/offmap.go
@@ -26,6 +26,7 @@ func main() {
cmd.AddCommand(newSyncCommand())
cmd.AddCommand(newDiffCommand())
+ cmd.AddCommand(newCheckCommand())
if err := cmd.ExecuteContext(ctx); err != nil {
log.Fatalf("%v", err)
}
diff --git a/go.mod b/go.mod
index bf297c95025e..25baf16d0e9b 100644
--- a/go.mod
+++ b/go.mod
@@ -43,6 +43,7 @@ require (
github.com/daixiang0/gci v0.8.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/denis-tingaikin/go-header v0.4.3 // indirect
+ github.com/emersion/go-imap-quota v0.0.0-20210203125329-619074823f3c // indirect
github.com/esimonov/ifshort v1.0.4 // indirect
github.com/ettle/strcase v0.1.1 // indirect
github.com/fatih/color v1.13.0 // indirect
diff --git a/go.sum b/go.sum
index 342bc20835a0..dd03529f896d 100644
--- a/go.sum
+++ b/go.sum
@@ -118,6 +118,8 @@ github.com/denis-tingaikin/go-header v0.4.3 h1:tEaZKAlqql6SKCY++utLmkPLd6K8IBM20
github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYBAC2Mra5RassOIQ2/c=
github.com/emersion/go-imap v1.2.1 h1:+s9ZjMEjOB8NzZMVTM3cCenz2JrQIGGo5j1df19WjTA=
github.com/emersion/go-imap v1.2.1/go.mod h1:Qlx1FSx2FTxjnjWpIlVNEuX+ylerZQNFE5NsmKFSejY=
+github.com/emersion/go-imap-quota v0.0.0-20210203125329-619074823f3c h1:khcEdu1yFiZjBgi7gGnQiLhpSgghJ0YTnKD0l4EUqqc=
+github.com/emersion/go-imap-quota v0.0.0-20210203125329-619074823f3c/go.mod h1:iApyhIQBiU4XFyr+3kdJyyGqle82TbQyuP2o+OZHrV0=
github.com/emersion/go-imap-uidplus v0.0.0-20200503180755-e75854c361e9 h1:2Kbw3iu7fFeSso6RWIArVNUj1VGG2PvjetnPUW7bnis=
github.com/emersion/go-imap-uidplus v0.0.0-20200503180755-e75854c361e9/go.mod h1:GfiSiw/du0221I3Cf4F0DqX3Bv5Xe580gIIATrQtnJg=
github.com/emersion/go-maildir v0.3.0 h1:TYCjECfYU05WR1zRuPbZ/cr/ShTfuXdBkvAEEi91uYA=
diff --git a/imap/capability.go b/imap/capability.go
new file mode 100644
index 000000000000..c3a0f1ea8ebe
--- /dev/null
+++ b/imap/capability.go
@@ -0,0 +1,40 @@
+package imap
+
+import (
+ "fmt"
+
+ "git.sr.ht/~rockorager/offmap/log"
+)
+
+func (s *Store) Capabilities() {
+ capsUsed := []string{
+ "UIDPLUS",
+ "CONDSTORE",
+ "LIST-STATUS",
+ "QUOTA",
+ }
+ client := s.getConn()
+ caps, err := client.Capability()
+ if err != nil {
+ log.Errorf("could not get capabilities: %w", err)
+ return
+ }
+ for _, cap := range capsUsed {
+ _, has := caps[cap]
+ switch has {
+ case true:
+ fmt.Printf("Capability found: %s\n", cap)
+ if cap == "QUOTA" {
+ quotas, err := client.quota.GetQuotaRoot("INBOX")
+ if err != nil {
+ fmt.Println(err)
+ }
+ for _, q := range quotas {
+ fmt.Println(q.Name, q.Resources)
+ }
+ }
+ case false:
+ fmt.Printf("Your server doesn't support '%s'\n", cap)
+ }
+ }
+}
diff --git a/imap/client.go b/imap/client.go
index c410993950d4..eb64bff8fe85 100644
--- a/imap/client.go
+++ b/imap/client.go
@@ -9,6 +9,7 @@ import (
liststatus "git.sr.ht/~rockorager/offmap/imap/list-status"
lstat "git.sr.ht/~rockorager/offmap/imap/list-status"
"git.sr.ht/~rockorager/offmap/log"
+ quota "github.com/emersion/go-imap-quota"
uidplus "github.com/emersion/go-imap-uidplus"
"github.com/emersion/go-imap/client"
"github.com/emersion/go-sasl"
@@ -89,6 +90,10 @@ func (s *Store) initClients() {
conn.lsc = liststatus.NewClient(c)
}
}
+ ok, _ = c.Support("QUOTA")
+ if ok {
+ conn.quota = quota.NewClient(c)
+ }
s.Lock()
s.clients[n] = conn
@@ -107,7 +112,9 @@ func (s *Store) initClients() {
type conn struct {
*client.Client
- lsc *lstat.Client
+ lsc *lstat.Client
+ quota *quota.Client
+
id int
busy int32
}
--
2.39.0