aboutsummaryrefslogtreecommitdiffstats
path: root/worker/imap
Commit message (Collapse)AuthorAgeFilesLines
* imap: fix data race on seqMap arrayRobin Jarry2022-06-246-28/+146
| | | | | | | | | | | | | | | | | | | | | | | | | | | There are concurrent threads that are accessing and modifying IMAPWorker.seqMap (the mapping of sequence numbers to message UIDs). This can lead to crashes when trying to add and remove a message ID. panic: runtime error: index out of range [391] with length 390 goroutine 1834 [running]: git.sr.ht/~rjarry/aerc/logging.PanicHandler() logging/panic-logger.go:47 +0x6de panic({0xa41760, 0xc0019b3290}) /usr/lib/golang/src/runtime/panic.go:838 +0x207 git.sr.ht/~rjarry/aerc/worker/imap.(*IMAPWorker).handleFetchMessages.func1() worker/imap/fetch.go:214 +0x185 created by git.sr.ht/~rjarry/aerc/worker/imap.(*IMAPWorker).handleFetchMessages worker/imap/fetch.go:209 +0x12b Use a map which makes more sense than a simple array for random access operations. Also, it allows better typing for the key values. Protect the map with a mutex. Add internal API to access the map. Add basic unit tests to ensure that concurrent access works. Fixes: https://todo.sr.ht/~rjarry/aerc/49 Signed-off-by: Robin Jarry <robin@jarry.cc> Acked-by: Moritz Poldrack <moritz@poldrack.dev>
* imap: add option to cache headersTim Culverhouse2022-06-225-12/+243
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add option to cache headers for imap accounts. Cache db is located at $XDG_CACHE_DIR/aerc/{account name}. The cache is cleaned of stale entries when aerc is first opened. Two new account level configuration options are introduced: * cache-headers (Default: false) * cache-max-age (Default: 30 days (720 hours)) The change in worker/imap/open.go is to set the selected directory. This is required to access the UIDVALIDITY field, which is used in combination with the message ID to form the key for use in the cache db. The key structure is: "header.{UIDVALIDITY}.{UID}" Where reasonable, cache does not stop aerc from running. In general, if there is an error in the cache, aerc should continue working as usual. Errors are either displayed to the user or logged. All messages are stored without flags, and when retrieved have the flags set to SEEN. This is to prevent UI flashes. A new method to FetchMessageFlags is introduced to update flags of cached headers. This is done asynchronously, and the user will see their messages appear and then any flags updated. The message will initially show as SEEN, but will update to unread. I considered updating the cache with the last-known flag state, however it seems prudent to spare the R/W cycle and assume that - eventually - all messages will end up read, and if it isn't the update will occur rather quickly. Note that leveldb puts a lock on the database, preventing multiple instances of aerc from accessing the cache at the same time. Much of this work is based on previous efforts by Vladimír Magyar. Implements: https://todo.sr.ht/~rjarry/aerc/2 Thanks: Vladimír Magyar <vladimir@mgyar.me> Signed-off-by: Tim Culverhouse <tim@timculverhouse.com> Tested-by: inwit <inwit@sindominio.net> Reviewed-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* dirlist: update RUE counts for imap/maildir on move|copy|delete|archiveTim Culverhouse2022-06-071-0/+5
| | | | | | | | | | | | | | | | | | | When moving/copying/deleting/archiving a message in imap, the RUE counts displayed in the dirlist would not update properly. Maildir has (had) an implementation that recounts the entire directory and updates the DirectoryInfo after one of these actions. This patch implements a more efficient method of updating, and also enables it to apply to IMAP without any additional requests. Upon completion of the action, the counts are manually updated with the count of messages in the action and recent and/or unseen states of those messages. This is more efficient for maildir, because we aren't counting everything in the store. For IMAP, we get the updates for free because we are only performing the update after confirmation from the server that the action has happened. Signed-off-by: Tim Culverhouse <tim@timculverhouse.com> Acked-by: Robin Jarry <robin@jarry.cc>
* feat: add background mail polling option for all workersTim Culverhouse2022-05-312-0/+42
| | | | | | | | | | | | | | | | | | | | | | | | | | | Check for new mail (recent, unseen, exists counts) with an external command, or for imap with the STATUS command, at start or on reconnection and every X time duration IMAP: The selected folder is skipped, per specification. Additional config options are included for including/excluding folders explicitly. Maildir/Notmuch: An external command will be run in the background to check for new mail. An optional timeout can be used with maildir/notmuch. Default is 10s New account options: check-mail check-mail-cmd (maildir/notmuch only) check-mail-timeout (maildir/notmuch only), default 10s check-mail-include (IMAP only) check-mail-exclude (IMAP only) If unset, or set less than or equal to 0, check-mail will be ignored Signed-off-by: Tim Culverhouse <tim@timculverhouse.com> Tested-by: Moritz Poldrack <moritz@poldrack.dev> Acked-by: Robin Jarry <robin@jarry.cc>
* imap: add timeout to tcp connect functionsKoni Marti2022-05-042-120/+188
| | | | | | | | | Extract the tcp connection details and timeout the tcp connect functions (net.ResolveTCPAddr and net.DialTCP). If timed out, ensure that the connection is properly closed. Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* imap: add debouncer to the idlerKoni Marti2022-05-043-11/+35
| | | | | | | | | | | | | Add a debouncer to the idle mode. Avoid unnecessary idling when another job arrives within a certain time frame. For example, the ui sends three messages to the worker at the same time when we open a message (FlagMessage, FetchMessageBodyPart, and the FetchMessageHeaders). The debouncer prevents the unnecessary entering and leaving of the idle mode between those messages. Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* imap: monitor the logout channel with an observerKoni Marti2022-05-043-86/+186
| | | | | | | | | Untangle the observer functionality from the message handling routine. Observe the imap client's logout channel and trigger a connection error when necessary to start the reconnect cycle. Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* imap: manage idle mode with an idlerKoni Marti2022-05-043-24/+181
| | | | | | | | | Untangle the idle functionality from the message handling routine. Wait for the idle mode to properly exit every time to ensure a consistent imap state. Timeout when hanging in idle mode and inform the ui. Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* imap: extract imap config and configure handlingKoni Marti2022-05-042-97/+123
| | | | | | | | 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>
* imap: fix out-of-range panic for imap updatesKoni Marti2022-04-291-0/+14
| | | | | | | | | | Check slice bounds before using it for the message and expunge updates. Log the error but ignore the affected updates. Link: https://lists.sr.ht/~rjarry/aerc-devel/%3CCJEHBFFUI11T.1AYGOMVGZ87ZS%40rek2system%3E Reported-by: ReK2 <rek2@hispagatos.org> Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* imap: avoid crash when replying to unread messageRobin Jarry2022-04-281-2/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When running `:reply -q` on an unread message, aerc crashes after opening the editor: panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x5d1019] goroutine 63 [running]: bufio.(*Reader).fill(0xc000086ef8) /usr/lib/golang/src/bufio/bufio.go:106 +0xd9 bufio.(*Reader).Peek(0xc00020bef8, 0x1) /usr/lib/golang/src/bufio/bufio.go:144 +0x5d github.com/emersion/go-message/textproto.ReadHeader(0xc00004a700?) emersion/go-message@v0.15.0/textproto/header.go:525 +0x5f git.sr.ht/~rjarry/aerc/worker/imap.(*IMAPWorker).handleFetchMessageBodyPart.func1(0xc00056e280) worker/imap/fetch.go:99 +0x1ab git.sr.ht/~rjarry/aerc/worker/imap.(*IMAPWorker).handleFetchMessages.func1() worker/imap/fetch.go:178 +0xd7 created by git.sr.ht/~rjarry/aerc/worker/imap.(*IMAPWorker).handleFetchMessages worker/imap/fetch.go:172 +0x12b This happens because the flags are updated in the callback that receives the message itself. It causes the flag update to arrive in the same channel/request. Ignore the messages that have an empty body (i.e. only containing flag updates). This is inherently racy but there seems no way to get rid of these extra messages. Signed-off-by: Robin Jarry <robin@jarry.cc> Tested-by: Connor Kuehl <cipkuehl@gmail.com>
* logging: added a log on panicMoritz Poldrack2022-03-234-0/+12
| | | | | | | | | | | | | Since panics still regularly "destroy" the terminal, it is hard to get a stack trace for panics you do not anticipate. This commit adds a panic handler that automatically creates a logfile inside the current working directory. It has to be added to every goroutine that is started and will repair the terminal on a panic. Signed-off-by: Moritz Poldrack <git@moritz.sh> Acked-by: Robin Jarry <robin@jarry.cc>
* go vet: composite literal uses unkeyed fieldsMoritz Poldrack2022-03-188-19/+19
| | | | | | | | This commit fixes all occurrences of the abovementioned lint-error in the codebase. Signed-off-by: Moritz Poldrack <git@moritz.sh> Acked-by: Robin Jarry <robin@jarry.cc>
* imap: start reconnect when initial connect failsKoni Marti2022-02-201-3/+11
| | | | | | | Start the reconnect cycle when the initial connect fails. Make the connection observer send a connection error when the imap client is nil. Signed-off-by: Koni Marti <koni.marti@gmail.com>
* imap: reconnect with exponential backoffKoni Marti2022-02-191-4/+28
| | | | | | | | | | | | | waits an increasing amount of time before attempting a reconnect. Wait is capped at 16s. Prevents many reconnect attemps in a short time period. Fixes commit 05ad96a30cb8 ("imap: improve reconnect stability") that improved the reliability of the reconnect mechanism but did not implement controls to prevent the triggering of too many reconnects within a short period of time. Fixes: 05ad96a30cb8 ("imap: improve reconnect stability") Signed-off-by: Koni Marti <koni.marti@gmail.com>
* imap: improve reconnect stabilityKoni Marti2022-02-061-7/+19
| | | | | | | | | | | | | | | | 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 <koni.marti@gmail.com>
* imap: do not abort on malformed messagesRobin Jarry2022-02-061-1/+7
| | | | | | | | | | | | | | Some messages contain invalid headers, textproto.ReadHeader fails with an error: malformed MIME header key: From nobody Fri Jan 14 19 And all other messages of the selected folder are ignored. Return an explicit error message to the UI and continue processing other messages. This is consistent with what the maildir worker does. Signed-off-by: Robin Jarry <robin@jarry.cc>
* imap: auto-reconnects on connection errorKoni Marti2022-01-191-2/+24
| | | | | | | | | if the worker emits a connection error, the ui will automatically send back a reconnect command. The worker then establishes a new connection. Auto-reconnect is disabled when the user sends the disconnect command. Fixes: https://todo.sr.ht/~rjarry/aerc/1 Signed-off-by: Koni Marti <koni.marti@gmail.com>
* imap: emits connection error on logoutKoni Marti2022-01-191-0/+29
| | | | | | | | implements a new connection error message. This allows the worker to emit a connection-related error message to the ui when the imap client closes the loggedOut channel. Signed-off-by: Koni Marti <koni.marti@gmail.com>
* imap: fix panic when sending multiple connect cmdsKoni Marti2022-01-191-15/+26
| | | | | | | | | | | fixes the panic when the user sends multiple connect commands and is already connected. The panic is caused by closing an already closed channel. This happens when the idle re-init code is not executed, e.g. when there's a return statement in the switch block. A defer func() before the switch block will prevent this. The existing behavior of only creating a new idleStop channel when properly connected is preseverd. Signed-off-by: Koni Marti <koni.marti@gmail.com>
* Revert "imap: attempt automatic reconnection on error"Robin Jarry2022-01-151-41/+3
| | | | | | | | | This reverts commit c605ada3ddc7569ebfc153b07db12a21b30d0569. This breaks reading message bodies. I am not sure why, I'll take some time to fix it later. Signed-off-by: Robin Jarry <robin@jarry.cc>
* imap: attempt automatic reconnection on errorRobin Jarry2022-01-141-3/+41
| | | | | | | | | | | | | Attempt to reconnect to the server when there is an unexpected disconnection or network error. Use the Client.LoggedOut() channel which is closed when the connection is closed. This patch is rather flaky and is certainly bugged. However, it is a start. Signed-off-by: Robin Jarry <robin@jarry.cc>
* imap: fix build on macosRobin Jarry2021-12-111-7/+2
| | | | | | | | | | | | Fix the following build error on mac os: worker/imap/worker.go:368:29: undefined: syscall.TCP_KEEPCNT worker/imap/worker.go:376:29: undefined: syscall.TCP_KEEPINTVL These symbols are not defined on darwin. Fixes: 5dfeff75f368 ("imap: add tcp connection options") Signed-off-by: Robin Jarry <robin@jarry.cc>
* imap: add tcp connection optionsRobin Jarry2021-12-071-0/+102
| | | | | | Allow fine tuning tcp connection options. Signed-off-by: Robin Jarry <robin@jarry.cc>
* imap: use low level tcp connectionRobin Jarry2021-12-071-6/+22
| | | | | | | | | | In preparation for tcp keepalive options, we need access to the net.TCPConn object associated with an IMAP connection. The only way to do this is to create the connection ourselves. No functional change. Signed-off-by: Robin Jarry <robin@jarry.cc>
* imap: move connect procedure into a dedicated functionRobin Jarry2021-12-071-45/+55
| | | | | | | This will prepare for extra tcp connection options support and for automatic reconnect. No functional change. Signed-off-by: Robin Jarry <robin@jarry.cc>
* imap: fix segfault when disconnectingRobin Jarry2021-11-221-3/+2
| | | | | | | | | | | | | | | | | | | | | | Do not set client = nil, it breaks almost all message handlers: panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x8c7e51] goroutine 25 [running]: git.sr.ht/~rjarry/aerc/worker/imap.(*IMAPWorker).handleListDirectories worker/imap/list.go:32 git.sr.ht/~rjarry/aerc/worker/imap.(*IMAPWorker).handleMessage worker/imap/worker.go:174 git.sr.ht/~rjarry/aerc/worker/imap.(*IMAPWorker).Run worker/imap/worker.go:264 created by git.sr.ht/~rjarry/aerc/widgets.NewAccountView widgets/account.go:85 +0x518 Simply leave the disconnected client object, it already returns explicit error messages. Fixes: e41ed82cf3db ("imap: add manual {dis,}connect support") Signed-off-by: Robin Jarry <robin@jarry.cc>
* messages: allow displaying email threadsy0ast2021-11-132-2/+68
| | | | | | | | | | | | | Display threads in the message list. For now, only supported by the notmuch backend and on IMAP when the server supports the THREAD extension. Setting threading-enable=true is global and will cause the message list to be empty with maildir:// accounts. Co-authored-by: Kevin Kuehler <keur@xcf.berkeley.edu> Co-authored-by: Reto Brunner <reto@labrat.space> Signed-off-by: Robin Jarry <robin@jarry.cc>
* imap: add manual {dis,}connect supportRobin Jarry2021-11-051-2/+14
| | | | Signed-off-by: Robin Jarry <robin@jarry.cc>
* go.mod: change base git urlRobin Jarry2021-11-059-14/+14
| | | | | | | I'm not sure what are the implications but it seems required. Link: https://github.com/golang/go/issues/20883 Signed-off-by: Robin Jarry <robin@jarry.cc>
* imap: use builtin idle supportRobin Jarry2021-11-022-7/+2
| | | | | | | go-imap supports IDLE since 1.2.0. Remove dependency to go-imap-idle. Link: https://github.com/emersion/go-imap/commit/ac3f8e195ef1b6d Signed-off-by: Robin Jarry <robin@jarry.cc>
* imap: strip <> from message-idsReto Brunner2020-11-141-1/+9
|
* remove models.Address in favor of go-message AddressReto Brunner2020-11-141-3/+4
| | | | | | | We made a new type out of go-message/mail.Address without any real reason. This suddenly made it necessary to convert from one to the other without actually having any benefit whatsoever. This commit gets rid of the additional type
* imap: add sort supportReto Brunner2020-10-112-3/+50
|
* base models.Address on the mail.Address typeReto Brunner2020-08-201-2/+1
| | | | | | | | | | | | This allows us to hook into the std libs implementation of parsing related stuff. For this, we need to get rid of the distinction between a mailbox and a host to just a single "address" field. However this is already the common case. All but one users immediately concatenated the mbox/domain to a single address. So this in effects makes it simpler for most cases and we simply do the transformation in the special case.
* Add support for :rmdirARaspiK2020-08-192-0/+21
| | | | | | | | | | | | | | | | | | | | | The `:rmdir` command removes the current directory (`-f` is required if the directory is not empty). This is not supported on the notmuch backend. An issue with the maildir backend is that some sync programs (e.g. offlineimap) may recover the directory after it is deleted. They need to specifically be configured to accept deletions, or special commands need to be executed (e.g. `offlineimap --delete-folder`) to properly delete folders. A danger of using this on the IMAP backend is that it is possible for a new message to be added to the directory and for aerc to not show it immediately (due to a slow connection) - using `:rmdir` at this moment (with `-f` if the directory already contains messages) would delete the directory and the new message that just arrived (and all other contents). This is documented in aerc(1) so that users are aware of possible risks.
* Add flag based search optionsTobias Wölfel2020-07-251-1/+24
| | | | | | | Provide search and filter with the option to specify more flag based conditions. Use '-x <flag>' to search for messages with a flag (seen, answered, flagged) and '-X <flag>' to search for messages without a flag.
* Add additional flagging functionalityARaspiK2020-07-082-7/+6
| | | | | | | | | | | | | | More mail flags can now be set, unset, and toggled, not just the read/seen flag. This functionality is implemented with a new `:flag` and `:unflag` command, which are extensions to the matching `:read` and `:unread` commands, adding support for different flags. In fact, the `read`/`unread` commands are now recognized aliases to `flag`/`unflag`. The new commands are also well documented in aerc(1). The change mostly extends the previous read/unread setting functionality by adding a selection for the flag to change.
* Set AnsweredFlag on successful replySrivathsan Murali2020-05-252-0/+34
|
* imap: Remove FetchMessageBodyPart.{Encoding,Charset}Reto Brunner2020-05-161-106/+107
| | | | Fixes https://todo.sr.ht/~sircmpwn/aerc2/352 exactly as suggested by emersion.
* imap/fetch.go: report error when fetching headers failsBen Fiedler2020-04-241-3/+4
| | | | | Correct me if I'm wrong, but shouldn't this raise an error when it fails?
* Ignore missing message part in getDecodedPartAmir Yalon2020-03-091-1/+1
| | | | The code that calls this function handles nil without issues.
* worker/imap: rely on go-imap for charset handlingSimon Ser2020-03-031-31/+13
| | | | | Set imap.CharsetReader so that go-imap can automatically decode all encoded fields.
* Mark sent messages as "seen" in maildirGalen Abell2020-03-034-8/+26
| | | | | | | - Add maildir flags to complement a messages imap flags - Set the "seen" flag on sent messages when using the maildir backend - Cleanup AppendMessage interface to use models.Flag for both IMAP and maildir
* remove the dirInfoUpdateRequest functionalityReto Brunner2020-02-291-2/+0
| | | | | The notmuch worker followed suit in handling the dirInfo submission manually. That removes the last user so we might as well remove the functionality.
* lib/msgstore: debounce directoryUpdateRequestsReto Brunner2020-02-251-0/+2
| | | | | | | | Apparently sending an event for every incoming messageInfo slows down the application significantly. Therefore this slows down the emmision rate, on the cost of being out of date in some cases.
* imap: fix double closing idleStopReto Brunner2020-02-161-2/+4
| | | | | | The idle restart code is at the end of handleMessage in the worker. However if an unsupported msg comes in, we returned early, skipping the re-init. That lead to a crash due to double closing idleStop in the next iteration.
* imap: emit messageinfo when changing read state.Reto Brunner2020-01-241-2/+17
| | | | We need to emit the changed msgInfo whenever we modify the state
* worker/imap: don't decode in FetchFullMessage.Reto Brunner2020-01-181-27/+2
| | | | | Doing that breaks `git am` as it expected the encoded variant. Same is probably true for any sort of signature validation (gpg / dkim)
* imap: decode reader prior to returning themReto Brunner2020-01-051-10/+90
|