← RFC Reference

RFC 8620: JMAP — JSON メタアプリケーションプロトコル

Standards Track Mail Access Protocols Published March 2026
ELI5: IMAPは1990年代に設計された時代のもので、クライアントはカスタムテキストプロトコルを使ってサーバーと生のTCPソケットで通信していました。JMAPは同じ概念です — メールボックスへのアクセス、フォルダの管理、変更の同期 — ですが、すべての開発者がすでに知っているツールを使用します。JSONをHTTPSで送受信します。メール用のREST風APIです。ソケット管理なし、奇妙なテキスト応答の解析なし、拡張機能のネゴシエーションなし。JSONリクエストをPOSTして、JSONレスポンスを取得するだけです。

これが存在する理由

IMAPは機能しますが、数十年の複雑さを抱えています:

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つのプッシュメカニズムを定義します:

Foo/get、Foo/set、Foo/queryパターン

JMAPはすべてのデータタイプに統一されたメソッドパターンを使用します:

メソッド 目的
Foo/get IDでオブジェクトを取得
Foo/changes 状態以降に変更されたオブジェクトのIDを取得
Foo/set オブジェクトを作成、更新、または削除
Foo/query 検索/フィルター、ソート、マッチするIDを返す
Foo/queryChanges 前のクエリ結果への増分更新

メールの場合、FooEmailMailboxThreadEmailSubmission などです。この一貫性により、1つのデータタイプを理解すれば、すべてを理解できます。

よくある間違い

配信可能性への影響

Related RFCs