Skip to content

Commit

Permalink
jmap: explicitly fetch body structure subparts
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Robin Jarry <[email protected]>
Reviewed-by: Tim Culverhouse <[email protected]>
  • Loading branch information
rjarry committed Feb 11, 2025
1 parent dbe350a commit 985ce7a
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 12 deletions.
23 changes: 19 additions & 4 deletions worker/jmap/fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,21 @@ import (
"github.com/emersion/go-message/charset"
)

var headersProperties = []string{
var bodyProperties = []string{
"blobId",
"charset",
"cid",
"disposition",
"language",
"location",
"name",
"partId",
"size",
"subParts",
"type",
}

var emailProperties = []string{
"id",
"blobId",
"threadId",
Expand Down Expand Up @@ -57,9 +71,10 @@ func (w *JMAPWorker) handleFetchMessageHeaders(msg *types.FetchMessageHeaders) e
var req jmap.Request

req.Invoke(&email.Get{
Account: w.AccountId(),
IDs: emailIdsToFetch,
Properties: headersProperties,
Account: w.AccountId(),
IDs: emailIdsToFetch,
Properties: emailProperties,
BodyProperties: bodyProperties,
})

resp, err := w.Do(&req)
Expand Down
17 changes: 10 additions & 7 deletions worker/jmap/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,9 @@ func (w *JMAPWorker) refresh(newState jmap.TypeState) error {
SinceState: emailState,
})
emailUpdated = req.Invoke(&email.Get{
Account: w.AccountId(),
Properties: headersProperties,
Account: w.AccountId(),
Properties: emailProperties,
BodyProperties: bodyProperties,
ReferenceIDs: &jmap.ResultReference{
ResultOf: callID,
Name: "Email/changes",
Expand All @@ -124,8 +125,9 @@ func (w *JMAPWorker) refresh(newState jmap.TypeState) error {
})

emailCreated = req.Invoke(&email.Get{
Account: w.AccountId(),
Properties: headersProperties,
Account: w.AccountId(),
Properties: emailProperties,
BodyProperties: bodyProperties,
ReferenceIDs: &jmap.ResultReference{
ResultOf: callID,
Name: "Email/changes",
Expand Down Expand Up @@ -378,9 +380,10 @@ func (w *JMAPWorker) refreshQueriesAndThreads(
}

req.Invoke(&email.Get{
Account: w.AccountId(),
Properties: headersProperties,
IDs: emailsToFetch,
Account: w.AccountId(),
Properties: emailProperties,
BodyProperties: bodyProperties,
IDs: emailsToFetch,
})

resp, err := w.Do(&req)
Expand Down
3 changes: 2 additions & 1 deletion worker/jmap/threads.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ func (w *JMAPWorker) fetchEntireThreads(threads []jmap.ID) ([]*email.Email, erro
Name: "Thread/get",
Path: "/list/*/emailIds",
},
Properties: headersProperties,
Properties: emailProperties,
BodyProperties: bodyProperties,
})

resp, err := w.Do(&req)
Expand Down

0 comments on commit 985ce7a

Please sign in to comment.