510 Commits

Author SHA1 Message Date
Robin Jarry
3273f8071d commands: add settle
Signed-off-by: Robin Jarry <robin@jarry.cc>
2025-09-09 09:18:59 +02:00
Robin Jarry
06a5ead1fc worker: uint64 message ids
Signed-off-by: Robin Jarry <robin@jarry.cc>
2025-09-09 09:18:58 +02:00
Robin Jarry
767287718e workers: rework cancellable
Signed-off-by: Robin Jarry <robin@jarry.cc>
2025-09-09 09:18:18 +02:00
Robin Jarry
1ec34824d3 worker: fix potential race in post action
Signed-off-by: Robin Jarry <robin@jarry.cc>
2025-09-09 09:17:18 +02:00
Robin Jarry
14eef02ecc worker: remove post message callback argument
Signed-off-by: Robin Jarry <robin@jarry.cc>
2025-09-09 09:17:16 +02:00
Robin Jarry
0211c9bf23 reload: fix crash when reloading via IPC
When reloading the configuration with :reload, global variables in the
config package are reset to their startup values and then, the config is
parsed from disk. While the parsing is done, these variables are
temporarily in an inconsistent and possibly invalid state.

When commands are executed interactively from aerc, they are handled by
the main goroutine which also deals with UI rendering. No UI render will
be done while :reload is in progress.

However, the IPC socket handler runs in an independent goroutine. This
has the unfortunate side effect to let the UI goroutine to run while
config parsing is in progress and causes crashes:

[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x6bb142]

goroutine 1 [running]:
git.sr.ht/~rjarry/aerc/lib/log.PanicHandler()
	lib/log/panic-logger.go:51 +0x6cf
panic({0xc1d960?, 0x134a6e0?})
	/usr/lib/go/src/runtime/panic.go:783 +0x132
git.sr.ht/~rjarry/aerc/config.(*StyleConf).getStyle(0xc00038b908?, 0x4206b7?)
	config/style.go:386 +0x42
git.sr.ht/~rjarry/aerc/config.StyleSet.Get({0x0, 0x0, 0x0, {0x0, 0x0, 0x0}}, 0x421a65?, 0x0)
	config/style.go:408 +0x8b
git.sr.ht/~rjarry/aerc/config.(*UIConfig).GetStyle(...)
	config/ui.go:379
git.sr.ht/~rjarry/aerc/lib/ui.(*TabStrip).Draw(0xc000314700, 0xc000192230)
	lib/ui/tab.go:378 +0x15b
git.sr.ht/~rjarry/aerc/lib/ui.(*Grid).Draw(0xc000186fc0, 0xc0002c25f0)
	lib/ui/grid.go:126 +0x28e
git.sr.ht/~rjarry/aerc/app.(*Aerc).Draw(0x14b9f00, 0xc0002c25f0)
	app/aerc.go:192 +0x1fe
git.sr.ht/~rjarry/aerc/lib/ui.Render()
	lib/ui/ui.go:155 +0x16b
main.main()
	main.go:310 +0x997

Make the reload operation safe by changing how config objects are
exposed and updated. Change all objects to be atomic pointers. Expose
public functions to access their value atomically. Only update their
value after a complete and successful config parse. This way the UI
thread will always have access to a valid configuration.

NB: The account configuration is not included in this change since it
cannot be reloaded.

Fixes: https://todo.sr.ht/~rjarry/aerc/319
Reported-by: Anachron <gith@cron.world>
Signed-off-by: Robin Jarry <robin@jarry.cc>
2025-09-08 12:19:51 +02:00
Simon Martin
d7b097f317 imap: always consider recently received unread messages as recent
We rely on IMAP's \Recent flag to trigger the new email hook, making it
unreliable since not all providers support that flag (it's been
deprecated in RFC 9051).

This patch implements the following heuristic to force the \Recent flag
on messages, regardless of what the server says, and "fixes" this
inconsistency across providers: a message is always considered having
the \Recent flag if:
 - The IMAP header cache is enabled, and
 - The message is not in the header cache, and
 - It's not marked as read, and
 - It's been received less than `check-mail` in the past

Signed-off-by: Simon Martin <simon@nasilyan.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-08-28 10:16:02 +02:00
Moritz Poldrack
fc5b6896ff chore: switch to using stdlib helper functions
Go has evolved significantly over the years and has introduced some
handy helper functions that make the code easier to read.

Use helper functions like slices.Contains, map.Copy, and
strings.CutPrefix, when appropriate.

Signed-off-by: Moritz Poldrack <git@moritz.sh>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-08-04 12:47:05 +02:00
Simon Martin
7df7d31e40 imap: consistently fetch gmail labels and improve logging
The various handleFetchXYZ functions do not consistently request
X-GM-LABELS when interacting with GMail, and the in-memory "label state"
can easily get out-of-sync with the server.

This patch fixes this, and also ensures that we only log that we're
attaching a label to a message when we actually do (and if so, puts the
account name in the log line).

Signed-off-by: Simon Martin <simon@nasilyan.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-08-04 12:27:30 +02:00
Simon Martin
96ed6a9505 imap: add support for :modify-labels / :tag for gmail and proton
As part of my effort to properly support labels in IMAP for providers
that have this notion, this patch takes care of the case of GMail and
Proton, and gracefully errors for all others.

To do so, it detects the actual provider we're connected to by analyzing
the target URL, and implements label addition / removal (toggling is not
supported right now [1]) according to the documentation:
 - For GMail, it leverages the IMAP STORE command.
 - For Proton, it leverages moving the message across (virtual) folders.

[1] There's nothing fundamental preventing supporting toggling, but
getting the current "label state" from there in the code is not trivial.
It could be done in a second step if there's demand).

Changelog-added: Support :modify-labels command for GMail and Proton.
Signed-off-by: Simon Martin <simon@nasilyan.com>
Tested-by: Jan Černohorský <jan@grsc.cz>
Reviewed-by: Moritz Poldrack <moritz@poldrack.dev>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-08-04 12:27:27 +02:00
Simon Martin
9a967f1795 imap: always use negotiated x-gm-ext-1 value
While it negotiates the X-GM-EXT-1 capability with GMail, aerc defaults
to not using it because the use-gmail-ext configuration knob defaults to
false.

This patch simply dismantles that knob, so that GMail users always
benefit from all its capabilities.

Changelog-added: Always use `X-GM-EXT-1` extension if negotiated
 with GMail.
Signed-off-by: Simon Martin <simon@nasilyan.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-06-25 16:46:15 +02:00
Jan Černohorský
0fc3481862 imap: add rudimentary readonly support for labels in gmail
Use the GMail IMAP extension to fetch labels for messages when
use-gmail-ext is enabled. Labels are automatically fetched when fetching
headers for a message and when fetching flags for a message. They should
be correctly cached.

Link: https://developers.google.com/workspace/gmail/imap/imap-extensions
Changelog-added: Readonly support for GMail labels.
Signed-off-by: Jan Černohorský <jan@grsc.cz>
Tested-by: Vojtěch Káně <vojta001@vkane.cz>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-06-20 09:30:44 +02:00
Simon Martin
c65a1db7c3 imap: workaround o365 bug upon new email
inwit reported on IRC that when receiving a new email (on his O365
account) in the currently selected folder, the unread counter is updated
as it should, but that the message list won't show the new mail until
navigating out of then back into the directory.

Traces that we captured together [1] show that O365 notifies aerc of the
update with a MailboxUpdate message, but does NOT report a different
UIDNEXT (I believe it's a bug; other providers do). It does however
report that the folder has more messages, and we can use this to force a
refetch (we'd have done so if they'd reported a different UIDNEXT).

[1] Lines 9-10 from https://paste.sr.ht/~inwit/8b7696456de831adc8e169e7f34b9f08c0a8971b

Reported-by: inwit <inwit@sindominio.net>
Signed-off-by: Simon Martin <simon@nasilyan.com>
Tested-by: Inwit <inwit@sindominio.net>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-06-20 09:02:01 +02:00
Simon Martin
3625e0f04a imap: workaround list-status issue with zoho
I've been working with skejg on a regression from 0.20 that he's seeing
with his Zoho account: when receiving a new email, the unread counter is
incremented but the message list is not updated.

The change in scope is 96603ea04e, that uses the directory name
instead of "" when LIST STATUS'ing a single directory, which improves
overall performance, especially for accounts with many folders.

The problem is that Zoho does not give an error in such a case, but also
does not return *any* status, making the CheckMail command virtually a
no-op.

This patch works this around (while not removing the performance benefit
to "normal providers") by always restricting the LIST STATUS' ref if a
single directory is required, and in case it returns neither a status
nor an error, do another LIST STATUS with "" as ref.

Fixes: 96603ea04e ("imap: only restrict list-status to a single directory when we can")
Reported-by: skejg <grolleman@zoho.com>
Signed-off-by: Simon Martin <simon@nasilyan.com>
Tested-by: skejg <grolleman@zoho.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-06-20 09:02:01 +02:00
Simon Martin
53b1d30515 imap: fix comment typo
The only think worse than no documentation is incorrect documentation...

Signed-off-by: Simon Martin <simon@nasilyan.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-06-12 11:36:47 +02:00
Simon Martin
55e9db303e imap: do not ignore delete notifications linked to move actions
As part of my analysis about read/unread, I noticed a bug in 8fc6ddd2:
the worker bit wrongly assumes that we can only have an ExpungeHandler
for deletes, and that MessageUpdates for messages in the ExpungeHandler
should therefore be ignored (because another one will arrive later).

This assumption is however wrong, and we should NOT ignore those updates
if the ExpungeHandler was built for a move action.

Fixes: 8fc6ddd292 ("imap: support various provider policies for expunge calls")
Signed-off-by: Simon Martin <simon@nasilyan.com>
Tested-by: Karel Balej <balejk@matfyz.cz>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-06-11 10:12:09 +02:00
Simon Martin
77758cc37c imap: use sequence to handle deletions not found in expungehandler
As part of my analysis about read/unread, I noticed another bug in
8fc6ddd2: if we're notified of a deletion that we are unable to resolve
in the ExpungeHandler, we should revert to using the sequence instead of
erroring out.

Fixes: 8fc6ddd292 ("imap: support various provider policies for expunge calls")
Signed-off-by: Simon Martin <simon@nasilyan.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-06-11 10:11:42 +02:00
Simon Martin
4cfc71b1be imap: improve seen count management
While investigating a reported slowness when marking messages (un)read,
I noticed an issue with commit 7cb8e0e7ce: it systematically updates
the Seen count using the unsolicited message's status. This is wrong
because we might receive that message long after we updated things on
our end, or at the next action on the message (e.g. opening it).

We need to compare the status reported by the server with ours, and only
if they differ update the counter with what the server states.

Doing so also allows to fix the reported slowdown by reflecting Seen
flag updates right after an explicit :[un]read command, instead of
deferring to the confirmation by the IMAP server, and paying the
(unnecessary) latency of a round-trip. It is safe because we will only
do it after a successful UidStore call, hence confirmation from the IMAP
server of the flag change.

Fixes: 7cb8e0e7ce ("imap: properly handle out-of-band Unseen flag updates")
Link: https://lists.sr.ht/~rjarry/aerc-discuss/%3CDACPBQ04UHUF.30CJJ4QKJDYLY@zoho.com%3E
Reported-by: skejg <grolleman@zoho.com>
Signed-off-by: Simon Martin <simon@nasilyan.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-06-11 10:11:16 +02:00
Folker Schwesinger
0d46a43a14 maildir: fix filename encoded UID removal when moving messages
Recently, in the process of updating the codebase to go-maildir v0.6.0
the logic to strip potential UID parts from the message filenames was
dropped. However, maildir synchronizer isync/mbsync encodes the UID
within the filename of the email and cannot recover if the UID is
preserved during a move.

Re-add the UID stripping logic to remove the "U=xxx" part from message
filenames.

Fixes: 730624ce ("mod: update go-maildir")
Link: https://lists.sr.ht/~rjarry/aerc-devel/patches/34893
Link: https://lists.sr.ht/~rjarry/aerc-discuss/%3CDACSXDU86DC3.LPLLI44C0QAK@sbinet.org%3E
Signed-off-by: Folker Schwesinger <dev@folker-schwesinger.de>
Tested-by: Sebastien Binet <s@sbinet.org>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-06-05 12:44:08 +02:00
Moritz Poldrack
730624ce47 mod: update go-maildir
Update to the latest version of go-maildir and update the code to use
the new methods.

Signed-off-by: Moritz Poldrack <git@moritz.sh>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-05-25 19:05:07 +02:00
Simon Martin
872e7879d2 imap: properly clean-up resources upon user initiated disconnect
While investigating how to speed up IMAP sync with the ProtonMail
bridge, and using :[dis]connect quite a bit, I noticed that after a
:disconnect, the first :connect consistently fails with the following
error (the next one works fine):

   auto-reconnect is disabled; run connect to enable it

This happens because the IMAP worker only partially cleans up its
connection dependent context, and what is left behind comes in the way
of the next :connect.

This patch makes the clean-up complete, and make :disconnect => :connect
work as expected.

Signed-off-by: Simon Martin <simon@nasilyan.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-05-21 18:28:26 +02:00
Simon Martin
8fc6ddd292 imap: support various provider policies for expunge calls
To delete N messages, aerc issues a single EXPUNGE command to the IMAP
server. The server sends back one ExpungeUpdate for each of those N
messages, and aerc reacts to each to update the folder contents.

Unfortunately, the RFC does not specify the order in which a conforming
server should send those "individual replies". aerc currently implicitly
assumes that it deletes messages in increasing sequence number order
(what GMail or FastMail do), and deleting N>1 messages will generally
not work for servers that use a different policy (e.g. Office 365 or
WorkMail, among others).

This patch implements an automatic detection of the policy used by the
server and adapts to it. Since some servers use a policy that can
confuse the automatic detection (e.g. WorkMail that deletes in random
order), it's also possible to statically configure that policy in
accounts.conf if needed.

Fixes: 80408384 ("handle outdated sequence numbers from server [...]")
Signed-off-by: Simon Martin <simon@nasilyan.com>
Tested-by: Karel Balej <balejk@matfyz.cz>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-05-12 13:18:38 +02:00
Simon Martin
8e56e9a3ee imap: dedupe mailboxupdate messages generated by go-imap v1.2.1
This is an alternative to 96ccb183 that was breaking some counters and
had to be reverted.

What triggered the initial patch is the fact that whenever going from
one folder to the other, I noticed that *two* LIST-STATUS were sent to
the server one after the other. They are triggered by MailboxUpdate
notifications by go-imap - 2 generated within the same millisecond (see
comment in the patch as to why).

The initial patch simply ignored those MailboxUpdates, which is actually
wrong: we don't want to have too many, but need at least one. What that
patch does is implement a crude deduplication mechanism that will ignore
any MailboxUpdate received by an IMAP worker within 20ms of the previous
one on the very same worker. The 20ms value is arbitrary, but looks like
a reasonable tradeoff between wrong and missed dedupes - examples of
actual timings can be found in
https://paste.sr.ht/~simartin/923d164d9f80344c91cb287e3272a82e6d2a6eff.

Fixes: 96ccb183 ("remove spurious checkmail when changing directories")
Reported-by: Karel Balej <balejk@matfyz.cz>
Signed-off-by: Simon Martin <simon@nasilyan.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-05-05 10:54:36 +02:00
Simon Martin
7cb8e0e7ce imap: properly handle out-of-band Unseen flag updates
I noticed that the fix I made via b576ab28 (and the general idea to get
rid of materialized RUE counters) does not work, because we're extremely
unlikely to have all the messages' flags in memory. So the patch worked
"by chance" when updating messages that are in the active message list
(e.g. their headers are already fetched) but not for "out of view"
messages.

This alternative patch "just" captures unsolicited MessageUpdate
messages from the server, and updates the Unseen counter according to
the status reported by the server for that message. This allows to
synchronize our view with the server's.

Fixes: b576ab28 ("properly update UI upon message (un)read in [...]")
Fixes: https://todo.sr.ht/~rjarry/aerc/307
Signed-off-by: Simon Martin <simon@nasilyan.com>
Tested-by: Karel Balej <balejk@matfyz.cz>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-04-07 10:51:38 +02:00
Robin Jarry
0ca8087ec9 treewide: replace interface{} with any
Since go 1.18, interface{} can be replaced with any.

Signed-off-by: Robin Jarry <robin@jarry.cc>
Reviewed-by: Karel Balej <balejk@matfyz.cz>
2025-04-07 10:51:05 +02:00
Simon Martin
87a3b42daa imap: partially revert two recent patches
Karel reported weird behaviour with RUE counters that are linked to two
of my recent patches:

- 96ccb183fb is simply wrong
- c9a57f76bf is a bit too eager at
  trusting the message store to recompute counters

This patch addresses those issues, and seems to address all the reported
issues at least on my mailboxes.

Fixes: 96ccb183fb ("imap: remove spurious checkmail when changing directories")
Fixes: c9a57f76bf ("msgstore: properly rebuild message store upon reconnection")
Signed-off-by: Simon Martin <simon@nasilyan.com>
Tested-by: Karel Balej <balejk@matfyz.cz>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-04-02 17:33:48 +02:00
Simon Martin
fb2908e778 imap: revert "handle outdated sequence numbers ... move/delete"
Revert commit 80408384ae ("imap: handle outdated sequence numbers from
server upon move/delete") which breaks "delete multiple messages in one
go" on GMail (ironically, it actually fixes this use case on WorkMail).

The fundamental problem is that IMAP often relies on sequence numbers
instead of UIDs (e.g. to delete multiple messages), and the RFC is super
open in terms of what the server should reply (see
https://datatracker.ietf.org/doc/html/rfc3501#section-7.4.1). GMail and
WorkMail are both compliant, but do completely different things.

Let's restore the functionality for GMail until I find a fix that works
for all providers.

Fixes: 80408384ae ("imap: handle outdated sequence numbers from server upon move/delete")
Signed-off-by: Simon Martin <simon@nasilyan.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-04-01 16:23:40 +02:00
Simon Martin
96603ea04e imap: only restrict list-status to a single directory when we can
rjarry mentioned on IRC that my e4b38efb29
commit was a bit too brutal, and regressed check-mail (checking only the
current directory instead of all).

This patch improves it by continuing to use "" as ref for LIST-STATUS
unless CheckMail.Directories contains a single directory, in which case
it uses it as ref.

This keeps most of the performance benefits (since we usually have at
most one directory to check when navigating between folders) without
regressing in terms of functionality (in particular I've checked that
check-mail does look at and updates *all* folders, not only the current
one).

Signed-off-by: Simon Martin <simon@nasilyan.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-04-01 14:57:54 +02:00
inwit
a6220d025a tag: allow to toggle tags
So far, the :tag command in the notmuch and jmap workers allows adding a
tag (by prefixing it with '+') and removing it (by prefixing it with
'-'). Add a new functionality to this command, allowing it to toggle a
tag by prefixing it with '!'.

Fixes: https://todo.sr.ht/~rjarry/aerc/292
Changelog-added: It is now possible to toggle notmuch and JMAP tags.
Signed-off-by: inwit <inwit@sindominio.net>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-03-30 22:10:58 +02:00
Simon Martin
3eb0046dde foldermap: map directory in Messages{Moved,Copied} and RemoveDirectory
When moving an unread message from current directory C to directory D,
the unseen count for C is properly decremented. However the one for D is
not consistently handled:

- If D is not folder-mapped, it's incremented, as expected.
- If D is folder-mapped, it's unchanged, a clear bug.

The problem is that the folderMapper.PostMessage is not intercepting and
de-mapping three commands that manipulate directory names.

This patch handles all them (I grepped for all PostMessage calls and I
think I got all the missing ones). It also adds an error log to
AccountView.updateDirCounts in case it processes a message that
references an unknown directory, a likely folder mapping bug.

Signed-off-by: Simon Martin <simon@nasilyan.com>
Reviewed-by: Moritz Poldrack <moritz@poldrack.dev>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-03-30 21:31:28 +02:00
Simon Martin
80408384ae imap: handle outdated sequence numbers from server upon move/delete
To delete N messages, aerc issues a single EXPUNGE command to the IMAP
server. The server sends back one ExpungeUpdate for each of those N
messages, and aerc reacts to each to update the folder contents.

The problem is that ExpungeUpdate messages contain a sequence number
that aerc uses to find the deleted message's UID, do its thing, and
*rightfully* pop the sequence number from the sequence. This works well
as long as N=1, but not otherwise: after the first ExpungeData, aerc and
the server have a different view of the sequence, and all subsequent
ExpungeData messages reference an *outdated* sequence number (yaaay
distributed systems :-D)), and
- If that number is higher than the current number of messages in the
folder, we log an error.
- Otherwise, we don't update the correct message in the UI :-/

This patch takes a snapshot of the current sequence numbers for all the
UIDs being deleted/moved, and uses it (not the actual sequence map) when
processing ExpungeUpdate messages from the server.

Signed-off-by: Simon Martin <simon@nasilyan.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-03-30 21:29:16 +02:00
Simon Martin
e4b38efb29 imap: properly set mailbox information in list-status calls
aerc is sluggish at start-up and when switching directories when
accessing my 5GB large WorkMail mailbox using IMAP.

This is due to to LIST-STATUS actions taking 7 (!!) seconds, because it
does not properly set the reference name in LIST-STATUS calls, hence
lists *everything* in the mailbox. When a specific folder is selected
(e.g. pretty much all the time except at startup), we can and should
restrict to the current folder. This is exactly what this patch does.

You can see before and after numbers for my mailbox in
  https://paste.sr.ht/~simartin/86065a15ded912375161f96031f4cf779c7e65d4

In terms of user experience, that latency observed between starting aerc
on my mailbox and having the default folder displayed goes from 29s to
14s (it's still high but I think it's still a good improvement).
Switching between folders also feels much snappier.

Signed-off-by: Simon Martin <simon@nasilyan.com>
Tested-by: Folker Schwesinger <dev@folker-schwesinger.de>
Tested-by: Moritz Poldrack <moritz@poldrack.dev>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-03-30 21:28:18 +02:00
Benno Lossin
a135097c09 maildir: fix sorting of thread siblings
Expose the account name in the `WorkerInteractor` interface and make use
of `ThreadingBySubject`, `ReverseThreadOrder` and `SortThreadSiblings`
in the maildir worker instead of constants.

Fixes: 86c612e480 ("maildir: enable backend threads")
Changelog-fixed: Maildir backend now builds the therads according
 to the various config options such as `sort-thread-siblings`,
 `reverse-msglist-order`, `threading-by-subject` and
 `reverse-thread-order`.
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-03-30 21:13:37 +02:00
Benno Lossin
a1830af485 worker: fix sorting of entire threads
Instead of sorting threads by the message with the greatest UID, instead
sort by the message greatest according to the `sortBy` slice.

Fixes: 65ae87a524 ("threading: honor user-defined sort criteria")
Changelog-fixed: Threads now sorted by the greatest message according
 to the sort criteria and not by the message with the greatest UID.
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-03-30 21:11:19 +02:00
Simon Martin
96ccb183fb imap: remove spurious checkmail when changing directories
I investigated why aerc felt so slow when changing directories with my
mailbox, and noticed that a spurious CheckMail is triggered whenever
OpenDirectory is called.

This happens because OpenDirectory does a Select(TheTargetMailbox),
which gets the server to reply a MailboxUpdate message for the target
directory, in turn triggering a (slow) CheckMail.

That CheckMail is completely useless, since the normal flow that follows
OpenDirectory involves a FetchDirectoryContents, which is what we need
to draw the message list (and not more).

This patch leverages a drainCloser object to ignore spurious messages
from the server, exactly like handle{Move,Delete}Messages do.

Some measurements to quantify the impact can be found in
  https://paste.sr.ht/~simartin/05011fb7615c5b60bf12bb36fc9d08221550e403
TL;DR: The latency of Shift+K => Shift+J to go to a large (8.6k message)
folder and back is divided by ~7.

Signed-off-by: Simon Martin <simon@nasilyan.com>
Reviewed-by: Moritz Poldrack <moritz@poldrack.dev>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-03-19 00:28:47 +01:00
Simon Martin
03061fe21f imap: fix processing of search criteria end date
This patch fixes a copy/paste error in translateSearch that was leading
to the types.SearchCriteria's StartDate to be mapped to both SentSince
and SentBefore in the imap.SearchCriteria, and the actual EndDate to be
ignored.

Fixes: 8464b37385 ("search: use a common api for all workers")
Signed-off-by: Simon Martin <simon@nasilyan.com>
Reviewed-by: Moritz Poldrack <moritz@poldrack.dev>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-03-09 00:40:30 +01:00
Jakub Růžička
40381389b2 imap: increase connection-timeout to 90 seconds
In case when the server does not support IDLE command, then default
value of the polling interval set in go-imap to 60 seconds is larger
then the default value of connection-timeout set to 30 seconds.
Therefore aerc disconnects while polling every 30 seconds, because there
is no activity.

This was tested on seznam.cz as well as a self hosted dovecot, where the
IDLE command was removed from announced capabilities.

Changelog-fixed: IMAP servers without IDLE support do not timeout
 while polling.
Changelog-changed: The default IMAP connection timeout has been
 increased to 90 seconds.
Signed-off-by: Jakub Růžička <jakub.ruzicka@matfyz.cz>
Tested-by: Karel Balej <balejk@matfyz.cz>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-03-05 17:33:58 +01:00
Robin Jarry
985ce7a92b jmap: explicitly fetch body structure subparts
When requesting the bodyStructure email property, the spec says that the
default returned body part properties are: ["partId", "blobId", "size",
"name", "type", "charset", "disposition", "cid", "language",
"location"].

Specifically, the "subParts" property is *NOT* expected by default.

Fastmail servers seem to use a different default "bodyProperties" list
and implicitly return "subParts" even if not requested.

Other JMAP server implementations (e.g. Apache James) do use the RFC
default "bodyProperties" and therefore omit returning "subParts" unless
explicitly asked to.

Change the requested "bodyProperties" to include "subParts" as well.
Aerc needs them to display messages.

NB: for later, we should probably change our message abstraction not to
include any body structure. This makes very little sense to expose that
to users. In fact, aerc has code to explicitly prevent users from
selecting multipart/* parts. Not requesting that information to the
server would make it easier.

Link: https://datatracker.ietf.org/doc/html/rfc8621#section-4.2
Reported-by: Benoit Tellier <btellier@linagora.com>
Signed-off-by: Robin Jarry <robin@jarry.cc>
Reviewed-by: Tim Culverhouse <tim@timculverhouse.com>
2025-02-11 21:02:24 +01:00
Robin Jarry
4e545d45fa treewide: fix English spelling
Use codespell to fix typos in code, comments and man pages.

Signed-off-by: Robin Jarry <robin@jarry.cc>
Reviewed-by: Bence Ferdinandy <bence@ferdinandy.com>
Acked-by: inwit <inwit@sindominio.net>
2025-01-21 13:39:01 +01:00
Robin Jarry
aef7bb09aa imap: add support for plain auth
If the server reports the AUTH=PLAIN SASL mechanism, use it in priority
over LOGIN which has been deprecated in favor of SASL.

Pass an empty identity argument which results in identity=username. Aerc
does not have the ability to configure it.

Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Runxi Yu <me@runxiyu.org>
2025-01-16 21:00:47 +01:00
Robin Jarry
553fabbc2e jmap: handle copy-to and :send -t
The jmap:// outgoing backend always copies (actually, just tags) the
sent emails with the mailbox that has the "sent" role. Regardless of the
copy-to or :send -t <folder> argument. Only the copy-to-replied setting
is effective.

Change the CopyTo parameter of the StartSendingMessage backend operation
to hold a list of folder names.

In the JMAP worker, label the sent message with the list of folders,
eliminating duplicates (e.g. do not label with "sent" role twice).

Reported-by: Matěj Cepl <mcepl@cepl.eu>
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Matěj Cepl <mcepl@cepl.eu>
2024-12-21 17:02:31 +01:00
Tim Culverhouse
b77bd33d8a jmap: cache threads
Cache threads that we have fetched. Monitor threads for changes, and
fetch any email which we don't have for any thread that changes.

Changelog-added: The JMAP backend now supports full thread fetching
 and caching (limited within a single mailbox).
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-12-21 16:49:31 +01:00
Tim Culverhouse
64b3d96d2f jmap: correctly compare when FolderContents needs refresh
A folders contents need refreshing if we don't have any saved state, or
if the sort criteria is different than the cache, or if the filter is
different than the cache. The previous logic required a refresh if
the cached filter == nil. This is almost always the case: opening a
plain folder has a nil filter. The only filter criteria is added in the
parsing step (ie: inMailbox). This meant every directory change that
wasn't already filtered required a Refresh. The new logic fixes this.

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-12-21 16:49:14 +01:00
Tim Culverhouse
95f60f8010 jmap: only call queryChanges for updated mailboxes
Track the list of updated mailboxes and make a second request which
updates only those mailboxes who require an update. The queryChanges
call can be expensive. In brief testing of the previous logic (which
queried changes for all mailboxes), the request time was reduced from
~300ms to ~60ms. Reducing the number of queryChanges calls has a
dramatic performance improvement here. A typical operation of moving
messages from one mailbox to another will result in only two mailboxes
being updated - which is a much faster request than the entire list.

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-12-21 16:49:14 +01:00
Tim Culverhouse
d3eeec606b jmap: directly check updated email mailboxes on update
Directly check if the updated email belongs to our selected mailbox.

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-12-21 16:49:14 +01:00
Tim Culverhouse
9f47067225 jmap: rely on updates to update mailbox list
The JMAP worker list directories logic performed a few too many
requests. The logic was:

1. Query the remote server for the mailbox state
2. If the state matches our cache, use the cache
3. If it doesn't match, query for the mailbox list

However, we can rely on the update channel to send updates for the
mailbox list, as long as we have a list to be updated, ie the cached
state value is not the empty string. Modify the logic such that the
cache is always trusted, and updates will be received from the update
channel. Make a request for the mailbox list only when there is nothing
in the cache, or we have missing mailboxes to fetch.

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-12-21 16:49:14 +01:00
Tim Culverhouse
9ef50626ba jmap: start listening for changes on Connect message
Start listening for remote changes as soon as we have the connect
message. The previous implementation listened once a ListDirectories
call was received, unnecessarily delaying updates.

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-12-21 16:49:14 +01:00
Tim Culverhouse
bbc5047c03 jmap: update flags on successful Email/set
The JMAP worker receives all updates from the update channel. This can
cause some UI responsiveness issues when the update is slow. For a
common task of updating message keywords, we can update the UI
immediately if the response indicates a successful set call.

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-12-21 16:49:14 +01:00
Koni Marti
6736cf0402 jmap: ignore charset encoding error
Ignore and log a charset error when fetching a message part.

Reported-by: Matěj Cepl <mcepl@cepl.eu>
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-12-09 09:40:42 +01:00
Koni Marti
edeac1a1c6 commands: fix empty entries from completion funcs
Fix the commands.GetTemplates() and types.StrategyStrs() completion
functions to avoid showing empty entries.

Reported-by: inwit <inwit@sindominio.net>
Reported-by: pam79
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-11-09 19:02:39 +01:00