From 05ad96a30cb8ea17970c84ea7c72f8f3def5afa5 Mon Sep 17 00:00:00 2001 From: Koni Marti Date: Sat, 5 Feb 2022 00:07:16 +0100 Subject: [PATCH] imap: improve reconnect stability improves the robustness of the imap reconnect feature which was introduced in commit beae17a6da37 ("imap: auto-reconnects on connection error"). If a connection error is emitted, the message list is cleared and a corresponding error message is shown in the ui. Status bar is updated as well. Upon reconnect, the directories and the message list will be re-fetched (same behavior as the connect command). Reconnect can be enabled and disabled with the connect and the disconnect commands. Signed-off-by: Koni Marti --- widgets/account.go | 4 +++- worker/imap/worker.go | 26 +++++++++++++++++++------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/widgets/account.go b/widgets/account.go index f970030..8dbaba3 100644 --- a/widgets/account.go +++ b/widgets/account.go @@ -289,8 +289,10 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) { case *types.LabelList: acct.labels = msg.Labels case *types.ConnError: - acct.logger.Printf("Connection error = %v", msg.Error) + acct.logger.Printf("connection error: %v", msg.Error) + acct.host.SetStatus("Disconnected.") acct.aerc.PushError(fmt.Sprintf("%v", msg.Error)) + acct.msglist.SetStore(nil) acct.worker.PostAction(&types.Reconnect{}, nil) case *types.Error: acct.logger.Printf("%v", msg.Error) diff --git a/worker/imap/worker.go b/worker/imap/worker.go index ba53df2..a1d55b9 100644 --- a/worker/imap/worker.go +++ b/worker/imap/worker.go @@ -85,6 +85,11 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error { } }() + checkConn := func() { + w.stopConnectionObserver() + w.startConnectionObserver() + } + var reterr error // will be returned at the end, needed to support idle switch msg := msg.(type) { @@ -171,9 +176,15 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error { } case *types.Connect: if w.client != nil && w.client.State() == imap.SelectedState { + if !w.autoReconnect { + w.autoReconnect = true + checkConn() + } reterr = fmt.Errorf("Already connected") break } + + w.autoReconnect = true c, err := w.connect() if err != nil { reterr = err @@ -187,7 +198,6 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error { w.startConnectionObserver() - w.autoReconnect = true w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil) case *types.Reconnect: if !w.autoReconnect { @@ -196,6 +206,7 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error { } c, err := w.connect() if err != nil { + checkConn() reterr = err break } @@ -209,18 +220,17 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error { w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil) case *types.Disconnect: + w.autoReconnect = false + w.stopConnectionObserver() if w.client == nil || w.client.State() != imap.SelectedState { reterr = fmt.Errorf("Not connected") break } - w.stopConnectionObserver() - if err := w.client.Logout(); err != nil { reterr = err break } - w.autoReconnect = false w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil) case *types.ListDirectories: w.handleListDirectories(msg) @@ -306,9 +316,11 @@ func (w *IMAPWorker) startConnectionObserver() { go func() { select { case <-w.client.LoggedOut(): - w.worker.PostMessage(&types.ConnError{ - Error: fmt.Errorf("Logged Out"), - }, nil) + if w.autoReconnect { + w.worker.PostMessage(&types.ConnError{ + Error: fmt.Errorf("imap: logged out"), + }, nil) + } case <-w.done: return }