mirror of
https://git.sr.ht/~rjarry/aerc
synced 2025-07-12 03:00:21 +02:00

When requesting the bodyStructure email property, the spec says that the default returned body part properties are: ["partId", "blobId", "size", "name", "type", "charset", "disposition", "cid", "language", "location"]. Specifically, the "subParts" property is *NOT* expected by default. Fastmail servers seem to use a different default "bodyProperties" list and implicitly return "subParts" even if not requested. Other JMAP server implementations (e.g. Apache James) do use the RFC default "bodyProperties" and therefore omit returning "subParts" unless explicitly asked to. Change the requested "bodyProperties" to include "subParts" as well. Aerc needs them to display messages. NB: for later, we should probably change our message abstraction not to include any body structure. This makes very little sense to expose that to users. In fact, aerc has code to explicitly prevent users from selecting multipart/* parts. Not requesting that information to the server would make it easier. Link: https://datatracker.ietf.org/doc/html/rfc8621#section-4.2 Reported-by: Benoit Tellier <btellier@linagora.com> Signed-off-by: Robin Jarry <robin@jarry.cc> Reviewed-by: Tim Culverhouse <tim@timculverhouse.com>
64 lines
1.6 KiB
Go
64 lines
1.6 KiB
Go
package jmap
|
|
|
|
import (
|
|
"git.sr.ht/~rockorager/go-jmap"
|
|
"git.sr.ht/~rockorager/go-jmap/mail/email"
|
|
"git.sr.ht/~rockorager/go-jmap/mail/thread"
|
|
)
|
|
|
|
func (w *JMAPWorker) fetchEntireThreads(threads []jmap.ID) ([]*email.Email, error) {
|
|
var req jmap.Request
|
|
|
|
if len(threads) == 0 {
|
|
return []*email.Email{}, nil
|
|
}
|
|
|
|
threadGetId := req.Invoke(&thread.Get{
|
|
Account: w.AccountId(),
|
|
IDs: threads,
|
|
})
|
|
|
|
// Opportunistically fetch all emails in this thread. We could wait for
|
|
// the result, check which ones we don't have, then fetch only those.
|
|
// However we can do this all in a single request which ends up being
|
|
// faster than two requests for most contexts
|
|
req.Invoke(&email.Get{
|
|
Account: w.AccountId(),
|
|
ReferenceIDs: &jmap.ResultReference{
|
|
ResultOf: threadGetId,
|
|
Name: "Thread/get",
|
|
Path: "/list/*/emailIds",
|
|
},
|
|
Properties: emailProperties,
|
|
BodyProperties: bodyProperties,
|
|
})
|
|
|
|
resp, err := w.Do(&req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
emailsToReturn := make([]*email.Email, 0)
|
|
for _, inv := range resp.Responses {
|
|
switch r := inv.Args.(type) {
|
|
case *thread.GetResponse:
|
|
if err = w.cache.PutThreadState(r.State); err != nil {
|
|
w.w.Warnf("PutThreadState: %s", err)
|
|
}
|
|
for _, thread := range r.List {
|
|
if err = w.cache.PutThread(thread.ID, thread.EmailIDs); err != nil {
|
|
w.w.Warnf("PutThread: %s", err)
|
|
}
|
|
}
|
|
case *email.GetResponse:
|
|
emailsToReturn = append(emailsToReturn, r.List...)
|
|
if err = w.cache.PutEmailState(r.State); err != nil {
|
|
w.w.Warnf("PutEmailState: %s", err)
|
|
}
|
|
case *jmap.MethodError:
|
|
return nil, wrapMethodError(r)
|
|
}
|
|
}
|
|
|
|
return emailsToReturn, nil
|
|
}
|