RFC 8620: JMAP — JSON メタアプリケーションプロトコル
ELI5: IMAPは1990年代に設計された時代のもので、クライアントはカスタムテキストプロトコルを使ってサーバーと生のTCPソケットで通信していました。JMAPは同じ概念です — メールボックスへのアクセス、フォルダの管理、変更の同期 — ですが、すべての開発者がすでに知っているツールを使用します。JSONをHTTPSで送受信します。メール用のREST風APIです。ソケット管理なし、奇妙なテキスト応答の解析なし、拡張機能のネゴシエーションなし。JSONリクエストをPOSTして、JSONレスポンスを取得するだけです。
これが存在する理由
IMAPは機能しますが、数十年の複雑さを抱えています:
- ステートフルTCP接続。 IMAPはメールボックスごとに永続接続が必要です。不安定なネットワーク上のモバイルクライアントは常に再接続と再同期を繰り返します。
- カスタムテキストプロトコル。 IMAPのワイヤフォーマットは特殊なパーサーが必要です。すべての言語に専用のIMAPライブラリが必要です。
- 拡張機能の分散。 重要な機能(CONDSTORE、MOVE、SPECIAL-USE)はオプション拡張であり、サーバーはサポートしていない可能性があります。
- プッシュ通知の制限。 IMAP IDLEは一度に1つのメールボックスでのみ機能し、多くのプロキシ/ファイアウォールがアイドルTCP接続を切断します。
JMAPはこれらすべてを解決します。ステートレス(各リクエストが自己完結型)、HTTPS を使用(すべてのプロキシとファイアウォールを通過)、JSON を使用(すべての言語がパーサーを持つ)、EventSourceまたはWeb Pushを介したプッシュ通知を第一級の機能として定義します。
仕組み
サービスディスカバリー
クライアントは既知のURIを介してJMAPエンドポイントを発見します:
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/" }
APIコールの実行
すべてのJMAP操作はAPIURLへの単一のPOSTで送信されます。リクエストボディには一連のメソッドコールが含まれ、レスポンスには対応する結果が含まれます:
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"] ] }
バッチ処理と逆参照
複数のメソッドコールを1つのリクエストでバッチ処理できます。逆参照により、1つのコールが以前のコールの結果を使用できます:
"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"] ]
これはインボックスを検索し、1つのHTTPラウンドトリップで上位10件の結果を取得します。これには複数のIMAPコマンドが必要になります。
主要な技術詳細
状態文字列と同期
すべてのJMAP /get レスポンスに state 文字列が含まれます。変更を同期するには、クライアントは最後に知られた状態を持つ /changes を呼び出します:
["Email/changes", { "accountId": "u1234", "sinceState": "e789" }, "c"] ["Email/changes", { "oldState": "e789", "newState": "e801", "created": ["em500", "em501"], "updated": ["em480"], "destroyed": ["em312"] }, "c"]
クライアントは作成/更新されたアイテムのみを取得します。これはすべてのメールボックスで同時に機能し、永続接続を必要としないため、IMAPのCONDSTOREより効率的です。
プッシュ通知
JMAPは2つのプッシュメカニズムを定義します:
-
EventSource: クライアントは
eventSourceUrlへの長時間接続SSE接続を開きます。サーバーは状態変化イベントが発生するときに送信します。 - Web Push(RFC 8030): モバイル/バックグラウンドクライアント向け。サーバーはクライアントが提供するプッシュサブスクリプションURLにプッシュ通知を送信します。
Foo/get、Foo/set、Foo/queryパターン
JMAPはすべてのデータタイプに統一されたメソッドパターンを使用します:
| メソッド | 目的 |
|---|---|
Foo/get |
IDでオブジェクトを取得 |
Foo/changes |
状態以降に変更されたオブジェクトのIDを取得 |
Foo/set |
オブジェクトを作成、更新、または削除 |
Foo/query |
検索/フィルター、ソート、マッチするIDを返す |
Foo/queryChanges |
前のクエリ結果への増分更新 |
メールの場合、Foo は Email、Mailbox、Thread、EmailSubmission などです。この一貫性により、1つのデータタイプを理解すれば、すべてを理解できます。
よくある間違い
- JMAPを従来のREST APIのように扱う。 JMAPはリソースベースのURLではなく、リクエストボディにメソッドコールを含む単一のエンドポイントを使用します。REST規約にマップしようとしないでください。
- 状態文字列を無視する。 すべてのレスポンスに状態があります。それを破棄すると、効率的な同期が失われ、次のコールですべてを再取得する必要があります。
-
すべてのプロパティを取得する。
propertiesリストなしのEmail/getは、完全なメッセージボディを含むすべてを返します。常に必要なプロパティを指定してください。 - 逆参照を使用しない。 クエリ+フェッチに対して個別のHTTPリクエストを作成すると、ラウンドトリップが無駄になります。逆参照を使用してそれらをバッチ処理してください。
- 汎用サーバーサポートを想定する。 2026年現在、JMAP採用は増加していますが、IMAPはまだはるかに広くデプロイされています。Fastmailが最も顕著なJMAPプロバイダーです。JMAPのみを使用する前にサーバー機能を確認してください。
- ポーリングの代わりにプッシュを使用しない。 JMAPはEventSourceとWeb Pushを提供するのは、ポーリングの必要がないようにするためです。それらを使用してください。
配信可能性への影響
-
JMAPは主に取得プロトコルです。 IMAPやPOP3と同様に、受信者がメールにアクセスする方法を管理しますが、送信方法ではありません。ただし、JMAPは送信用に
EmailSubmissionも定義しており、一部のユースケースでSMTP送信に代わる可能性があります。 - より優れたエンゲージメントデータ。 JMAPの構造化されたフラグとメールボックス移動へのアプローチは、プロバイダーにより清潔なエンゲージメント信号を与えます。ユーザーがJMAPを介してメッセージをジャンクからインボックスに移動するとき、プロバイダーは明確な信号を見ます。
- より高速なクライアント同期。 JMAPの同期がIMAPより効率的であるため、モバイルクライアントはより信頼できるように同期されます。これは受信者がメッセージをより早く表示し、エンゲージメント(開封、クリック)がより早く発生することを意味します。
-
EmailSubmissionオブジェクト。 JMAP の
EmailSubmission/setメソッドにより、読み取りに使用される同じAPIを通じてメールを送信できます。送受信の両方を行うアプリケーションの場合、これにより1つのプロトコルの下でメール全体ワークフローを統一します。