RFC 8620: JMAP — Giao Thức Ứng Dụng Meta JSON
Tại sao nó tồn tại
IMAP hoạt động, nhưng nó mang theo độ phức tạp của nhiều thập kỷ:
- Kết nối TCP có trạng thái. IMAP yêu cầu một kết nối liên tục cho mỗi hộp thư. Các client di động trên mạng không đáng tin cây liên tục kết nối lại và đồng bộ lại.
- Giao thức văn bản tùy chỉnh. Định dạng dây của IMAP yêu cầu các trình phân tích cú pháp chuyên biệt. Mỗi ngôn ngữ cần một thư viện IMAP riêng.
- Phân mảnh phần mở rộng. Các tính năng quan trọng (CONDSTORE, MOVE, SPECIAL-USE) là các phần mở rộng tùy chọn mà máy chủ có thể hỗ trợ hoặc không.
- Hạn chế thông báo đẩy. IMAP IDLE chỉ hoạt động cho một hộp thư tại một thời điểm, và nhiều proxy/firewall sẽ ngắt kết nối TCP idle.
JMAP giải quyết tất cả những điều này. Nó không có trạng thái (mỗi yêu cầu tự chứa), sử dụng HTTPS (hoạt động qua mọi proxy và firewall), sử dụng JSON (mỗi ngôn ngữ có một trình phân tích cú pháp), và xác định thông báo đẩy như một tính năng hạng nhất thông qua EventSource hoặc Web Push.
Nó hoạt động như thế nào
Khám phá dịch vụ
Một client khám phá điểm cuối JMAP thông qua một URI được xác định tốt:
GET https://example.com/.well-known/jmap { "capabilities": { "urn:ietf:params:jmap:core": { ... }, "urn:ietf:params:jmap:mail": { ... } }, "apiUrl": "https://jmap.example.com/api/", "uploadUrl": "https://jmap.example.com/upload/{accountId}/", "downloadUrl": "https://jmap.example.com/download/{accountId}/{blobId}/{name}", "eventSourceUrl": "https://jmap.example.com/events/" }
Thực hiện lệnh gọi API
Tất cả các hoạt động JMAP được gửi dưới dạng một POST duy nhất tới URL API. Phần thân yêu cầu chứa một mảng các lệnh gọi phương thức, và phản hồi chứa các kết quả tương ứng:
POST https://jmap.example.com/api/ { "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], "methodCalls": [ ["Mailbox/get", { "accountId": "u1234", "ids": null }, "a"] ] } { "methodResponses": [ ["Mailbox/get", { "accountId": "u1234", "state": "m42", "list": [ { "id": "mb1", "name": "Inbox", "totalEmails": 142 }, { "id": "mb2", "name": "Sent", "totalEmails": 87 }, { "id": "mb3", "name": "Archive", "totalEmails": 4210 } ] }, "a"] ] }
Đóng gói và tham chiếu ngược
Có thể đóng gói nhiều lệnh gọi phương thức trong một yêu cầu duy nhất. Các tham chiếu ngược cho phép một lệnh gọi sử dụng kết quả của lệnh gọi trước đó:
"methodCalls": [ ["Email/query", { "accountId": "u1234", "filter": { "inMailbox": "mb1", "after": "2025-03-01T00:00:00Z" }, "sort": [{ "property": "receivedAt", "isAscending": false }], "limit": 10 }, "q"], ["Email/get", { "accountId": "u1234", "#ids": { "resultOf": "q", "name": "Email/query", "path": "/ids" }, "properties": ["from", "subject", "receivedAt", "preview"] }, "g"] ]
Điều này tìm kiếm hộp thư đến và tìm nạp 10 kết quả hàng đầu trong một vòng HTTP duy nhất — điều gì sẽ mất nhiều lệnh IMAP.
Chi tiết kỹ thuật chính
Chuỗi trạng thái và đồng bộ hóa
Mỗi phản hồi JMAP /get bao gồm một chuỗi state. Để đồng bộ hóa các thay đổi, client gọi /changes với trạng thái được biết lần cuối:
["Email/changes", { "accountId": "u1234", "sinceState": "e789" }, "c"] ["Email/changes", { "oldState": "e789", "newState": "e801", "created": ["em500", "em501"], "updated": ["em480"], "destroyed": ["em312"] }, "c"]
Client sau đó tìm nạp chỉ các mục được tạo/cập nhật. Điều này hiệu quả hơn CONDSTORE của IMAP vì nó hoạt động trên tất cả các hộp thư cùng một lúc và không yêu cầu một kết nối liên tục.
Thông báo đẩy
JMAP xác định hai cơ chế đẩy:
-
EventSource: Client mở một kết nối SSE lâu dài tới
eventSourceUrl. Server gửi các sự kiện thay đổi trạng thái khi chúng xảy ra. - Web Push (RFC 8030): Cho client di động/nền. Server gửi thông báo đẩy tới URL đăng ký đẩy do client cung cấp.
Mô hình Foo/get, Foo/set, Foo/query
JMAP sử dụng một mô hình phương thức thống nhất cho mỗi loại dữ liệu:
| Phương thức | Mục đích |
|---|---|
Foo/get |
Tìm nạp các đối tượng theo ID |
Foo/changes |
Lấy ID của các đối tượng đã thay đổi kể từ một trạng thái |
Foo/set |
Tạo, cập nhật, hoặc xóa các đối tượng |
Foo/query |
Tìm kiếm/lọc và sắp xếp, trả về ID phù hợp |
Foo/queryChanges |
Cập nhật tăng dần cho kết quả truy vấn trước đó |
Đối với email, Foo là Email, Mailbox, Thread, EmailSubmission, v.v. Tính nhất quán này có nghĩa là một khi bạn hiểu được một loại dữ liệu, bạn sẽ hiểu được tất cả chúng.
Những sai lầm phổ biến
- Coi JMAP như một API REST truyền thống. JMAP sử dụng một điểm cuối duy nhất với các lệnh gọi phương thức trong phần thân yêu cầu, không phải các URL dựa trên tài nguyên. Đừng cố gắng ánh xạ nó tới các quy ước REST.
- Bỏ qua chuỗi trạng thái. Mỗi phản hồi có một trạng thái. Nếu bạn loại bỏ nó, bạn sẽ mất khả năng đồng bộ hóa hiệu quả và phải tìm nạp lại mọi thứ trong lệnh gọi tiếp theo.
-
Tìm nạp tất cả các thuộc tính.
Email/getmà không có danh sáchpropertiestrả về mọi thứ, bao gồm cả phần thân tin nhắn đầy đủ. Luôn chỉ định các thuộc tính bạn cần. - Không sử dụng tham chiếu ngược. Thực hiện các yêu cầu HTTP riêng cho truy vấn + tìm nạp sẽ lãng phí một vòng. Sử dụng tham chiếu ngược để đóng gói chúng.
- Giả định hỗ trợ máy chủ phổ quát. Tính đến năm 2026, sự chấp nhận JMAP đang tăng lên nhưng IMAP vẫn được triển khai rộng rãi hơn nhiều. Fastmail là nhà cung cấp JMAP nổi bật nhất. Kiểm tra khả năng máy chủ trước khi cam kết chỉ JMAP.
- Sử dụng cuộc thăm dò thay vì đẩy. JMAP cung cấp EventSource và Web Push cụ thể để bạn không phải sử dụng cuộc thăm dò. Sử dụng chúng.
Tác động khả năng giao hàng
-
JMAP chủ yếu là một giao thức truy xuất. Giống như IMAP và POP3, nó quản lý cách người nhận truy cập thư, không phải cách bạn gửi nó. Tuy nhiên, JMAP cũng xác định
EmailSubmissionđể gửi, có thể thay thế SMTP submission cho một số trường hợp sử dụng. - Dữ liệu tương tác tốt hơn. Cách tiếp cận có cấu trúc của JMAP đối với các cờ và di chuyển hộp thư cung cấp cho các nhà cung cấp các tín hiệu tương tác sạch hơn. Khi người dùng di chuyển tin nhắn của bạn từ Junk sang Inbox thông qua JMAP, nhà cung cấp sẽ thấy một tín hiệu rõ ràng.
- Đồng bộ hóa client nhanh hơn. Vì đồng bộ hóa JMAP hiệu quả hơn IMAP, nên các client di động luôn đồng bộ hóa một cách đáng tin cây. Điều này có nghĩa là những người nhận sẽ thấy tin nhắn của bạn sớm hơn và tương tác (mở, nhấp chuột) xảy ra nhanh hơn.
-
Đối tượng EmailSubmission. Phương thức
EmailSubmission/setcủa JMAP cho phép gửi email thông qua cùng một API được sử dụng để đọc. Đối với các ứng dụng vừa gửi vừa nhận, điều này thống nhất toàn bộ quy trình email dưới một giao thức.