aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/imap/client.go128
-rw-r--r--internal/imap/imap.go134
2 files changed, 137 insertions, 125 deletions
diff --git a/internal/imap/client.go b/internal/imap/client.go
new file mode 100644
index 0000000..7440ed7
--- /dev/null
+++ b/internal/imap/client.go
@@ -0,0 +1,128 @@
+package imap
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/emersion/go-imap"
+ imapClient "github.com/emersion/go-imap/client"
+
+ "github.com/Necoro/feed2imap-go/internal/log"
+)
+
+type Client struct {
+ c *imapClient.Client
+ host string
+ folders folders
+ delimiter string
+ toplevel string
+}
+
+type folders map[string]*imap.MailboxInfo
+
+func (f folders) contains(elem string) bool {
+ _, ok := f[elem]
+ return ok
+}
+
+func (f folders) add(elem *imap.MailboxInfo) {
+ name := elem.Name
+ f[name] = elem
+}
+
+func (client *Client) Disconnect() {
+ if client != nil {
+ connected := (client.c.State() & imap.ConnectedState) != 0
+ _ = client.c.Logout()
+
+ if connected {
+ log.Print("Disconnected from ", client.host)
+ }
+ }
+}
+
+func (client *Client) FolderName(path []string) string {
+ return strings.Join(path, client.delimiter)
+}
+
+func (client *Client) createFolder(folder string) error {
+ err := client.c.Create(folder)
+ if err != nil {
+ return fmt.Errorf("creating folder '%s': %w", folder, err)
+ }
+
+ err = client.c.Subscribe(folder)
+ if err != nil {
+ return fmt.Errorf("subscribing to folder '%s': %w", folder, err)
+ }
+
+ log.Printf("Created folder '%s'", folder)
+
+ return nil
+}
+
+func (client *Client) list(folder string) (*imap.MailboxInfo, int, error) {
+ mailboxes := make(chan *imap.MailboxInfo, 10)
+ done := make(chan error, 1)
+ go func() {
+ done <- client.c.List("", folder, mailboxes)
+ }()
+
+ found := 0
+ var mbox *imap.MailboxInfo
+ for m := range mailboxes {
+ if found == 0 {
+ mbox = m
+ }
+ found++
+ }
+
+ if err := <-done; err != nil {
+ return nil, 0, fmt.Errorf("while listing '%s': %w", folder, err)
+ }
+
+ return mbox, found, nil
+}
+
+func (client *Client) selectToplevel() (err error) {
+ err = client.EnsureFolder(client.toplevel)
+
+ if err == nil {
+ _, err = client.c.Select(client.toplevel, false)
+ }
+
+ return
+}
+
+func (client *Client) fetchDelimiter() error {
+ mbox, _, err := client.list("")
+ if err != nil {
+ return err
+ }
+
+ client.delimiter = mbox.Delimiter
+ return nil
+}
+
+func (client *Client) EnsureFolder(folder string) error {
+
+ if client.folders.contains(folder) {
+ return nil
+ }
+
+ log.Printf("Checking for folder '%s'", folder)
+
+ mbox, found, err := client.list(folder)
+
+ switch {
+ case err != nil:
+ return err
+ case found == 0:
+ return client.createFolder(folder)
+ case found == 1:
+ client.folders.add(mbox)
+ return nil
+ default:
+ return fmt.Errorf("Found multiple folders matching '%s'.", folder)
+ }
+}
diff --git a/internal/imap/imap.go b/internal/imap/imap.go
index 88cded3..ac24b9d 100644
--- a/internal/imap/imap.go
+++ b/internal/imap/imap.go
@@ -5,51 +5,32 @@ import (
"net/url"
"strings"
- "github.com/emersion/go-imap"
imapClient "github.com/emersion/go-imap/client"
"github.com/Necoro/feed2imap-go/internal/log"
)
const (
- imapsPort = "993"
- imapPort = "143"
+ imapsPort = "993"
+ imapPort = "143"
+ imapsSchema = "imaps"
+ imapSchema = "imap"
)
-type folders map[string]*imap.MailboxInfo
-
-func (f folders) contains(elem string) bool {
- _, ok := f[elem]
- return ok
-}
-
-func (f folders) add(elem *imap.MailboxInfo) {
- name := elem.Name
- f[name] = elem
-}
-
-type Client struct {
- c *imapClient.Client
- host string
- folders folders
- delimiter string
- toplevel string
-}
-
func forceTLS(url *url.URL) bool {
- return url.Scheme == "imaps" || url.Port() == imapsPort
+ return url.Scheme == imapsSchema || url.Port() == imapsPort
}
func setDefaultScheme(url *url.URL) {
switch url.Scheme {
- case "imap", "imaps":
+ case imapSchema, imapsSchema:
return
default:
oldScheme := url.Scheme
if url.Port() == imapsPort {
- url.Scheme = "imaps"
+ url.Scheme = imapsSchema
} else {
- url.Scheme = "imap"
+ url.Scheme = imapSchema
}
if oldScheme != "" {
@@ -61,7 +42,7 @@ func setDefaultScheme(url *url.URL) {
func setDefaultPort(url *url.URL) {
if url.Port() == "" {
var port string
- if url.Scheme == "imaps" {
+ if url.Scheme == imapsSchema {
port = imapsPort
} else {
port = imapPort
@@ -75,103 +56,6 @@ func sanitizeUrl(url *url.URL) {
setDefaultPort(url)
}
-func (client *Client) Disconnect() {
- if client != nil {
- connected := (client.c.State() & imap.ConnectedState) != 0
- _ = client.c.Logout()
-
- if connected {
- log.Print("Disconnected from ", client.host)
- }
- }
-}
-
-func (client *Client) FolderName(path []string) string {
- return strings.Join(path, client.delimiter)
-}
-
-func (client *Client) createFolder(folder string) error {
- err := client.c.Create(folder)
- if err != nil {
- return fmt.Errorf("creating folder '%s': %w", folder, err)
- }
-
- err = client.c.Subscribe(folder)
- if err != nil {
- return fmt.Errorf("subscribing to folder '%s': %w", folder, err)
- }
-
- log.Printf("Created folder '%s'", folder)
-
- return nil
-}
-
-func (client *Client) list(folder string) (*imap.MailboxInfo, int, error) {
- mailboxes := make(chan *imap.MailboxInfo, 10)
- done := make(chan error, 1)
- go func() {
- done <- client.c.List("", folder, mailboxes)
- }()
-
- found := 0
- var mbox *imap.MailboxInfo
- for m := range mailboxes {
- if found == 0 {
- mbox = m
- }
- found++
- }
-
- if err := <-done; err != nil {
- return nil, 0, fmt.Errorf("while listing '%s': %w", folder, err)
- }
-
- return mbox, found, nil
-}
-
-func (client *Client) selectToplevel() (err error) {
- err = client.EnsureFolder(client.toplevel)
-
- if err == nil {
- _, err = client.c.Select(client.toplevel, false)
- }
-
- return
-}
-
-func (client *Client) fetchDelimiter() error {
- mbox, _, err := client.list("")
- if err != nil {
- return err
- }
-
- client.delimiter = mbox.Delimiter
- return nil
-}
-
-func (client *Client) EnsureFolder(folder string) error {
-
- if client.folders.contains(folder) {
- return nil
- }
-
- log.Printf("Checking for folder '%s'", folder)
-
- mbox, found, err := client.list(folder)
-
- switch {
- case err != nil:
- return err
- case found == 0:
- return client.createFolder(folder)
- case found == 1:
- client.folders.add(mbox)
- return nil
- default:
- return fmt.Errorf("Found multiple folders matching '%s'.", folder)
- }
-}
-
func Connect(url *url.URL) (*Client, error) {
var c *imapClient.Client
var err error