Commitc4e02febRecorded21 Mar 2026Repositorysigil-jmap

Add jmap-download-blob for downloading JMAP blobs to files

Message

Expands the server's download URL template (RFC 8620 §6.2) and streams the blob to disk using http-download with Bearer auth.

Changed
 src/sigil/jmap.sgl        |  3 +++
 src/sigil/jmap/client.sgl | 43 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 45 insertions(+), 1 deletion(-)
Diff
src/sigil/jmap.sglmodified
@@ -73,6 +73,9 @@
73
jmap-email-set-keyword!
74
jmap-email-remove-keyword!
75
+76
;; Blob download (from sigil jmap client)
+77
jmap-download-blob
+78
79
;; Send (from sigil jmap send)
80
jmap-identities
81
jmap-send!))
src/sigil/jmap/client.sglmodified
@@ -35,7 +35,10 @@
35
;; Response helpers
36
jmap-response-get
37
jmap-response-error?
38
jmap-error-type)
+38
jmap-error-type
+39
+40
;; Blob download
+41
jmap-download-blob)
42
43
(begin
44
@@ -263,4 +266,42 @@
266
(jmap-response-get response call-id))))
267
(jmap-response-get response call-id)))
268
+269
+270
;; ============================================================
+271
;; Blob Download
+272
;; ============================================================
+273
+274
;;; Download a JMAP blob to a file.
+275
;;;
+276
;;; Expands the server's download URL template (RFC 8620 section 6.2)
+277
;;; and streams the blob to `dest-path` using the client's auth.
+278
;;;
+279
;;; Returns a dict with download info on success:
+280
;;; `#{ status: 200 size: 12345 path: "/tmp/file.pdf" }`
+281
;;;
+282
;;; ```scheme
+283
;;; (jmap-download-blob client "Bf12abc" "report.pdf"
+284
;;; "application/pdf" "/tmp/report.pdf")
+285
;;; ```
+286
(define (jmap-download-blob client blob-id name type dest-path)
+287
(: jmap-client? string? string? string? string? -> dict?)
+288
(let* ((template (or (jmap-client-download-url client)
+289
(error "jmap-download-blob: no download URL in session")))
+290
(account-id (or (jmap-client-account-id client)
+291
(error "jmap-download-blob: no account ID")))
+292
(url (string-replace
+293
(string-replace
+294
(string-replace
+295
(string-replace template
+296
"{accountId}" account-id)
+297
"{blobId}" blob-id)
+298
"{name}" name)
+299
"{type}" type))
+300
(result (http-download url dest-path
+301
headers: (dict
+302
authorization: (jmap-client-auth-header client)))))
+303
(unless result
+304
(error "jmap-download-blob: download failed" url))
+305
result))
+306
307
))