Since the totality of sourcehut only has 4 CI slots at the moment, slim
the CI pipeline down to the lowest common denominator:
Linux (alpine-edge)
- GNU make
- latest Go version
- Go1.13
OpenBSD
- BSD make
- latest available Go Version (currently lagging behind 1 version)
We might also want to consider changing OpenBSD to FreeBSD as to my
knowledge FreeBSD is the more common Home-Computer-Version of BSD
instead of OpenBSD which is mainly used for servers. (please don't lynch
me, dear 3 OpenBSD people)
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Acked-by: Robin Jarry <robin@jarry.cc>
Add a dev target which enables Go's race detector. This requires CGo to
be enabled and reduces performance significantly, but helps in finding
data races which can lead to hard to diagnose bugs.
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Acked-by: Robin Jarry <robin@jarry.cc>
Replace the implicit shell-parsing with explicitly running the command.
This allows the built version to be reflected in the build log.
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Acked-by: Robin Jarry <robin@jarry.cc>
Add the -trimpath flag to the default build command to remove the user's
path from stack traces.
Use a separate BUILD_OPTS make var to avoid it being accidentally
overridden on the command line.
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Acked-by: Robin Jarry <robin@jarry.cc>
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>
The default config had completion-{delay,popover} in the [viewer]
section, but they belong in the [ui] section
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Moritz Poldrack <moritz@poldrack.dev>
Acked-by: Robin Jarry <robin@jarry.cc>
When using section.MapTo(struct) (go-ini), if the struct has a default
value for a time.Duration type, a zero-value in the config will not
overwrite the default. If the type is *time.Duration, it will be
overwritten properly. One consideration was to change all
time.Duration types to *time.Duration. This method was chosen for ease
of implementation.
For example, if you set dirlist-delay = 0s, the delay will be 200ms.
This can be observed by logging the value just after mapping the ui
section in config.go. A config value of 0.1ms will have a delay of
0.1ms.
Currently, aerc has 4 time.Duration config values:
1. DirlistDelay - default 200 ms
2. CompletionDelay - default 250 ms
3. CheckMail - default unset (0)
4. CheckMailTimeout - default 10 s
1, 2, and 4 have a non-zero default value and are subject to this bug.
Only 1 and 2 are fixed in this patch. Number 4 would not make sense to
have a 0 second timeout, therefore we can prevent the user from doing
this by keeping it as it is.
Another option could be to set these to 0 in config.go. The default
config (aerc.conf) has these keys in it with their default values.
Presumably, we don't need to set them again in config.go. If a user
deletes the config values out of aerc.conf, the UI will function but
with 0s delays.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Tested-by: Moritz Poldrack <moritz@poldrack.dev>
Add a default keybind to open messages in the default Postpone folder
("Drafts") in edit-mode.
A frequent question on IRC is "how do I edit a draft?". When a user
selects a Draft and presses <Enter>, the intent is usually to edit that
draft. This commit makes this the default behaviour for the default
Postpone folder.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Add option to specify folder-specific binds for message lists. The binds
are layered: any existing binds in [messages] are overwritten by a more
specific bind in say, [messages:folder=Drafts]. The order is currently:
[messages] < [messages:account=<account>] < [messages:folder=<folder>]
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
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>
Parse http links from a message and display them as completions in the
:open-link command.
Add the following binds to the [view] section in your binds.conf:
<C-l> = :open-link <space>
Parsing can be disabled in aerc.conf by setting parse-http-links to
false in the viewer section.
Thanks to Moritz for the help with the regular expression.
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Reviewed-by: Moritz Poldrack <git@moritz.sh>
Acked-by: Robin Jarry <robin@jarry.cc>
In order to better align to vim functionality: deselect visual mode
selections after performing a command on the selection. This patch also
introduces a new command to allow for re-selecting (remarking) the
previous selection set so that commands can be chained together. The
deselection only applies to msg commands that *do not* move the message
from the store (those types of commands already deselect):
- read/unread
- flag/unflag
- modify-labels
- copy
- pipe
Previous usage to mark several messages as read and deselect all:
Vjjj:read<Enter>:unmark -a<Enter>
New usage, similar to vim:
Vjjj:read<Enter>
To chain a command together:
Vjjj:read<Enter>:remark<Enter>{next command}<Enter>
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
The maildir worker was adding Recent messages to the counts of Unseen
and Exists, however these messages were already included in those counts.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Commit 8b6f971 broke ruestring counts when AccurateCounts=true, which
primarily occur from a checkmail. This restores the functionality.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Parse the Authentication-Results header and display it in the message
viewer (not enabled by default). DKIM, SPF and DMARC authentication
methods are supported. Implement recommendation from RFC 7601 Sec 7.1 to
have an explicit list of trustworthy hostnames before displaying the
authentication results. Be aware that the authentication headers can be
forged.
To display the results for a specific authentication method, add the
corresponding name to the layout of headers in the viewer section of
aerc.conf, e.g. to display all three, use:
header-layout = From|To,Cc|Bcc,Date,Subject,DKIM|SPF|DMARC
More information will be displayed when "+" is appended to the
authentication method name, e.g. DKIM+ or SPF+ or DMARC+.
Also, add the trustworthy hosts per account with the trusted-authres
parameter, e.g.
trusted-authres = *
to trust every host or use regular expressions for a finer control.
Multiple hosts can be entered as a comma-separated list. Authentication
results will only be displayed when the host is listed in the
trusted-authres list.
Link: https://datatracker.ietf.org/doc/html/rfc7601
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Tested-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Commit 2027223a created a panic when attempting to clear the dirlist
when the config option dirlist-tree is set to false.
This patch fixes that panic by creating a dirlist.ClearList() function
to prevent needing to check a callback.
Tested with both dirlist-tree=false and true
Fixes: 2027223ab3 ("fix: clear dirlist on disconnect")
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
A message of Done:Disconnect will trigger an update of the dirlist. An
update of the dirlist will issue a ListDirectories message, which causes
an imap: client not ready error by trying to use the imap connection -
which is disconnected. By not issuing the update, we prevent using a
disconnected client.
This patch checks for connection state prior to updating the dirlist. A
disconnected state will clear out the dirlist.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
If an error occurs when parsing the content-type, check if the
content-type is quoted; if so, remove quotes. If this is not the case,
then return a text/plain content-type as a sane fallback option, so that
the message can be at least viewed in plaintext.
Fixes: https://todo.sr.ht/~rjarry/aerc/44
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
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>
The countRUE function was inaccurately counting flags. If a message was
unread and recent, it was only counted as recent. The two flags are not
mutually exclusive. A previous count for a mailbox with 1 recent, 1
unread, and 5 existing would be :
1/0/5
An accurate count of this state would be:
1/1/5
This patch fixes the count.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
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>
Clean marked messages after new uids are fetched.
Commit 5c5158b3 ("store: remove callbacks on error") removed side
effects in the message store after a longer suspend period but neglected
to remove marked zombie messages.
References: https://todo.sr.ht/~rjarry/aerc/28
Co-authored-by: inwit <inwit@sindominio.net>
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Provide a choice to the user with the selector dialog to select the
desired unsubscribe method. Before, the first method that appeared in
the list-unsubscribe header was used.
For the http method, the user can now also confirm whether he wants to
open the provided link in the browser or not.
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Provide a generic selector dialog popup where the user can select from
different options.
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Check bounds before drawing a dialog window to avoid a panic when
resizing the terminal window.
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Reply to iCalendar invitations with three commands: :accept,
:accept-tentative or :decline. Parse a text/calendar request, create a
reply and append it to the composer.
Suggested-by: Ondřej Synáček <ondrej@synacek.org>
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Append text parts to emails in the composer as multipart/alternative.
Display the mime-type of the parts in the review window.
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Implement a filter to read text/calendar (ics) data with awk.
Parses multiple events and shows the date recurrence if
available. Awk alternative to the python filter.
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Aerc was sending empty address list header fields (specifically CC by
default). This was causing DKIM failures in lists.sr.ht. RFC 5322 states
that an address field should consist of the field name and one or more
addresses, implying empty fields are not allowed.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Commit 1bac87e804 ("terminal: fix race when closing a terminal") fixed
a race in Terminal.Draw by using a mutex. The current locking of the
entire Draw function could create a deadlock, however, since this
function itself might call Terminal.Close which is protected by the same
mutex. A finer-grained locking solves both the race and deadlock
problem.
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Refactor lib/crypto/gpg tests to facilitate unit test runs on macos.
Macos creates temporary directories with names too long to call
gpg-agent (108 characters). Additionally, too many concurrent test calls
created IPC errors to gpg-agent. To get around this, tests were given
shorter names and refactored into subtests to create fewer concurrent
tests
Tested on Linux and MacOS.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Add :help completion arguments (config, imap, etc). The option "aerc"
brings up the general manpage
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Koni Marti <koni.marti@gmail.com>
Skip the tests if gpg is not installed.
Avoid interference with the global ~/.gnupg.
Automatically delete GNUPGHOME at the end of tests.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>
Fix panic when resizing the terminal by dynamically adjusting the width
of the option selector. The selector does not check the width of the
terminal before printing. This can lead to a panic in the account wizard
when reducing the terminal width.
If the terminal width is not large enough, the space between the options
is reduced. If this is still not enough, then the selector will only
show the focused option and arrows indicating the alternatives.
Fixes: https://todo.sr.ht/~rjarry/aerc/41
Reported-by: Omar Polo <op@omarpolo.com>
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Add compose command ("attach-key") to attach the public key associated
with the sending account. Public key is attached in ascii armor format,
with the mimetype set according to RFC 3156 ("application/pgp-keys").
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Tested-by: Koni Marti <koni.marti@gmail.com>
Add check for public keys of all message recipients (to, cc, and bcc)
before sending the message. Adds an OnFocusLost callback to header
editors to facilitate a callback for checking keys whenever a new
recipient is added (OnChange results in too many keyring checks).
Once encryption is initially set, the callbacks are registered. If a
public key is not available for any recipient, encryption is turned off.
However, notably, the callbacks are still registered meaning as s soon
as the user removes the recipients with missing keys, encryption is
turned back on.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Tested-by: Koni Marti <koni.marti@gmail.com>
Unmark deleted messages and remove pending headers in the callback
function when an error in the backend occurs (e.g. due to connection
issues).
The message store marks messages that should be deleted. If the delete
operation in the backend fails, messages are never unmarked and will
remain rendered as empty lines in the message list. This also affects
the move and archive commands that rely on a copy and delete operation.
A similar issue occurs with the pending headers when the operation to
fetch them fails. In this case, messages will appear as loading
indefinitely in the message list and are never re-fetched because the
corresponding pending headers from the failed operations are still
present.
Fixes: https://todo.sr.ht/~rjarry/aerc/28
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
The gpg decrypt function was catching errors but not returning them.
This patch returns errors that are caught instead of aerc panicking.
Reported-by: ReK2 <rek2@hispagatos.org>
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Tested-by: ReK2 <rek2@hispagatos.org>
Acked-by: Robin Jarry <robin@jarry.cc>
Check that the signing key exists when the user issues the :sign
command. The signing key ID will be displayed in the security status
also, allowing the user to see what key will be used to sign the
message.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Tested-by: Jens Grassel <jens@wegtam.com>
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>
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>
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>
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>
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>