aboutsummaryrefslogtreecommitdiffstats
path: root/lib
Commit message (Collapse)AuthorAgeFilesLines
* gpg: redirect status-fd from stdout to stderrMarcin Serwin12 days6-64/+101
| | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* attach: fix content-transfer-encoding for rfc822 attachmentsKoni Marti2024-10-241-0/+16
| | | | | | | | | | | | | | | | | | | | | | Fix the content-transfer-encoding for attachments with message/rfc822 mime types. It's not allowed by RFC2046 to set any other content-transfer-encoding than 7bit, 8bit, or binary for message/rfc822 mime types (see RFC2046, section 5.2.1). We can enforce this by setting a content-transfer-encoding header for attachments to 'binary' explicitly. 'binary' is more lenient than '8bit' with respect to line length and CRLF semantics and thus seems more suitable. Link: https://datatracker.ietf.org/doc/html/rfc2046#section-5.2.1 Link: https://lists.sr.ht/~rjarry/aerc-devel/%3CD48A6YOQOXRG.3KKB6UTGMT8LY@maslowski.xyz%3E Reported-by: Piotr Masłowski <piotr@maslowski.xyz> Reported-by: inwit <inwit@sindominio.net> Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* textinput: make completions run async with cancellationTim Culverhouse2024-10-241-17/+37
| | | | | | | | | | | | | | | | | | 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: read the history file from XDG_STATE_HOMETristan Partin2024-10-241-0/+13
| | | | | | | | | | | 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>
* completion: display descriptions next to choicesRobin Jarry2024-10-233-27/+46
| | | | | | | | | | | | | | | | | | | | | | | | | 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>
* gpg: do not sign with untrusted keysMarcin Serwin2024-10-236-38/+82
| | | | | | | | | | | During encryption gpg was ignoring trust model of the user in favor of always using the insecure "always". This change removes this override and adds a helpful message if a user tries to encrypt a message with an untrusted key. To revert to the previous behavior users can add "trust-model always" to their gpg.conf file (default ~/.gnupg/gpg.conf). Signed-off-by: Marcin Serwin <marcin@serwin.dev> Acked-by: Tim Culverhouse <tim@timculverhouse.com>
* xdg: determine user runtime directory in a robust mannerRalph Seichter2024-10-121-1/+14
| | | | | | | | | | | | | Instead of relying on systemd-style /run/user/NNN directories, which are unavailable on platforms like OpenRC Gentoo Linux, create either the per user /tmp/aerc-NNN directory, or fall back to using /tmp as a last resort. Changelog-fixed: Failure to create IPC socket on Gentoo. Signed-off-by: Ralph Seichter <aerc@seichter.de> Reviewed-by: Jason Cox <me@jasoncarloscox.com> Acked-by: Robin Jarry <robin@jarry.cc>
* crypto: add pinentry support to gpgKoni Marti2024-10-123-0/+14
| | | | | | | | | Add pinentry support to GPG for signing, enrypting and decrypting messages. Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* aerc: support terminal-based pinentry programsKoni Marti2024-10-123-0/+129
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Support terminal-based pinentry programs. Suspend vaxis before running the command that can trigger a pinentry call. Provide the proper tty in the GPG_TTY environment variable (and set a TERM variable if not provided; this is necessary for pinentry-curses). Finally, resume vaxis. To enable terminal-based pinentry support, you have to set [general] use-terminal-pinentry = true in your aerc.conf. Any GUI-based pinentry programs will work the same as before if this option is not set to true. To test pinentry-tty, add the following to your ~/.gnupg/gpg-agent.conf: pinentry-program /usr/bin/pinentry-tty and kill all running gpg-agents: $ killall gpg-agent Fixes: https://todo.sr.ht/~rjarry/aerc/202 Changelog-fixed: Terminal-based pinentry programs (e.g. `pinentry-curses`) now work properly. Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* templates/quote: only prefix quoted lines with '>'Tim Culverhouse2024-09-201-1/+5
| | | | | | | | | | | | | | | | Prefix all quoted lines with depth > 1 with '>'. Quoted lines of depth 1 are quoted with "> ". This follows conventions of mailing lists which collapse quote depths without spaces. For example: >>> Quote depth 3 > Quote depth 1 >> Quote depth 2 Changelog-changed: Template function `quote` only prefixes with a space if at quote depth 1. Requested-by: Isaac Freund <mail@isaacfreund.com> Signed-off-by: Tim Culverhouse <tim@timculverhouse.com> Acked-by: Robin Jarry <robin@jarry.cc>
* lint: update golangci-lint to 1.61.0Tristan Partin2024-09-201-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | golangci-lint 1.56 does not work with go 1.23. It causes obscure errors: [linters_context/goanalysis] buildir: panic during analysis: Cannot range over: func(yield func(K, V) bool), goroutine 4743 [running]: runtime/debug.Stack() /usr/lib/go/src/runtime/debug/stack.go:26 +0x5e github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*action).analyzeSafe.func1() /home/build/go/pkg/mod/github.com/golangci/golangci-lint@v1.56.1/pkg/golinters/goanalysis/runner_action.go:104 +0x5a panic({0x164b260?, 0xc00669b4a0?}) /usr/lib/go/src/runtime/panic.go:785 +0x132 honnef.co/go/tools/go/ir.(*builder).rangeStmt(0xc000051910, 0xc00a29cf00, 0xc009bf55c0, 0x0, {0x1af1960, 0xc009bf55c0}) /home/build/go/pkg/mod/honnef.co/go/tools@v0.4.6/go/ir/builder.go:2214 +0x894 honnef.co/go/tools/go/ir.(*builder).stmt(0xc000051910, 0xc00a29cf00, {0x1af6970?, 0xc009bf55c0?}) /home/build/go/pkg/mod/honnef.co/go/tools@v0.4.6/go/ir/builder.go:2427 +0x20a honnef.co/go/tools/go/ir.(*builder).stmtList(...) /home/build/go/pkg/mod/honnef.co/go/tools@v0.4.6/go/ir/builder.go:847 honnef.co/go/tools/go/ir.(*builder).stmt(0xc000051910, 0xc00a29cf00, {0x1af6880?, 0xc004f52ed0?}) /home/build/go/pkg/mod/honnef.co/go/tools@v0.4.6/go/ir/builder.go:2385 +0x1415 honnef.co/go/tools/go/ir.(*builder).buildFunction(0xc000051910, 0xc00a29cf00) /home/build/go/pkg/mod/honnef.co/go/tools@v0.4.6/go/ir/builder.go:2497 +0x417 honnef.co/go/tools/go/ir.(*builder).buildFuncDecl(0xc000051910, 0xc00622eea0, 0xc004f52f00) /home/build/go/pkg/mod/honnef.co/go/tools@v0.4.6/go/ir/builder.go:2534 +0x189 honnef.co/go/tools/go/ir.(*Package).build(0xc00622eea0) /home/build/go/pkg/mod/honnef.co/go/tools@v0.4.6/go/ir/builder.go:2638 +0xb46 sync.(*Once).doSlow(0xc009b81260?, 0xc009bf5bc0?) /usr/lib/go/src/sync/once.go:76 +0xb4 sync.(*Once).Do(...) /usr/lib/go/src/sync/once.go:67 honnef.co/go/tools/go/ir.(*Package).Build(...) /home/build/go/pkg/mod/honnef.co/go/tools@v0.4.6/go/ir/builder.go:2556 honnef.co/go/tools/internal/passes/buildir.run(0xc000cf61a0) /home/build/go/pkg/mod/honnef.co/go/tools@v0.4.6/internal/passes/buildir/buildir.go:86 +0x18b github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*action).analyze(0xc002d77d70) /home/build/go/pkg/mod/github.com/golangci/golangci-lint@v1.56.1/pkg/golinters/goanalysis/runner_action.go:190 +0x9cd github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*action).analyzeSafe.func2() /home/build/go/pkg/mod/github.com/golangci/golangci-lint@v1.56.1/pkg/golinters/goanalysis/runner_action.go:112 +0x17 github.com/golangci/golangci-lint/pkg/timeutils.(*Stopwatch).TrackStage(0xc0007a5c70, {0x1859190, 0x7}, 0xc001c28f48) /home/build/go/pkg/mod/github.com/golangci/golangci-lint@v1.56.1/pkg/timeutils/stopwatch.go:111 +0x44 github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*action).analyzeSafe(0xc00212f680?) /home/build/go/pkg/mod/github.com/golangci/golangci-lint@v1.56.1/pkg/golinters/goanalysis/runner_action.go:111 +0x6e github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*loadingPackage).analyze.func2(0xc002d77d70) /home/build/go/pkg/mod/github.com/golangci/golangci-lint@v1.56.1/pkg/golinters/goanalysis/runner_loadingpackage.go:80 +0xa5 created by github.com/golangci/golangci-lint/pkg/golinters/goanalysis.(*loadingPackage).analyze in goroutine 3468 /home/build/go/pkg/mod/github.com/golangci/golangci-lint@v1.56.1/pkg/golinters/goanalysis/runner_loadingpackage.go:75 +0x1e9 Update golangci-lint to 1.61.0 that works with go 1.23. It has new checkers that report errors that we need to fix: lib/crypto/gpg/gpgbin/gpgbin.go:226:22: printf: non-constant format string in call to fmt.Errorf (govet) return fmt.Errorf(strings.TrimPrefix(line, "[GNUPG:] ")) ^ worker/imap/observer.go:142:21: printf: non-constant format string in call to fmt.Errorf (govet) Error: fmt.Errorf(errMsg), ^ app/dirlist.go:409:5: S1009: should omit nil check; len() for []string is defined as zero (gosimple) if dirlist.dirs == nil || len(dirlist.dirs) == 0 { ^ app/dirtree.go:181:5: S1009: should omit nil check; len() for []*git.sr.ht/~rjarry/aerc/worker/types.Thread is defined as zero (gosimple) if dt.list == nil || len(dt.list) == 0 || dt.countVisible(dt.list) < y+dt.Scroll() { ^ app/authinfo.go:30:34: printf: non-constant format string in call to (*git.sr.ht/~rjarry/aerc/lib/ui.Context).Printf (govet) ctx.Printf(0, 0, defaultStyle, text) ^ app/authinfo.go:34:27: printf: non-constant format string in call to (*git.sr.ht/~rjarry/aerc/lib/ui.Context).Printf (govet) ctx.Printf(0, 0, style, text) ^ app/authinfo.go:62:34: printf: non-constant format string in call to (*git.sr.ht/~rjarry/aerc/lib/ui.Context).Printf (govet) x += ctx.Printf(x, 0, style, text) ^ Pretty much all of these errors are us passing non-const format strings to various methods. In C land, this is a large security issue. I would assume the same stands in Go. Thank you golangci-lint! Link: https://builds.sr.ht/~rjarry/job/1332376#task-validate-500 Signed-off-by: Tristan Partin <tristan@partin.io> Acked-by: Robin Jarry <robin@jarry.cc>
* treewide: replace uint32 uids with opaque stringsRobin Jarry2024-08-2812-189/+132
| | | | | | | | | | | | | | | | | Add a new models.UID type (an alias to string). Replace all occurrences of uint32 being used as message UID or thread UID with models.UID. Update all workers to only expose models.UID values and deal with the conversion internally. Only IMAP needs to convert these to uint32. All other backends already use plain strings as message identifiers, in which case no conversion is even needed. The directory tree implementation needed to be heavily refactored in order to accommodate thread UID not being usable as a list index. Signed-off-by: Robin Jarry <robin@jarry.cc> Tested-by: Inwit <inwit@sindominio.net> Tested-by: Tim Culverhouse <tim@timculverhouse.com>
* patch: add auto-switch optionKoni Marti2024-08-242-0/+103
| | | | | | | | | | | | | | | | | | | Add an auto-switch option that changes the project of the patch manager based on the subject line of a message if it contains a '[PATCH <project>]' segment. A subject line with '[PATCH aerc v2]' would switch to the 'aerc' project if that project is available in the patch manager. The auto switching can be activated per account by adding 'pama-auto-switch = true' to your account config. Implements: https://todo.sr.ht/~rjarry/aerc/226 Changelog-added: Auto-switch projects based on the message subject for the :patch command. Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* gpg: fix signed message encodingKoni Marti2024-08-241-3/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Fix the content encoding for GPG-signed messages. To remove the Mime-Version header field for the signed message part, the raw message is parsed with go-message. go-message.Read(), however, decodes the message body as well (i.e. from quoted-printable to UTF8 depending on the Content-Transfer-Encoding header). This means that the msg.Body field now contains the decoded message (it is no longer encoded as quoted-printable). We never encode the message back to the proper Content-Transfer-Encoding. To fix this, use net/mail.ReadMessage() to parse the headers and to not decode the message body. To verify the issue, send a signed message with the following text: "19+1=20!" The message will be properly signed, but the text is wrong; it shows "19+1 !"; instead it should read "19+1=3D20!". Fixes: 5e443bce ("gpg: fix mime-version header position") References: https://todo.sr.ht/~rjarry/aerc/79 Signed-off-by: Koni Marti <koni.marti@gmail.com> Tested-by: Jens Grassel <jens@wegtam.com> Acked-by: Robin Jarry <robin@jarry.cc>
* store: extract configure logicKoni Marti2024-08-201-50/+52
| | | | | | | | | | Extract a function to configure the message store from its constructor to reconfigure the store when the data changes. Signed-off-by: Koni Marti <koni.marti@gmail.com> Tested-by: Inwit <inwit@sindominio.net> Acked-by: Robin Jarry <robin@jarry.cc>
* tabs: update ui config in any tabKoni Marti2024-08-201-18/+17
| | | | | | | | | Update UI config in tabs. Signed-off-by: Koni Marti <koni.marti@gmail.com> Tested-by: Inwit <inwit@sindominio.net> Acked-by: Robin Jarry <robin@jarry.cc>
* log: handle config reloadKoni Marti2024-08-201-1/+37
| | | | | | | | | | | | Prepare the logging system for a config file reload. Make sure that we never close os.Stdout but only log file descriptors. Note that if you started aerc by redirecting its output into a specific file, this cannot be changed by a config reload. Signed-off-by: Koni Marti <koni.marti@gmail.com> Tested-by: Inwit <inwit@sindominio.net> Acked-by: Robin Jarry <robin@jarry.cc>
* templates: add a template for forwaded messagesinwit2024-08-201-0/+10
| | | | | | | | | | | Add a {{.IsForwarded}} template to tell if a message has been forwarded or not. Changelog-added: Forwarded messages can be identified with the {{.IsForwarded}} template. Signed-off-by: inwit <inwit@sindominio.net> Acked-by: Robin Jarry <robin@jarry.cc>
* forward: allow forwarded flag to be setinwit2024-08-201-0/+11
| | | | | | | | | | | | Usually, a MUA sets a flag for messages that have been forwarded, but this is currently not the case for aerc. Consider the forwarded flag and prepare aerc to set it everytime the :forward command is called and ends successfully. Changelog-added: The :forward command now sets the forwarded flag. Signed-off-by: inwit <inwit@sindominio.net> Acked-by: Robin Jarry <robin@jarry.cc>
* cryptoutil: implement cleartext functionKoni Marti2024-08-201-0/+69
| | | | | | | | | | | | | | | Implement a cleartext function in the cryptoutil package to decrypt an encrypted message to cleartext and construct a valid rfc2822 message. The headers from the decrypt message body will be merged with the original headers to create a fully decrypted message. Implements: https://todo.sr.ht/~rjarry/aerc/238 Signed-off-by: Koni Marti <koni.marti@gmail.com> Tested-by: Jens Grassel <jens@wegtam.com> Reviewed-by: Tim Culverhouse <tim@timculverhouse.com> Acked-by: Robin Jarry <robin@jarry.cc>
* go: bump minimal version to 1.21 and handle deprecationsBence Ferdinandy2024-08-201-2/+3
| | | | | | | | | | | | | Go 1.18 is already EOL. go-maildir v0.5.0 requires go 1.20 at least. Since go 1.20 is also EOL, bump the minimum required go version to the first still supported version which is 1.21. Go 1.20 deprecated Seed and Read in math/rand. Update the code accordingly. Changelog-deprecated: Support for go 1.20 and older. Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Acked-by: Robin Jarry <robin@jarry.cc>
* log: explain why the signature command failedTristan Partin2024-08-201-0/+5
| | | | | | | It wasn't previously apparent why the command failed. Signed-off-by: Tristan Partin <tristan@partin.io> Acked-by: Robin Jarry <robin@jarry.cc>
* template: pass account and folder names to signature commandTristan Partin2024-08-201-0/+4
| | | | | | | | | This can help to dynamically determine what signature you want. Changelog-added: `AERC_ACCOUNT` and `AERC_FOLDER` are now available in the signature command environment. Signed-off-by: Tristan Partin <tristan@partin.io> Acked-by: Robin Jarry <robin@jarry.cc>
* view-message: add option to view message in background tabAron Lebani2024-08-041-2/+6
| | | | | | | | | | | | | | | Add a -b flag to the :view command to open messages in a background tab instead of automatically switching to the new tab after opening. This is similar to opening browser tabs in the background. More generally, adds a new function app.NewBackgroundTab so that it is possible to enable other tabs to be opened in the background in the future. Implements: https://todo.sr.ht/~rjarry/aerc/266 Changelog-added: Add `-b` flag to the `:view` command to open messages in a background tab. Signed-off-by: Aron Lebani <aron@lebani.dev> Acked-by: Robin Jarry <robin@jarry.cc>
* hooks: add logging for STDOUT and STDERRBence Ferdinandy2024-08-041-1/+10
| | | | | | | | | | Currently the only feedback we have from hooks is the error code. Log STDOUT on loglevel TRACE and log STDERR on loglevel ERROR if the command exists with an error. Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Acked-by: Robin Jarry <robin@jarry.cc>
* reply: allow copying to current folderRobin Jarry2024-08-033-3/+7
| | | | | | | | | Add a new copy-to-replied setting in accounts.conf to copy sent replies to the same folder than their replied message. Requested-by: Tristan Partin <tristan@partin.io> Signed-off-by: Robin Jarry <robin@jarry.cc> Tested-by: Tristan Partin <tristan@partin.io>
* reply: handle the Sender headerBence Ferdinandy2024-08-031-0/+1
| | | | | | | | | | | | | | | | | | | | | | Sometimes emails will have a Sender: header, that is different from the From: header. The only use of this in the wild I have seen to date is when meeting invitation is forwarded by somebody. The From: header will be the person organising the meeting, and the Sender: will be the person forwarding. Naturally, when one replies (e.g. with on accept), it should go to the meeting oragniser, but sometimes one would want to include the Sender in such a reply. When executing :reply determine the To: address in order of Reply-To:, From:, Sender:. When executing :reply -a, include the Sender: in Cc:. Implements: https://todo.sr.ht/~rjarry/aerc/259 Link: https://www.rfc-editor.org/rfc/rfc4021#section-2.1.3 Changelog-added: Replying to all will include the Sender in Cc. Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Reviewed-by: Tim Culverhouse <tim@timculverhouse.com> Reviewed-by: Tristan Partin <tristan@partin.io> Acked-by: Robin Jarry <robin@jarry.cc>
* templates: add {{.AccountFrom}} templateBence Ferdinandy2024-08-031-0/+7
| | | | | | | | | | Add template variable to access the current account's From address. Implements: https://todo.sr.ht/~rjarry/aerc/150 Changelog-added: New `{{.AccountFrom}}` template variable. Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Tested-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* templates: add head and tail functionsBence Ferdinandy2024-08-032-0/+54
| | | | | | | | | | | | | | | Add head and tail functions to get beginning or ends of strings. E.g.: {{"hello" | head 2}} will return "he" {{"hello" | tail 2}} will return "lo" Implements: https://todo.sr.ht/~rjarry/aerc/220 Changelog-added: New `head` and `tail` templates functions for strings. Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Reviewed-by: Moritz Poldrack <moritz@poldrack.dev> Acked-by: Robin Jarry <robin@jarry.cc>
* ui: add :redraw commandTim Culverhouse2024-08-031-1/+13
| | | | | | | | | | | Add a :redraw command to force a repaint of the entire screen. Changelog-added: New `:redraw` command to force a repaint of the screen. Requested-by: Remko Tronçon <r@mko.re> Signed-off-by: Tim Culverhouse <tim@timculverhouse.com> Tested-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* smtp: take smtp-domain into account for tls connectionsRobin Jarry2024-07-151-2/+9
| | | | | | | | | | | | | smtp-domain is ignored when using smtps:// transport. It is only configured for clear text and STARTTLS connections. Also use it for TLS encrypted connections. Fixes: c10cb370bb94 ("config: add option for SMTP HELO/EHLO local domain") Changelog-fixed: `smtp-domain` is now properly taken into account for TLS connections. Signed-off-by: Robin Jarry <robin@jarry.cc> Reviewed-by: Tristan Partin <tristan@partin.io>
* rfc822: make header parsing less pedanticRobin Jarry2024-07-152-66/+45
| | | | | | | | | | | | | When receiving invalid headers, just log the errors and move on with our life. When failing to decode addresses, do whatever is possible to at least make the message readable. Changelog-fixed: Aerc is now less pedantic about invalid headers for the maildir and notmuch backends. Signed-off-by: Robin Jarry <robin@jarry.cc> Tested-by: Bence Ferdinandy <bence@ferdinandy.com> Tested-by: Vitaly Ovchinnikov <v@ovch.ru> Tested-by: inwit <inwit@sindominio.net>
* ui: make textinput grapheme awareTim Culverhouse2024-07-022-22/+37
| | | | | | | | | | | | | | | | | The textinput widget operated on a slice of runes, and naively assumed a rune was a "character". When deleting or navigating the cursor through text which contains multi-codepoint characters (such as emoji), the cursor index could desync and cause panics. Use a slice of vaxis.Characters instead of runes to more accurately reflect the index state of the cursor with respect to characters. Fixes: https://todo.sr.ht/~rjarry/aerc/263 Reported-by: Bence Ferdinandy <bence@ferdinandy.com> Signed-off-by: Tim Culverhouse <tim@timculverhouse.com> Tested-by: Bence Ferdinandy <bence@ferdinandy.com> Reviewed-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* rfc822: be liberal with invalid address headersRobin Jarry2024-07-022-0/+61
| | | | | | | | | | | | | | | | | | | | | | | | Some email clients format email addresses with quotes around B encoded names. E.g.: "=?utf-8?B?U21pZXRhbnNraSwgV29qY2llY2ggVGFkZXVzeiBpbiBUZWFtcw==?=" This seems non standard. I tried reading the multiple RFCs that describe the MIME headers encoding but could not find any precise answer to determine if adding quotes around encoded words is valid or not. In any case, ParseAddressList completely ignores any encoding when it encounters a double quote. When that happens, try to detect it and force decoding a second time after the quotes have been removed. Link: https://datatracker.ietf.org/doc/html/rfc2045#section-3 Link: https://datatracker.ietf.org/doc/html/rfc2047#section-2 Link: https://datatracker.ietf.org/doc/html/rfc822#section-3.3 Reported-by: Bence Ferdinandy <bence@ferdinandy.com> Signed-off-by: Robin Jarry <robin@jarry.cc> Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
* imap: report errors from serverRobin Jarry2024-07-011-2/+4
| | | | | | | | | | | | Avoid eternal spinner on the message list when the imap server advertises some message UIDs but fails to provide their headers when aerc asks from them. When an error occurs, or if some UIDs are not returned, make sure to report the errors to the message list UI. Signed-off-by: Robin Jarry <robin@jarry.cc> Reviewed-by: Tristan Partin <tristan@partin.io>
* rfc822: properly parse address listsRobin Jarry2024-06-291-10/+7
| | | | | | | | | | | | | | | | h.Text() parses blobs of encoded text without taking into account specific handling for email addresses. h.AddressList(key) uses mail.ParseAddressList(h.Get(key)) already deals with charsets and quoted-printable stuff. Pass it the raw header value. In some cases, mail.ParseAddressList will return a list of addresses *and* an UnknownCharset error. In this specific case, ignore the error. Fixes: https://todo.sr.ht/~rjarry/aerc/257 Reported-by: Inwit <inwit@sindominio.net> Signed-off-by: Robin Jarry <robin@jarry.cc> Tested-by: Inwit <inwit@sindominio.net> Reviewed-by: Tristan Partin <tristan@partin.io>
* threadbuilder: allow threading by subjectRobin Jarry2024-06-252-10/+28
| | | | | | | | | | | | If no match were found in the References and In-Reply-To headers, allow threading by looking at subjects. This behaviour is disabled by default. Add a setting to enable it. Changelog-added: Allow fallback to threading by subject with `[ui].threading-by-subject`. Signed-off-by: Robin Jarry <robin@jarry.cc> Tested-by: Matěj Cepl <mcepl@cepl.eu>
* threadbuilder: show siblings even when no parent foundKoni Marti2024-06-252-21/+33
| | | | | | | | | | | | | | | Show all threading associations even when not all nodes are present. Indicate if a thread is incomplete, i.e. misses a direct parent node. Use the `msglist_thread_orphan.fg=red` styleobject in your stylesheet to indicate whether a messsage has a missing parent. Also use a different thread prefix ("┬─" instead of "├─") not to confuse them with regular threads that have a visible parent. Signed-off-by: Koni Marti <koni.marti@gmail.com> Signed-off-by: Robin Jarry <robin@jarry.cc> Tested-by: Matěj Cepl <mcepl@cepl.eu>
* hooks: add AERC_ACCOUNT_BACKEND to hooks with AERC_ACCOUNTBence Ferdinandy2024-06-056-0/+11
| | | | | | | | | | It can be good to know the backend used for an account in a hook. Add this information to all hooks that already pass the account name along. Changelog-added: Added `AERC_ACCOUNT_BACKEND` to hooks with `AERC_ACCOUNT`. Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Acked-by: Robin Jarry <robin@jarry.cc>
* templates: add .AccountBackendBence Ferdinandy2024-06-051-0/+7
| | | | | | | | | | | It's useful to know what the current account's backend is, especially if one has multiple configs where the same account name might use a different backend. Add AccountBackend to templates. Changelog-added: Added `{{.AccountBackend}}` to templates. Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Acked-by: Robin Jarry <robin@jarry.cc>
* hooks: add AERC_FOLDER_ROLE to hooks with AERC_FOLDERBence Ferdinandy2024-06-054-0/+8
| | | | | | | | | | It's logical to pass this information as well, when we pass a folder name. Changelog-added: Added `AERC_FOLDER_ROLE` to hooks that have `AERC_FOLDER`. Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Acked-by: Robin Jarry <robin@jarry.cc>
* ui: add select-last-message optionKoni Marti2024-05-281-1/+8
| | | | | | | | | | | | | | Add a [ui].select-last-message option to position the cursor at the bottom of the message list view. Fixes: https://todo.sr.ht/~rjarry/aerc/254 Changelog-added: Add `[ui].select-last-message` option to position cursor at the bottom of the view. Suggested-by: Bence Ferdinandy <bence@ferdinandy.com> Requested-by: Tomasz Kramkowski <tomasz@kramkow.ski> Signed-off-by: Koni Marti <koni.marti@gmail.com> Tested-by: Tomasz Kramkowski <tomasz@kramkow.ski> Acked-by: Robin Jarry <robin@jarry.cc>
* msgstore: restore the directoryChange bool to fix new message bellKarel Balej2024-05-091-0/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In 24eab0f5ef63 the condition under which the triggerDirectoryChange callback is executed was changed so that it would now only run if there were new messages in the currently scrolled into view part of the message list whereas previously it ran for new messages anywhere in the list. The motivation for this was to make the mail-received hook work even when the tab of the receiving account is not currently focused by fetching the new message's/s' headers needed for the hook to execute based on what changed in the scrolled into part of the list. This limitation is needed because apparently we don't currently have a better way to recognize new messages other than comparing the list of UIDs provided by the worker and that kept by the store. My current understanding is that we cannot remove the scroll view limit because then we would be fetching headers for all messages in the directory which can be a somewhat intensive operation. However we can disregard the view limit for the bell as that does not require the headers: it only cares about that something has changed. It is noteworthy that the bell is rung on aerc startup: I assume that this occurs with the initial load of the message store for every account when the else branch where directoryChange is set to true inevitably executes. Overall, this patch is more of a workaround than a proper fix: the ideal situation would be if we were able to fetch headers for new messages independently of the scroll status. However as this is how this was before, it should be suitable as a temporary solution. There are also further problems here: currently we have triggerNewEmail and triggerDirectoryChange callbacks which are both supposed to run when new mail is received, the latter only implicitly. And yet they both use a different mechanism and thus execute under different circumstances. It would be ideal to move the bell into the new mail trigger and get rid of the directory change one as it is otherwise unused. However this is not done here because for some setups the new mail trigger does not run until the tab is focused which is what the aforementioned commit was meant to fix but apparently succeeded in doing so only partially. The directoryChange trigger does not have this drawback and thus should be kept until the issue is resolved for all setups. Also note that for instance for O365 mail the bell still doesn't work properly as there new mail only appears in the store after the given folder is reopened (:prev-folder :next-folder) and the bell is thus rung only then. Fixes: 24eab0f5ef63 ("msglist: fetch headers even when not focused") Fixes: https://todo.sr.ht/~rjarry/aerc/249 Changelog-fixed: Restore previous behaviour of the new message bell which was broken in the last two releases for at least some setups. Signed-off-by: Karel Balej <balejk@matfyz.cz> Acked-by: Robin Jarry <robin@jarry.cc>
* attach: use absolute paths instead of relativeBence Ferdinandy2024-04-141-1/+2
| | | | | | | | | | | | Sometimes it is easier to change folders when adding attachments, but currently we store relative paths, which doesn't work with this. Add the absolute paths when attaching files. Replace the current user home dir with ~ to make it prettier in the UI. Implements: https://todo.sr.ht/~rjarry/aerc/134 Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Acked-by: Robin Jarry <robin@jarry.cc>
* hooks: add flag-changedBence Ferdinandy2024-04-142-1/+49
| | | | | | | | | Add the flag-changed hook. References: https://todo.sr.ht/~rjarry/aerc/136 Changelog-added: New `flag-changed` hook. Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Acked-by: Robin Jarry <robin@jarry.cc>
* hooks: add tag-modifiedBence Ferdinandy2024-04-142-2/+37
| | | | | | | | | Add the tag-modified hook for notmuch and JMAP accounts. References: https://todo.sr.ht/~rjarry/aerc/136 Changelog-added: New `tag-modified` hook for notmuch and JMAP accounts. Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Acked-by: Robin Jarry <robin@jarry.cc>
* compose,viewer: do not always wrap people names in quotesRobin Jarry2024-04-131-8/+6
| | | | | | | | | | | | | | | | | | | | | | | | | Currently, names of recipients in From, To, Cc and Bcc headers are (almost) always wrapped in quotes. Even if they are pure ASCII and contain one upper case letter. E.g.: From: "Foo" <foo@baz.org> There is no valid reason to add these quotes unless the name contains special characters as specified by RFC 5322, section 3.2.3: specials = "(" / ")" / ; Special characters that do "<" / ">" / ; not appear in atext "[" / "]" / ":" / ";" / "@" / "\" / "," / "." / DQUOTE Adapt the check accordingly. Link: https://datatracker.ietf.org/doc/html/rfc5322#section-3.2.3 Signed-off-by: Robin Jarry <robin@jarry.cc> Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
* compose: explicitly identify converted text/* partsRobin Jarry2024-04-131-6/+15
| | | | | | | | | | | | | | | | | | | | | When running :accept, an error is displayed on the review screen: text/calendar error: no command defined for mime/type When running :multipart text/xxx, its contents are not specified. They are regenerated every time the review screen is displayed. When running :accept, a text/calendar part is added with actual contents. Update the Part object to hold a boolean initialized when first being created. If body is nil, identify the part as "Converted" and update its contents every time the review screen is displayed. When body is not nil but contains text (e.g. when running :accept), identify the part as *not* converted and ignore the conversion step. Fixes: cbcabfafaab2 ("compose: allow writing multipart/alternative messages") Reported-by: Inwit <inwit@sindominio.net> Signed-off-by: Robin Jarry <robin@jarry.cc> Tested-by: Inwit <inwit@sindominio.net>
* vaxis: fix panic trace print on stderrRobin Jarry2024-04-131-0/+1
| | | | | | | | | | | | | | | | | | By default, vaxis tries to open stderr, stdout and stdin in that order and uses the first one as its TTY file descriptor. Upon exit, vaxis.Close() closes that file descriptor. When aerc panics, our panic handler calls UICleanup() which is an alias for vaxis.Close(). This effectively makes os.Stderr unusable and all error messages are written to a closed file descriptor. This also break the regular go runtime panic() handler which prints on stderr as well. Use an explicit /dev/tty path instead of stderr to keep it open. Fixes: 6eff242090dc ("ui: so long tcell") Signed-off-by: Robin Jarry <robin@jarry.cc> Tested-by: Bence Ferdinandy <bence@ferdinandy.com> Reviewed-by: Tim Culverhouse <tim@timculverhouse.com>
* ipc: disable IPC completely when disable-ipc=trueJason Cox2024-04-131-4/+0
| | | | | | | | | | | | | | | Truly disable IPC when disable-ipc is set to true in aerc.conf. Don't run commands over IPC and don't start an IPC server. Being able to disable IPC in the config is useful because it allows making aerc open mailto links in a new instance without modifying the aerc.desktop file. There are of course potential security benefits as well. Changelog-changed: The `disable-ipc` option in `aerc.conf` completely disables IPC. Signed-off-by: Jason Cox <me@jasoncarloscox.com> Acked-by: Robin Jarry <robin@jarry.cc>