13 Commits

Author SHA1 Message Date
Robin Jarry
0ec957dfba send: fix double close and swallowed write error
The deferred w.w.Close() caused the underlying writer to always be
closed twice: once via defer and again with the explicit return at
the end. For the SMTP sender this results in calling Quit() on an
already-closed connection.

Remove the defer and instead call w.w.Close() explicitly in each
error path so that the connection is closed exactly once.

Also fix a write error that was silently discarded (return nil instead
of return err).

Fixes: cb1c4c9c62 ("send: ensure crlf line endings")
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: septante <septante@memeware.net>
Acked-by: septante <septante@memeware.net>
2026-02-13 08:53:30 +01:00
Robin Jarry
f4a31ca653 smtp: fix connection leak
newSmtpSender() returned the io.WriteCloser from conn.Data() instead of
the smtpSender wrapper. Callers would only close the data writer without
ever calling Quit() or Close() on the underlying SMTP connection,
leaking it.

Return the smtpSender object so that its Close() method properly
terminates the SMTP session. Also send QUIT before closing since some
servers hang when the client disconnects without it. If Quit() fails,
fall back to a raw Close().

Fixes: 67923707ff ("Refactor send command")
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: septante <septante@memeware.net>
Acked-by: septante <septante@memeware.net>
2026-02-13 08:53:30 +01:00
Robin Jarry
9a823672f9 messages: generalize cancellation context
Move the cancellation context from individual message types to the base
Message struct. Previously, only a few message types (OpenDirectory,
FetchDirectoryContents, FetchDirectoryThreaded, SearchDirectory,
FetchMessageHeaders, FetchMessageFlags) had a Context field, requiring
special handling in workers.

Now all worker messages carry a context through the base Message type,
set via PostAction's new first parameter. Workers access it uniformly
via the Context() method which returns context.Background() when unset.

Add a Close() method to MessageStoreView that cancels pending fetch
operations when the message viewer is closed, preventing wasted work on
messages the user is no longer viewing.

Signed-off-by: Robin Jarry <robin@jarry.cc>
Reviewed-by: Simon Martin <simon@nasilyan.com>
2026-02-09 14:46:27 +01:00
Robin Jarry
018e6f81f4 lib: consolidate SASL authentication code
SASL and OAuth2 authentication logic was duplicated across the IMAP
worker and the SMTP sender code. Both implementations handled XOAUTH2,
OAUTHBEARER, and token caching independently, making maintenance
difficult and bug fixes error-prone.

Move this shared logic into lib/auth where it can be reused by all
backends. The IMAP worker no longer needs its own OAuth structs and
configuration parsing since it can now rely on the common
implementation also used by the SMTP sender.

Signed-off-by: Robin Jarry <robin@jarry.cc>
Reviewed-by: Simon Martin <simon@nasilyan.com>
2026-02-09 14:46:27 +01:00
Moritz Poldrack
1d6eb2dc58 smtp: add option to request DSN for successful deliveries
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>
2025-03-09 00:40:38 +01:00
Robin Jarry
cb1c4c9c62 send: ensure crlf line endings
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>
2025-01-07 19:20:44 +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
Robin Jarry
3c9ad93801 completion: display descriptions next to choices
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>
2024-10-23 10:22:51 +02:00
Robin Jarry
954c812d84 reply: allow copying to current folder
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>
2024-08-03 20:19:37 +02:00
Robin Jarry
d960b8d2ca smtp: take smtp-domain into account for tls connections
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: c10cb370bb ("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>
2024-07-15 22:39:12 +02:00
Robin Jarry
7c789624d7 mod: update all dependencies
Patch produced with the following commands:

	go mod edit -dropreplace=golang.org/x/crypto
	go get -t -u
	go mod tidy

I dropped the replace of x/crypto. The only use for the fork from
ProtonMail is for openpgp which has been deprecated by the official
implementation. And aerc explicitly uses the correct import path where
needed.

go-smtp update was a bit harsh. The API was changed completely.

Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
2024-04-02 22:21:50 +02:00
Karel Balej
e8a6e8316a lib: add function to obtain Message-ID hostname
Make the function already present in app/compose.go reusable while also
changing its signature for it not to require involvement of a Composer
instance.

Signed-off-by: Karel Balej <balejk@matfyz.cz>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-02-12 23:01:55 +01:00
Karel Balej
3553e4f271 send: move code to lib for reuse
Move the code which handles the preparation of a sender into which the
message can be written into lib to allow for reuse. Also hide the
sending backend a bit more from the `:send` command code by introducing
a NewSender function which determines which backend should be used and
invokes the appropriate sender factory function.

Rename send() to sendHelper() to avoid collision.

Signed-off-by: Karel Balej <balejk@matfyz.cz>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-02-12 22:58:40 +01:00