imap: extract imap config and configure handling
Extract the imap config and move the configure part out of the message handler. Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
This commit is contained in:
parent
a1b75a99bd
commit
4d75137b20
2 changed files with 123 additions and 97 deletions
99
worker/imap/configure.go
Normal file
99
worker/imap/configure.go
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
package imap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.sr.ht/~rjarry/aerc/worker/types"
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (w *IMAPWorker) handleConfigure(msg *types.Configure) error {
|
||||||
|
u, err := url.Parse(msg.Config.Source)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
w.config.scheme = u.Scheme
|
||||||
|
if strings.HasSuffix(w.config.scheme, "+insecure") {
|
||||||
|
w.config.scheme = strings.TrimSuffix(w.config.scheme, "+insecure")
|
||||||
|
w.config.insecure = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasSuffix(w.config.scheme, "+oauthbearer") {
|
||||||
|
w.config.scheme = strings.TrimSuffix(w.config.scheme, "+oauthbearer")
|
||||||
|
w.config.oauthBearer.Enabled = true
|
||||||
|
q := u.Query()
|
||||||
|
|
||||||
|
oauth2 := &oauth2.Config{}
|
||||||
|
if q.Get("token_endpoint") != "" {
|
||||||
|
oauth2.ClientID = q.Get("client_id")
|
||||||
|
oauth2.ClientSecret = q.Get("client_secret")
|
||||||
|
oauth2.Scopes = []string{q.Get("scope")}
|
||||||
|
oauth2.Endpoint.TokenURL = q.Get("token_endpoint")
|
||||||
|
}
|
||||||
|
w.config.oauthBearer.OAuth2 = oauth2
|
||||||
|
}
|
||||||
|
|
||||||
|
w.config.addr = u.Host
|
||||||
|
if !strings.ContainsRune(w.config.addr, ':') {
|
||||||
|
w.config.addr += ":" + w.config.scheme
|
||||||
|
}
|
||||||
|
|
||||||
|
w.config.user = u.User
|
||||||
|
w.config.folders = msg.Config.Folders
|
||||||
|
w.config.idle_timeout = 10 * time.Second
|
||||||
|
w.config.connection_timeout = 30 * time.Second
|
||||||
|
w.config.keepalive_period = 0 * time.Second
|
||||||
|
w.config.keepalive_probes = 3
|
||||||
|
w.config.keepalive_interval = 3
|
||||||
|
for key, value := range msg.Config.Params {
|
||||||
|
switch key {
|
||||||
|
case "idle-timeout":
|
||||||
|
val, err := time.ParseDuration(value)
|
||||||
|
if err != nil || val < 0 {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"invalid idle-timeout value %v: %v",
|
||||||
|
value, err)
|
||||||
|
}
|
||||||
|
w.config.idle_timeout = val
|
||||||
|
case "connection-timeout":
|
||||||
|
val, err := time.ParseDuration(value)
|
||||||
|
if err != nil || val < 0 {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"invalid connection-timeout value %v: %v",
|
||||||
|
value, err)
|
||||||
|
}
|
||||||
|
w.config.connection_timeout = val
|
||||||
|
case "keepalive-period":
|
||||||
|
val, err := time.ParseDuration(value)
|
||||||
|
if err != nil || val < 0 {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"invalid keepalive-period value %v: %v",
|
||||||
|
value, err)
|
||||||
|
}
|
||||||
|
w.config.keepalive_period = val
|
||||||
|
case "keepalive-probes":
|
||||||
|
val, err := strconv.Atoi(value)
|
||||||
|
if err != nil || val < 0 {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"invalid keepalive-probes value %v: %v",
|
||||||
|
value, err)
|
||||||
|
}
|
||||||
|
w.config.keepalive_probes = val
|
||||||
|
case "keepalive-interval":
|
||||||
|
val, err := time.ParseDuration(value)
|
||||||
|
if err != nil || val < 0 {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"invalid keepalive-interval value %v: %v",
|
||||||
|
value, err)
|
||||||
|
}
|
||||||
|
w.config.keepalive_interval = int(val.Seconds())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -6,15 +6,12 @@ import (
|
||||||
"math"
|
"math"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/emersion/go-imap"
|
"github.com/emersion/go-imap"
|
||||||
sortthread "github.com/emersion/go-imap-sortthread"
|
sortthread "github.com/emersion/go-imap-sortthread"
|
||||||
"github.com/emersion/go-imap/client"
|
"github.com/emersion/go-imap/client"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/oauth2"
|
|
||||||
|
|
||||||
"git.sr.ht/~rjarry/aerc/lib"
|
"git.sr.ht/~rjarry/aerc/lib"
|
||||||
"git.sr.ht/~rjarry/aerc/logging"
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
|
@ -28,7 +25,11 @@ func init() {
|
||||||
handlers.RegisterWorkerFactory("imaps", NewIMAPWorker)
|
handlers.RegisterWorkerFactory("imaps", NewIMAPWorker)
|
||||||
}
|
}
|
||||||
|
|
||||||
var errUnsupported = fmt.Errorf("unsupported command")
|
var (
|
||||||
|
errUnsupported = fmt.Errorf("unsupported command")
|
||||||
|
errNotConnected = fmt.Errorf("not connected")
|
||||||
|
errAlreadyConnected = fmt.Errorf("already connected")
|
||||||
|
)
|
||||||
|
|
||||||
type imapClient struct {
|
type imapClient struct {
|
||||||
*client.Client
|
*client.Client
|
||||||
|
@ -36,20 +37,23 @@ type imapClient struct {
|
||||||
sort *sortthread.SortClient
|
sort *sortthread.SortClient
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type imapConfig struct {
|
||||||
|
scheme string
|
||||||
|
insecure bool
|
||||||
|
addr string
|
||||||
|
user *url.Userinfo
|
||||||
|
folders []string
|
||||||
|
oauthBearer lib.OAuthBearer
|
||||||
|
idle_timeout time.Duration
|
||||||
|
// tcp connection parameters
|
||||||
|
connection_timeout time.Duration
|
||||||
|
keepalive_period time.Duration
|
||||||
|
keepalive_probes int
|
||||||
|
keepalive_interval int
|
||||||
|
}
|
||||||
|
|
||||||
type IMAPWorker struct {
|
type IMAPWorker struct {
|
||||||
config struct {
|
config imapConfig
|
||||||
scheme string
|
|
||||||
insecure bool
|
|
||||||
addr string
|
|
||||||
user *url.Userinfo
|
|
||||||
folders []string
|
|
||||||
oauthBearer lib.OAuthBearer
|
|
||||||
// tcp connection parameters
|
|
||||||
connection_timeout time.Duration
|
|
||||||
keepalive_period time.Duration
|
|
||||||
keepalive_probes int
|
|
||||||
keepalive_interval int
|
|
||||||
}
|
|
||||||
|
|
||||||
client *imapClient
|
client *imapClient
|
||||||
idleStop chan struct{}
|
idleStop chan struct{}
|
||||||
|
@ -103,91 +107,14 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
|
||||||
case *types.Unsupported:
|
case *types.Unsupported:
|
||||||
// No-op
|
// No-op
|
||||||
case *types.Configure:
|
case *types.Configure:
|
||||||
u, err := url.Parse(msg.Config.Source)
|
reterr = w.handleConfigure(msg)
|
||||||
if err != nil {
|
|
||||||
reterr = err
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
w.config.scheme = u.Scheme
|
|
||||||
if strings.HasSuffix(w.config.scheme, "+insecure") {
|
|
||||||
w.config.scheme = strings.TrimSuffix(w.config.scheme, "+insecure")
|
|
||||||
w.config.insecure = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.HasSuffix(w.config.scheme, "+oauthbearer") {
|
|
||||||
w.config.scheme = strings.TrimSuffix(w.config.scheme, "+oauthbearer")
|
|
||||||
w.config.oauthBearer.Enabled = true
|
|
||||||
q := u.Query()
|
|
||||||
|
|
||||||
oauth2 := &oauth2.Config{}
|
|
||||||
if q.Get("token_endpoint") != "" {
|
|
||||||
oauth2.ClientID = q.Get("client_id")
|
|
||||||
oauth2.ClientSecret = q.Get("client_secret")
|
|
||||||
oauth2.Scopes = []string{q.Get("scope")}
|
|
||||||
oauth2.Endpoint.TokenURL = q.Get("token_endpoint")
|
|
||||||
}
|
|
||||||
w.config.oauthBearer.OAuth2 = oauth2
|
|
||||||
}
|
|
||||||
|
|
||||||
w.config.addr = u.Host
|
|
||||||
if !strings.ContainsRune(w.config.addr, ':') {
|
|
||||||
w.config.addr += ":" + w.config.scheme
|
|
||||||
}
|
|
||||||
|
|
||||||
w.config.user = u.User
|
|
||||||
w.config.folders = msg.Config.Folders
|
|
||||||
w.config.connection_timeout = 30 * time.Second
|
|
||||||
w.config.keepalive_period = 0 * time.Second
|
|
||||||
w.config.keepalive_probes = 3
|
|
||||||
w.config.keepalive_interval = 3
|
|
||||||
for key, value := range msg.Config.Params {
|
|
||||||
switch key {
|
|
||||||
case "connection-timeout":
|
|
||||||
val, err := time.ParseDuration(value)
|
|
||||||
if err != nil || val < 0 {
|
|
||||||
reterr = fmt.Errorf(
|
|
||||||
"invalid connection-timeout value %v: %v",
|
|
||||||
value, err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
w.config.connection_timeout = val
|
|
||||||
case "keepalive-period":
|
|
||||||
val, err := time.ParseDuration(value)
|
|
||||||
if err != nil || val < 0 {
|
|
||||||
reterr = fmt.Errorf(
|
|
||||||
"invalid keepalive-period value %v: %v",
|
|
||||||
value, err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
w.config.keepalive_period = val
|
|
||||||
case "keepalive-probes":
|
|
||||||
val, err := strconv.Atoi(value)
|
|
||||||
if err != nil || val < 0 {
|
|
||||||
reterr = fmt.Errorf(
|
|
||||||
"invalid keepalive-probes value %v: %v",
|
|
||||||
value, err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
w.config.keepalive_probes = val
|
|
||||||
case "keepalive-interval":
|
|
||||||
val, err := time.ParseDuration(value)
|
|
||||||
if err != nil || val < 0 {
|
|
||||||
reterr = fmt.Errorf(
|
|
||||||
"invalid keepalive-interval value %v: %v",
|
|
||||||
value, err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
w.config.keepalive_interval = int(val.Seconds())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case *types.Connect:
|
case *types.Connect:
|
||||||
if w.client != nil && w.client.State() == imap.SelectedState {
|
if w.client != nil && w.client.State() == imap.SelectedState {
|
||||||
if !w.autoReconnect {
|
if !w.autoReconnect {
|
||||||
w.autoReconnect = true
|
w.autoReconnect = true
|
||||||
checkConn(0)
|
checkConn(0)
|
||||||
}
|
}
|
||||||
reterr = fmt.Errorf("Already connected")
|
reterr = errAlreadyConnected
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +160,7 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
|
||||||
w.autoReconnect = false
|
w.autoReconnect = false
|
||||||
w.stopConnectionObserver()
|
w.stopConnectionObserver()
|
||||||
if w.client == nil || w.client.State() != imap.SelectedState {
|
if w.client == nil || w.client.State() != imap.SelectedState {
|
||||||
reterr = fmt.Errorf("Not connected")
|
reterr = errNotConnected
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue