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>
The maintainer of this library has gone AWOL. We are depending on
a patch that has never been merged. Let's vendor the library to avoid
future issues.
This patch has been made with the following steps:
git clone https://github.com/konimarti/jwz lib/jwz
git -C lib/jwz checkout fix-missing-messages
mv lib/jwz/test/testdata/ham lib/jwz/testdata
sed -i 's#test/testdata#testdata#' lib/jwz/jwz_test.go
rm -rf lib/jwz/.* lib/jwz/docs lib/jwz/examples lib/jwz/test
sed -i 's#github.com/gatherstars-com/jwz#git.sr.ht/~rjarry/aerc/lib/jwz#' \
lib/threadbuilder.go
go mod tidy
git add --intent-to-add lib/jwz
make fmt
Along with some manual adjustments to fix the linter warnings. Also, to
make the patch smaller, I only kept 93 test emails from the test data
fixture.
Changelog-changed: The JWZ library used for threading is now vendored.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Reviewed-by: Moritz Poldrack <moritz@poldrack.dev>
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>
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>
When typing inside textinput, Ctrl+Left places the cursor at the start
of the current word, and Ctrl+Right goes to the start of the next one.
Ctrl+Left uses the same code `deleteWord()` function used (which is now
split into a separate function), and Ctrl+Right uses similar lookup in
the other direction.
Implements: https://todo.sr.ht/~rjarry/aerc/231
Signed-off-by: GregTheMadMonk <yagreg7@gmail.com>
Tested-by: skejg <grolleman@zoho.com>
Acked-by: Robin Jarry <robin@jarry.cc>
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>
My kids' school has put a leading space in their name, which breaks the
visual alignment in the message list and viewer.
This patch calls TrimSpace when displaying addresses and fixes both
views.
Signed-off-by: Simon Martin <simon@nasilyan.com>
Acked-by: Robin Jarry <robin@jarry.cc>
When navigating between messages in the Message Viewer, the whole tab is
updated except its title: it remains set to the subject of the message
that was initially opened in that tab.
Tabs.Replace needs to update both the content *and* the title; this is
what this patch does.
Signed-off-by: Simon Martin <simon@nasilyan.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Some address names may be quoted AND partially encoded. That is only
a word in the middle of the name could be encoded (and be surrounded by
=? and ?= delimiters).
Just check if the address name contains these two delimiters (regardless
of their position) to determine if we should re-decode the name.
Fixes: 44b14ebdff ("rfc822: be liberal with invalid address headers")
Signed-off-by: Robin Jarry <robin@jarry.cc>
Add a template for the terminal tab title and define two
terminal-specific properties: Title which expands to whatever the
underlying application requests via OSC and defaults to the command name
and Bell which is a boolean indicating whether the application has
emitted bell, the flag is cleared when the corresponding tab gains focus
and is not set at all if it currently has it.
This can among other things be used to highlight the terminal tab when
the underlying process prints the bell, such as by setting the template
as such:
tab-title-terminal={{if .Bell}}[BELL] {{end}}{{.Title}}
Implements: https://todo.sr.ht/~rjarry/aerc/138
Changelog-added: A tab-title-terminal setting for customizing the
title of tabs in which the terminal widget is run.
Requested-by: Drew DeVault <drew@ddevault.org>
Signed-off-by: Karel Balej <balejk@matfyz.cz>
Acked-by: Robin Jarry <robin@jarry.cc>
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>
Add a flag to indicate whether the account has received new messages
since it last had focus and allow its use in the templates.
Changelog-added: A `.HasNew` flag indicating whether the account has
received new messages to be used in the templates.
Signed-off-by: Karel Balej <balejk@matfyz.cz>
Tested-by: Inwit <inwit@sindominio.net>
Acked-by: Robin Jarry <robin@jarry.cc>
When sort-thread-siblings = false and threading-by-subject = true, do
not order siblings by ascending UID. Instead, use the message Subject
headers to order siblings.
Changelog-changed: Thread siblings will now be ordered by subject if
`[ui].sort-thread-siblings = false` and `[ui].threading-by-subject
= true`.
Reported-by: Brendan Jackman <jackmanb@google.com>
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Brendan Jackman <jackmanb@google.com>
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>
After "gmake config", git-send-email currently fails on Darwin with the
following:
> lib/watchers/fsevents.go:67:11: Error return value of `w.w.Start` is
> not checked (errcheck)
This patch fixes this by checking the return code and bubbling it up in
case of error.
Signed-off-by: Simon Martin <simon@nasilyan.com>
Acked-by: Robin Jarry <robin@jarry.cc>
This patch fixes an error that occurs when decrypting an email with an
invalid gpg signature. The error "gpg-exit 33554433" will be thrown and
the email will not be opened.
Signed-off-by: Bryce Vandegrift <bryce@brycevandegrift.xyz>
Acked-by: Robin Jarry <robin@jarry.cc>
Due to vaxis low-level design, the enter key of the number block has
a different key code that a regular carriage return. Since most people
do not care which of the two they are hitting, remap the former and
up/down/left/right to act like the latter.
Changelog-added: Support for number block enter to act as <Cr>
in mappings.
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Reviewed-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
During startup, d.account and d.folder are not set and thus not
lead to a segmentation fault when running a signature command.
Only set these values if they are available.
Fixes: da5ca1a5 ("template: pass account and folder names to signature command")
Changelog-fixed: Fix an error when starting aerc through a `mailto:`
link when the `new_message` template runs a signature command.
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Acked-by: Robin Jarry <robin@jarry.cc>
In some cases it can be desirable to receive a success notification for
a message from the server. This currently only works on SMTP.
Changelog-added: Add option to request full DSN for SMTP sent messages.
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Acked-by: Robin Jarry <robin@jarry.cc>
lib/marker makes extensive uses of maps, but does not guard against
concurrent accesses. Add two mutexes to ensure read and write access do
not happen simultaneously.
Changelog-fixed: Fixed an unguarded concurrent map access leading
to crashes.
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Tested-by: Terrance <srht@terrance.allofti.me>
This commit fixes a critical bug found by the CI where import was
allegedly misspelled
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Acked-by: Robin Jarry <robin@jarry.cc>
Add a direct mailserver poker that tries to connect to the mailserver
with the highest priority retrieved from via DNS.
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Acked-by: Robin Jarry <robin@jarry.cc>
Add a fallback to the autoconfig module that performs some educated
guesses regarding hostname, port, and encryption.
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Acked-by: Robin Jarry <robin@jarry.cc>
Add the capability to parse DNS entries to infer mailserver settings.
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Acked-by: Robin Jarry <robin@jarry.cc>
Add a function to retrieve configurations from the autoconfig-subdomain
or a .well-known file.
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Acked-by: Robin Jarry <robin@jarry.cc>
Add a command to copy links to the system clipboard. This can be useful
for instance when the URL should be handled in some other way than
opened (e. g. resent via some other communication channel or saved to a
file). It also improves security for situations where it's not desirable
for the URL to be visible on the process command line, such as when it
contains sensitive information such as an access token.
Adapted from open-link.
Changelog-added: If supported by the terminal, links from a message
can now be copied to the system clipboard with the :copy-link command
of the message viewer.
Signed-off-by: Karel Balej <balejk@matfyz.cz>
Acked-by: Robin Jarry <robin@jarry.cc>
Make sure that links placed verbatim inside HTML elements' bodies are
not parsed along with adjacent HTML tags as illustrated in the new test
case.
Also change the existing code to use the idiomatic Go way to get a
set-like functionality.
Changelog-fixed: Parsed links in HTML message parts now do not include
trailing HTML tags.
Signed-off-by: Karel Balej <balejk@matfyz.cz>
Tested-by: Jakub Růžička <jakub.ruzicka@matfyz.cz>
Threaded directories were never marked as loaded and thus the terminal
bell was never rung when a new message arrived in them. Add the missing
directive to mark them as loaded when appropriate.
Fixes: 8d4704775b ("msgstore: do not trigger notification on initial load")
Changelog-fixed: The new-message bell is now rung again for threaded
directories as well.
Cc: Remko Tronçon <remko@el-tramo.be>
Signed-off-by: Karel Balej <balejk@matfyz.cz>
Acked-by: Robin Jarry <robin@jarry.cc>
When composing a message, the location of the popovers was not offset by
the location of the field that was being completed (To, Cc,...)
resulting in them appearing always at the same position near the top
left corner of the window. Restore the offset to have them appear right
underneath the active field again.
Fixes: 787cfbd9a9 ("ui: remove screen and viewports")
Changelog-fixed: The address-book completion popovers now again appear
under the field being completed.
Signed-off-by: Karel Balej <balejk@matfyz.cz>
Reviewed-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Fix the following error when running tests with go 1.24:
lib/iterator/iterator_test.go:58:12: non-constant format string in call to (*testing.common).Errorf
lib/iterator/iterator_test.go:62:13: non-constant format string in call to (*testing.common).Errorf
lib/iterator/iterator_test.go:66:12: non-constant format string in call to (*testing.common).Errorf
lib/iterator/iterator_test.go:69:12: non-constant format string in call to (*testing.common).Errorf
lib/iterator/iterator_test.go:83:12: non-constant format string in call to (*testing.common).Errorf
lib/iterator/iterator_test.go:87:13: non-constant format string in call to (*testing.common).Errorf
lib/iterator/iterator_test.go:91:12: non-constant format string in call to (*testing.common).Errorf
lib/iterator/iterator_test.go:94:12: non-constant format string in call to (*testing.common).Errorf
Signed-off-by: Robin Jarry <robin@jarry.cc>
Add the filters folders to the exec search path when calling the "exec"
template function. This is to allow executing filters by name.
Changelog-changed: The templates `exec` commands is now executed with
the `filters` exec `$PATH` similar to filter commands.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Bence Ferdinandy <bence@ferdinandy.com>
Update go-pgpmail which has a similar fix to the one we had in place.
Update our fix to use the same implementation: do not parse the whole
signed part. Only parse the part header, remove the mime-version header
from it if any and re-write it, followed the part body verbatim without
any decoding/re-encoding.
Fixes: 7346d20343 ("gpg: fix signed message encoding")
Fixes: 7b8fbe2a3d ("gpg: fix mime-version header position")
Signed-off-by: Robin Jarry <robin@jarry.cc>
Reviewed-by: Simon Ser <contact@emersion.fr>
Given the following tab layout: name(index). The current index is 2 and
history is considered empty:
MessageList TermFoo [TermBar] Viewer
0 1 2 3
If we focus TermFoo, index 2 is added to history and current index
becomes 1:
MessageList [TermFoo] TermBar Viewer
0 1 2 3
Now, if we close TermFoo, the last item in the history (2) is popped and
selected:
MessageList TermBar [Viewer]
0 1 2
This leads to selecting the message viewer whereas TermBar should have
been selected.
A different issue happens when the tab history index is out of bounds.
For example:
MessageList TermFoo [TermBar]
0 1 2
Move to TermFoo, 2 is pushed to history:
MessageList [TermFoo] TermBar
0 1 2
Close TermFoo, last index in history (2) is invalid, current index
remains selected but not completely:
MessageList [TermBar]
0 1
The widget/terminal in TermBar will not be focused or made visible to
the ui (via (Visible).Show(true)) until one key is pressed. Effectively
delaying interaction with the program running in it.
Replace a list of index with a list of pointers to *Tab objects for the
history. This makes it impervious to removal, reordering and removes
the need to recompute the history indexes.
Limit the history to 256 items to avoid memory hog after a long time.
When removing the current tab, ensure "something" is selected. If the
history is empty, select the next best thing.
Suggested-by: Koni Marti <koni.marti@gmail.com>
Reported-by: Brandon Sprague <brandon@sprague.mx>
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
RFC 5322 states that messages should only use CRLF line endings. Here
are two important excerpts:
> 2.1. General Description
>
> Messages are divided into lines of characters. A line is a series of
> characters that is delimited with the two characters carriage-return
> and line-feed; that is, the carriage return (CR) character (ASCII
> value 13) followed immediately by the line feed (LF) character (ASCII
> value 10). (The carriage return/line feed pair is usually written in
> this document as "CRLF".)
> 2.3. Body
>
> The body of a message is simply lines of US-ASCII characters. The
> only two limitations on the body are as follows:
>
> o CR and LF MUST only occur together as CRLF; they MUST NOT appear
> independently in the body.
> o Lines of characters in the body MUST be limited to 998 characters,
> and SHOULD be limited to 78 characters, excluding the CRLF.
Most MTA are tolerant to invalid messages but some others are more
pedantic. Ensure we only send valid line endings.
Link: https://www.rfc-editor.org/rfc/rfc5322.html#section-2.1
Link: https://www.rfc-editor.org/rfc/rfc5322.html#section-2.3
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Matěj Cepl <mcepl@cepl.eu>
When sending signed messages with outgoing = jmap://, the following
error is returned by the server (provider=Fastmail):
Message contains bare newlines
RFC 5322 section 2.3 states that:
> CR and LF MUST only occur together as CRLF; they MUST NOT appear
> independently in the body.
Most MTA handle invalid messages without warnings, but some others
reject them.
Ensure GPG generated parts use CRLF to comply with the RFC.
Fixes: 57699b1fa6 ("feat: add gpg integration")
Link: https://www.rfc-editor.org/rfc/rfc5322.html#section-2.3
Changelog-fixed: GPG signatures and encrypted parts now use CRLF line
endings as required by RFC 5322.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Matěj Cepl <mcepl@cepl.eu>
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>
There currently is no difference between updating the store of
a directory that was already loaded, and a directory that has not yet
been initialized. When a directory is opened, and the initial update
request is processed, all messages are therefore treated as new, and the
directory change notification (i.e. bell) is triggered.
To prevent triggering this update, track whether the directory was
already initialized, and if not, don't send out any change
notifications.
Signed-off-by: Remko Tronçon <remko@el-tramo.be>
Acked-by: Robin Jarry <robin@jarry.cc>
Parse multipart messages on a best-efforts basis. Allow the user to see
as much of the message as possible, but log the errors.
If a charset or encoding error is encountered for a message part of a
multipart message, the error is logged and ignored. In those cases, we
still get a valid message body but the content is just not decoded or
converted. No error will be propagated.
If a multipart message cannot be parsed, ParseEntityStructure will
return a multipart error. This error indicates that the message is
malformed and there is nothing more we can do. The caller is then
advised to use a single text/plain body structure using
CreateTextPlainPart() to provide the entire message content to the user.
Fixes: https://todo.sr.ht/~rjarry/aerc/288
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
By preparing a maliciously crafted message an attacker could send an
encrypted message without signature that would appear as signed within
the aerc client. It is caused by the fact that the gpg status messages,
which are used for determining the validity signature, are interspered
with message contents. An example of such malicious message was added to
the `reader_test.go`.
This change redirects the satus-fd to stderr, while the usual stderr
logs are discarded to /dev/null. In addition to fixing the vulnerability
described above, this has the added benefit of stdout containing only
useful output which does not need to be filtered. This simplifies the
logic and avoids needless copies.
Previous stderr parsing logic which detected when no valid OpenPGP data
was present is replaced with detecting `NODATA 1` in status-fd messages.
The stderr logs are different depending on user locale, thus, they
should not be parsed. On the other hand, the status-fd are relatively
stable. The previous method of detecting invalid OpenPGP data would fail
on systems with non-English locale.
Signed-off-by: Marcin Serwin <marcin@serwin.dev>
Acked-by: Robin Jarry <robin@jarry.cc>
Make the Completer interface accept a context.Context. Provide a
cancellation feature on text input tab completion to cancel an inflight
completion command. This is particularly useful for address book
completion if the user has specified a network-accessing command, eg
carddav-query. The command is started according to the completion delay,
but is cancellable if another request comes in. We also check for
cancellation after the request is complete to ensure we only show valid
completion results.
Changelog-changed: Tab completions for text fields are run
asynchronously. In-flight requests are cancelled when new input
arrives.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
History is more like application state than a cache you would just want
to blow away. Let's reflect that in the path for the history file.
Changelog-changed: The location of the command history file has
changed to ${XDG_STATE_HOME:-$HOME/.local/state}/aerc/history.
Signed-off-by: Tristan Partin <tristan@partin.io>
Acked-by: Robin Jarry <robin@jarry.cc>
Use go-opt v2 new completion API which returns items descriptions along
with their text values.
Display the descriptions after the items separated by two spaces. Wrap
the descriptions in parentheses to better indicate that they are not
part of the completion choices. Limit the description length to 80
characters to avoid display issues.
Add a new style object completion_description in stylesets. By default,
the object will be rendered with a dimmed terminal attribute. Update all
stylesets and documentation accordingly.
Implements: https://todo.sr.ht/~rjarry/aerc/271
Link: https://git.sr.ht/~rjarry/go-opt/commit/ebeb82538395a
Changelog-added: Command completion now displays descriptions next
to completion items.
Changelog-added: New `completion_description` style object in style
sets used for rendering completion item descriptions.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Bojan Gabric <bojan@bojangabric.com>
Tested-by: Jason Cox <me@jasoncarloscox.com>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>