aboutsummaryrefslogtreecommitdiff
path: root/internal/imap/imap.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/imap/imap.go')
-rw-r--r--internal/imap/imap.go126
1 files changed, 126 insertions, 0 deletions
diff --git a/internal/imap/imap.go b/internal/imap/imap.go
new file mode 100644
index 0000000..18039d3
--- /dev/null
+++ b/internal/imap/imap.go
@@ -0,0 +1,126 @@
+package imap
+
+import (
+ "fmt"
+ "net/url"
+
+ "github.com/emersion/go-imap"
+ imapClient "github.com/emersion/go-imap/client"
+
+ "github.com/Necoro/feed2imap-go/internal/log"
+)
+
+const (
+ imapsPort = "993"
+ imapPort = "143"
+)
+
+type Client struct {
+ c *imapClient.Client
+ host string
+}
+
+func forceTLS(url *url.URL) bool {
+ return url.Scheme == "imaps" || url.Port() == imapsPort
+}
+
+func setDefaultScheme(url *url.URL) {
+ switch url.Scheme {
+ case "imap", "imaps":
+ return
+ default:
+ oldScheme := url.Scheme
+ if url.Port() == imapsPort {
+ url.Scheme = "imaps"
+ } else {
+ url.Scheme = "imap"
+ }
+
+ if oldScheme != "" {
+ log.Warnf("Unknown scheme '%s', defaulting to '%s'", oldScheme, url.Scheme)
+ }
+ }
+}
+
+func setDefaultPort(url *url.URL) {
+ if url.Port() == "" {
+ var port string
+ if url.Scheme == "imaps" {
+ port = imapsPort
+ } else {
+ port = imapPort
+ }
+ url.Host += ":" + port
+ }
+}
+
+func sanitizeUrl(url *url.URL) {
+ setDefaultScheme(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 Connect(url *url.URL) (*Client, error) {
+ var c *imapClient.Client
+ var err error
+
+ sanitizeUrl(url)
+
+ forceTls := forceTLS(url)
+
+ if forceTls {
+ c, err = imapClient.DialTLS(url.Host, nil)
+ if err != nil {
+ return nil, fmt.Errorf("connecting (TLS) to %s: %w", url.Host, err)
+ }
+ log.Print("Connected to ", url.Host, " (TLS)")
+ } else {
+ c, err = imapClient.Dial(url.Host)
+ if err != nil {
+ return nil, fmt.Errorf("connecting to %s: %w", url.Host, err)
+ }
+ }
+
+ var client = Client{c, url.Host}
+
+ defer func() {
+ if err != nil {
+ client.Disconnect()
+ }
+ }()
+
+ if !forceTls {
+ var hasStartTls bool // explicit to avoid shadowing err
+
+ hasStartTls, err = c.SupportStartTLS()
+ if err != nil {
+ return nil, fmt.Errorf("checking for starttls for %s: %w", url.Host, err)
+ }
+
+ if hasStartTls {
+ if err = c.StartTLS(nil); err != nil {
+ return nil, fmt.Errorf("enabling starttls for %s: %w", url.Host, err)
+ }
+
+ log.Print("Connected to ", url.Host, " (STARTTLS)")
+ }
+ log.Print("Connected to ", url.Host, " (Plain)")
+ }
+
+ pwd, _ := url.User.Password()
+ if err = c.Login(url.User.Username(), pwd); err != nil {
+ return nil, fmt.Errorf("login to %s: %w", url.Host, err)
+ }
+
+ return &client, nil
+}
de9a76fac10f99721f0&follow=1'>showed masked packages unmasked by the user similar to stable marked testing ...necoro5-13/+40 2007-03-31changed changelognecoro1-1/+2 2007-03-31Some small changes for etcproposals 1.1necoro1-2/+2 2007-03-31Some small changes for etcproposals 1.1necoro2-3/+3 2007-03-31Some small changes for etcproposals 1.1necoro1-6/+13 2007-03-31Allowed Plugins to have a menunecoro7-201/+315 2007-03-15Added etc-proposals pluginnecoro7-28/+121 2007-03-10Added USE_EXPAND-supportnecoro5-11/+63 2007-03-10Added plugin-data to about-dialognecoro3-197/+264