aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarel Balej <balejk@matfyz.cz>2024-01-30 20:11:26 +0100
committerRobin Jarry <robin@jarry.cc>2024-02-12 22:56:16 +0100
commit324e620c5a62fee07970c436f792c7383a3fb1e5 (patch)
tree7bf519252f9fc74c4490dd5e95a1310ebbf909b5
parent1bc295580e0b2caf9349226f46f4ea29c7b12a7a (diff)
downloadaerc-324e620c5a62fee07970c436f792c7383a3fb1e5.tar.gz
jmap: set explicit sender and recipients
JMAP is able to automatically determine sender and recipients based on the message headers after it is submitted for sending. However this means that it is not possible to send a message with the From header not matching the account with this approach (or to send the message to recipients not listed in the headers). Luckily, JMAP allows setting the envelope containing the envelope sender and recipients manually. Modify the code to do so. Also bump go-jmap to include a fix needed for this to work. Signed-off-by: Karel Balej <balejk@matfyz.cz> Acked-by: Robin Jarry <robin@jarry.cc>
-rw-r--r--commands/compose/send.go8
-rw-r--r--go.mod2
-rw-r--r--go.sum4
-rw-r--r--worker/jmap/send.go22
-rw-r--r--worker/types/messages.go3
5 files changed, 21 insertions, 18 deletions
diff --git a/commands/compose/send.go b/commands/compose/send.go
index 25df174d..65b501b4 100644
--- a/commands/compose/send.go
+++ b/commands/compose/send.go
@@ -182,7 +182,7 @@ func send(composer *app.Composer, header *mail.Header, uri *url.URL, domain stri
case "smtp", "smtp+insecure", "smtps":
sender, err = newSmtpSender(protocol, auth, uri, domain, from, rcpts)
case "jmap":
- sender, err = newJmapSender(composer, header)
+ sender, err = newJmapSender(composer.Worker(), from, rcpts)
case "":
sender, err = newSendmailSender(uri, rcpts)
default:
@@ -519,13 +519,13 @@ func connectSmtps(host string) (*smtp.Client, error) {
}
func newJmapSender(
- composer *app.Composer, header *mail.Header,
+ worker *types.Worker, from *mail.Address, rcpts []*mail.Address,
) (io.WriteCloser, error) {
var writer io.WriteCloser
done := make(chan error)
- composer.Worker().PostAction(
- &types.StartSendingMessage{Header: header},
+ worker.PostAction(
+ &types.StartSendingMessage{From: from, Rcpts: rcpts},
func(msg types.WorkerMessage) {
switch msg := msg.(type) {
case *types.Done:
diff --git a/go.mod b/go.mod
index b7a9b09d..0235abf2 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.18
require (
git.sr.ht/~rjarry/go-opt v1.3.0
- git.sr.ht/~rockorager/go-jmap v0.3.0
+ git.sr.ht/~rockorager/go-jmap v0.4.5
git.sr.ht/~rockorager/vaxis v0.7.2
github.com/ProtonMail/go-crypto v0.0.0-20230417170513-8ee5748c52b5
github.com/arran4/golang-ical v0.0.0-20230318005454-19abf92700cc
diff --git a/go.sum b/go.sum
index 4bc68aa8..7e45f1cf 100644
--- a/go.sum
+++ b/go.sum
@@ -1,7 +1,7 @@
git.sr.ht/~rjarry/go-opt v1.3.0 h1:9BLOcXi5OhDYVzH3Td48i2uM/byMGNqXY7YhBzvEZg8=
git.sr.ht/~rjarry/go-opt v1.3.0/go.mod h1:oEPZUTJKGn1FVye0znaLoeskE/QTuyoJw5q+fjusdM4=
-git.sr.ht/~rockorager/go-jmap v0.3.0 h1:h2WuPcNyXRYFg9+W2HGf/mzIqC6ISy9EaS/BGa7Z5RY=
-git.sr.ht/~rockorager/go-jmap v0.3.0/go.mod h1:aOTCtwpZSINpDDSOkLGpHU0Kbbm5lcSDMcobX3ZtOjY=
+git.sr.ht/~rockorager/go-jmap v0.4.5 h1:ab/2+voWrR2/ej4l9GtsyyycK5lOgUMfGSFgNny3Q0c=
+git.sr.ht/~rockorager/go-jmap v0.4.5/go.mod h1:aOTCtwpZSINpDDSOkLGpHU0Kbbm5lcSDMcobX3ZtOjY=
git.sr.ht/~rockorager/vaxis v0.7.2 h1:w+vBMkBWiGLSMMuHwZTDBrTXrjjAoyBc3k681WBT1kU=
git.sr.ht/~rockorager/vaxis v0.7.2/go.mod h1:h94aKek3frIV1hJbdXjqnBqaLkbWXvV+UxAsQHg9bns=
github.com/ProtonMail/crypto v0.0.0-20200420072808-71bec3603bf3 h1:JW27/kGLQzeM1Fxg5YQhdkTEAU7HIAHMgSag35zVTnY=
diff --git a/worker/jmap/send.go b/worker/jmap/send.go
index 4b033d2e..0d8bb23f 100644
--- a/worker/jmap/send.go
+++ b/worker/jmap/send.go
@@ -27,7 +27,7 @@ func (w *JMAPWorker) handleStartSend(msg *types.StartSendingMessage) error {
defer log.PanicHandler()
defer close(send.done)
- identity, err := w.getSenderIdentity(msg.Header)
+ identity, err := w.getSenderIdentity(msg.From)
if err != nil {
send.done <- err
return
@@ -58,6 +58,14 @@ func (w *JMAPWorker) handleStartSend(msg *types.StartSendingMessage) error {
},
})
+ from := &emailsubmission.Address{Email: msg.From.Address}
+ var rcpts []*emailsubmission.Address
+ for _, address := range msg.Rcpts {
+ rcpts = append(rcpts, &emailsubmission.Address{
+ Email: address.Address,
+ })
+ }
+ envelope := &emailsubmission.Envelope{MailFrom: from, RcptTo: rcpts}
// Create the submission
req.Invoke(&emailsubmission.Set{
Account: w.accountId,
@@ -65,6 +73,7 @@ func (w *JMAPWorker) handleStartSend(msg *types.StartSendingMessage) error {
"sub": {
IdentityID: identity,
EmailID: "#aerc",
+ Envelope: envelope,
},
},
OnSuccessUpdateEmail: map[jmap.ID]jmap.Patch{
@@ -122,15 +131,8 @@ func (w *jmapSendWriter) Close() error {
return sendErr
}
-func (w *JMAPWorker) getSenderIdentity(header *mail.Header) (jmap.ID, error) {
- from, err := header.AddressList("from")
- if err != nil {
- return "", fmt.Errorf("msg.Header.AddressList: %w", err)
- }
- if len(from) != 1 {
- return "", fmt.Errorf("no from header in message")
- }
- name, domain, _ := strings.Cut(from[0].Address, "@")
+func (w *JMAPWorker) getSenderIdentity(from *mail.Address) (jmap.ID, error) {
+ name, domain, _ := strings.Cut(from.Address, "@")
for _, ident := range w.identities {
n, d, _ := strings.Cut(ident.Email, "@")
switch {
diff --git a/worker/types/messages.go b/worker/types/messages.go
index 35310b98..7ebb3aae 100644
--- a/worker/types/messages.go
+++ b/worker/types/messages.go
@@ -213,7 +213,8 @@ type CheckMail struct {
type StartSendingMessage struct {
Message
- Header *mail.Header
+ From *mail.Address
+ Rcpts []*mail.Address
}
// Messages