<?xml version="1.0" encoding="utf-8"?>
<rfc version="3" ipr="trust200902" docName="draft-ietf-jmap-emailpush-02" submissionType="IETF" category="std" xml:lang="en" xmlns:xi="http://www.w3.org/2001/XInclude" indexInclude="true" consensus="true">

<front>
<title abbrev="JMAP Email Delivery Push">JSON Meta Application Protocol (JMAP) Email Delivery Push Notifications</title><seriesInfo value="draft-ietf-jmap-emailpush-02" stream="IETF" status="standard" name="Internet-Draft"></seriesInfo>
<author role="editor" initials="N.M." surname="Jenkins" fullname="Neil Jenkins">
    <organization>Fastmail</organization>
    <address>
        <postal>
            <street>PO Box 234, Collins St West</street>
            <city>Melbourne</city>
            <code>VIC 8007</code>
            <country>Australia</country>
        </postal>
        <email>neilj@fastmailteam.com</email>
        <uri>https://www.fastmail.com</uri>
    </address>
</author>
<date year="2025" month="November" day="6"></date>
<area>Applications</area>
<workgroup>JMAP</workgroup>
<keyword>JMAP</keyword>
<keyword>JSON</keyword>
<keyword>email</keyword>

<abstract>
<t>This document specifies an extension to the JSON Meta Application Protocol (JMAP) that allows clients to receive an object via the JMAP push channel whenever a new email is delivered that matches a client-defined filter. The object can also include properties from the email, to allow a user notification to be displayed without having to make a further network request.</t>
</abstract>

</front>

<middle>

<section anchor="introduction">
<name>Introduction</name>

<t>The JSON Meta Application Protocol (JMAP) <xref target="RFC8620" /> defines a mechanism for creating a push subscription, allowing a client to be efficiently notified whenever the state on the server changes for a data type the client is interested in. This can be used to trigger a resync of that data in the client.</t>

<t>Many email clients wish to show the user a notification when a new email arrives. Email clients implementing JMAP for Mail <xref target="RFC8621" /> may subscribe to changes in the pseudo-type "EmailDelivery" to be notified just whenever a new email is delivered (as opposed to whenever changes are made to the Email data in general, which may be caused by user actions such as reading, organising, or deleting their mail). However, this does not meet the needs of some email clients in constrained environments, particularly on mobile:</t>

<ol>
<li>Data is pushed for all email deliveries, but the client needs to receive them only when a message arrives for which it intends to show the user a notification. For example, this is commonly only shown for messages delivered to the inbox by default, not messages filtered to other mailboxes.</li>
<li>The client needs to make at least one HTTP request, and sometimes more, to resynchronise its datastore before it can show a visible notification to the user. This can sometimes fail when there is poor connectivity. In such circumstances, the client is only able to tell the user a new message has arrived, not any of the details such as who sent it, or the subject.</li>
</ol>

<t>To address these issues, this document defines a way to receive a new EmailPush object via the JMAP push subscription. Clients can request a filter be applied to precisely restrict which messages they are notified about. Clients may request certain properties of the emails be included in the EmailPush object, so it has sufficient information to show the user notifications without having to make any further requests to the server.</t>

<section anchor="notational-conventions">
<name>Notational Conventions</name>

<t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 <xref target="RFC2119"></xref> <xref target="RFC8174"></xref> when, and only when, they appear in all capitals, as shown here.</t>

<t>Type signatures, examples, and property descriptions in this document follow the conventions established in <xref target="RFC8620" section="1.1" sectionFormat="of" />.</t>
</section>

<section anchor="terminology">
<name>Terminology</name>

<t>The same terminology is used in this document as in the core JMAP specification, see <xref target="RFC8620" section="1.6"></xref>.</t>

<t>The term Email (with this specific capitalisation) is used to refer to the data type defined in <xref target="RFC8621" section="4" sectionFormat="of" />.</t>
</section>
</section>

<section anchor="addition-to-the-capabilities-object"><name>Addition to the Capabilities Object</name>
<t>The capabilities object is returned as part of the JMAP Session object; see <xref target="RFC8620" section="2" />. This document defines an additional capability URI.</t>

<section anchor="urn-ietf-params-jmap-calendars">
<name>urn:ietf:params:jmap:emailpush</name>
<t>The <tt>urn:ietf:params:jmap:emailpush</tt> capability support for the extensions to PushSubscription described in this document. The value of this property in the JMAP Session "capabilities" property is an empty object.</t>
<t>Accounts for which email delivery push is supported <bcp14>MUST</bcp14> have this capability in the account's "accountCapabilities" property. The value is an empty object.</t>
<t>Note, this capability may be supported in servers or accounts that do not support the <tt>urn:ietf:params:jmap:mail</tt> capability — in such servers, notification of new emails is supported but any further interaction will require use of a different protocol, such as IMAP <xref target="RFC9051" />.</t>
</section>
</section>

<section anchor="emailpush-object">
<name>The EmailPush object</name>

<t>An <strong>EmailPush</strong> object represents one or more new messages that have been delivered to an account. It has the following properties:</t>

<dl spacing="normal" newline="true">
<dt><strong>@type</strong>: <tt>String</tt></dt>
<dd>This <bcp14>MUST</bcp14> be the string "EmailPush".</dd>

<dt><strong>accountId</strong>: <tt>Id</tt></dt>
<dd>The id of the Account this Email is in.</dd>

<dt><strong>emails</strong>: <tt>Email[]</tt></dt>
<dd><t>An array of objects representing the new messages. Each object has the properties of the Email object (as defined in <xref target="RFC8621" section="4.1" />) that were requested by the client in the EmailPushConfig. If multiple emails arrive in quick succession, or the server comes back online after a period of downtime, it may include multiple Email objects in this array to reduce the number of push notifications it sends, avoiding rate limiting issues.</t>
<t>Note, push channels often have strict restrictions on the size of data that can be sent. The server <bcp14>MUST</bcp14> take care not to exceed this when amalgamating multiple Email objects into a single EmailPush.</t>
<t>In some cases, just a single Email may be too large. Properties <bcp14>MUST</bcp14> be added to this object in the order defined in the properties array of the associated EmailPushConfig. If adding a property would exceed the size limit for the push channel, the property <bcp14>MUST</bcp14> be omitted. Clients are <bcp14>RECOMMENDED</bcp14> to only request the properties they need for the visible notification, plus the "id" property if they want to then fetch further information.</t></dd>

<dt><strong>state</strong>: <tt>String</tt></dt>
<dd>The state string for the Email data type, as would be returned by an "Email/get" call (<xref target="RFC8621" section="4.2" />) for this account. If the server does not support <xref target="RFC8621" />, this property is omitted.</dd>
</dl>
</section>

<section anchor="pushsubscription-object">
<name>Extension to the PushSubscription object</name>

<t>The PushSubscription object is defined in <xref target="RFC8620" section="7.2" />. This document defines an extra property for this object:</t>

<dl spacing="normal" newline="true">
<dt><strong>emailPush</strong>: <tt>Id[EmailPushConfig]|null</tt></dt>
<dd>If not null, this is a map. The keys are Account ids for accounts with support for the <tt>urn:ietf:params:jmap:emailpush</tt> capability. The server will push EmailPush objects for these accounts when a new message arrives, in accordance with the associated EmailPushConfig options for the account.</dd>
</dl>

<t>An <strong>EmailPushConfig</strong> object has the following properties:</t>

<dl spacing="normal" newline="true">
<dt><strong>filter</strong>: <tt>FilterOperator|FilterCondition|null</tt></dt>
<dd><t>A filter to apply to determine which new messages to push an EmailPush object for. The FilterCondition is as defined in <xref target="RFC8621" section="4.4.1" />.</t>
<t>If <tt>urn:ietf:params:jmap:mail</tt> capability is not supported for an account, support for the "inMailbox" and "inMailboxOtherThan" filter conditions is <bcp14>OPTIONAL</bcp14>. However, if the server supports IMAP access to the same account with the ObjectID extension <xref target="RFC8474" />, it <bcp14>MUST</bcp14> support using mailbox ids discovered via IMAP with these filter conditions.</t>
</dd>

<dt><strong>properties</strong>: <tt>String[]</tt></dt>
<dd><t>The list of properties to include in the "emails" value of the EmailPush object. This is the same as the properties argument in "Email/get", as defined in <xref target="RFC8621" section="4.2" />.</t>

<t>If <tt>urn:ietf:params:jmap:mail</tt> capability is supported the server <bcp14>MUST</bcp14> support all the properties it supports for the "Email/get" method. Otherwise, it <bcp14>MUST</bcp14> support the following properties:</t>

<ul spacing="compact">
<li>keywords</li>
<li>from</li>
<li>to</li>
<li>cc</li>
<li>subject</li>
<li>preview</li>
<li>receivedAt</li>
<li>sentAt</li>
</ul>

<t>And if the server supports IMAP ObjectID <xref target="RFC8474" />, it <bcp14>MUST</bcp14> also support the following properties:</t>

<ul spacing="compact">
<li>id</li>
<li>threadId</li>
<li>mailboxIds</li>
</ul>
</dd>

<dt><strong>urgency</strong>: <tt>String</tt> (default: "normal")</dt>
<dd><t>The urgency with which to send push notifications containing the EmailPush object when sending over Web Push <xref target="RFC8030" />. The value must be an <tt>urgency-option</tt>, as defined in <xref target="RFC8030" section="5.3" />.</t></dd>

</dl>
</section>

<section anchor="example">
<name>Example</name>
<t>An email client connects to a server over IMAP (<xref target="RFC9051" />) and after authenticating, sees the OBJECTID <xref target="RFC8474" /> and JMAPACCESS <xref target="RFC9698" /> capabilities advertised.</t>

<t>The JMAPACCESS IMAP capability gives it the URL for the JMAP session resource, and guarantees the client can use the same credentials to authenticate that it used for IMAP. The client fetches the JMAP Session object and finds the following JMAP capabilities present:</t>

<figure>
<name>The "capabilities" property of a JMAP Session object</name>
<sourcecode type="json">
{
  "urn:ietf:params:jmap:core": {
    "maxCallsInRequest": 50,
    "maxConcurrentUpload": 10,
    "maxObjectsInGet": 4096,
    "maxObjectsInSet": 4096,
    "collationAlgorithms": [
      "i;ascii-numeric",
      "i;ascii-casemap",
      "i;octet"
    ],
    "maxSizeUpload": 250000000,
    "maxSizeRequest": 10000000,
    "maxConcurrentRequests": 10
  },
  "urn:ietf:params:jmap:emailpush": {},
}
</sourcecode>
</figure>

<t>The server doesn't support <tt>urn:ietf:params:jmap:mail</tt> yet, so the client can't switch over to using JMAP fully instead of IMAP, but it does support <tt>urn:ietf:params:jmap:emailpush</tt>, so the client can now use JMAP to receive push notifications.</t>

<t>The user has asked the client to notify it of any message delivered to the inbox, plus any message delivered to another folder that has the <tt>$notify</tt> keyword set. The client discovers the mailbox id of the inbox over IMAP using ObjectID, then creates a push subscription by making the following API request:</t>

<figure>
<name>"methodCalls" Property of a JMAP Request</name>
<sourcecode type="json">
[[ "PushSubscription/set", {
  "create": {
    "4f29": {
      "deviceClientId": "a889-ffea-910",
      "url": "https://push.example.com/WmYD3enMWsSOE0ndiBZfYeg54j4eWHfI",
      "keys": {
        "p256dh": "BM0HH37xD8sEh8NeiHu1hFuwxqeeruxPlX5S7XGWGjHY5UT5yZFQKAiihFQLP6GuEQPQOtD9z28HRyV7e1nndh8",
        "auth": "uwPFKACOLBipGPTVz4UCDg"
      },
      "types": [],
      "emailPush": {
        "A1412": {
          "filter": {
            "operator": "OR",
            "conditions": [
              { "inMailbox": "674cc240-95db-49ce-a8a2-054f4f733095" },
              { "hasKeyword": "$notify" }
            ]
          },
          "properties": ["from", "subject", "id"]
        }
      }
    }
  }
}, "0" ]]
</sourcecode>
</figure>

<t>The server creates the push subscription and immediately pushes a PushVerification object to the client. The client updates the PushSubscription object with this value to validate it as per <xref target="RFC8620" section="7.2.2" />. With this done, the server will now push an EmailPush object whenever a new message arrives that's delivered to the mailbox with id "674cc240-95db-49ce-a8a2-054f4f733095", or has the "$notify" keyword. As the "types" property is the empty array, the server will not push any StateChange objects. For example, a message arrives and the server pushes the following:</t>

<figure>
<name>An EmailPush object</name>
<sourcecode type="json">
{
  "@type": "EmailPush",
  "accountId": "A1412",
  "emails": [{
    "from": [{ "name": "John Smith", "email": "john@example.com" }],
    "subject": "Surprise birthday party for Jane tonight",
    "id": "M699bb151ca4cbf1c24364a68"
  }],
  "state": "XH99813"
}
</sourcecode>
</figure>

</section>

<section anchor="security-considerations">
<name>Security Considerations</name>
<t>All security considerations of JMAP <xref target="RFC8620" /> apply to this specification. Additional considerations are detailed below.</t>
<t>With the push defined in JMAP Core, no user data travels over the push channel, only state strings. The EmailPush object on the other hand contains sensitive user data. As specfied in <xref target="RFC8620" section="8.7" />, to ensure confidentiality and integrity of the user's data, the client <bcp14>MUST</bcp14> specify encryption keys when establishing the PushSubscription and ignore any push notification received that is not encrypted with those keys.</t>
</section>

<section anchor="iana-considerations">
<name>IANA Considerations</name>

<section anchor="jmap-capability-registration-for-calendars"><name>JMAP Capability Registration for "emailpush"</name>
<t>IANA will register the "emailpush" JMAP Capability as follows:</t>
<dl newline="false" spacing="compact">
<dt>Capability Name:</dt> <dd><tt>urn:ietf:params:jmap:emailpush</tt></dd>
<dt>Specification document:</dt> <dd>this document</dd>
<dt>Intended use:</dt> <dd>common</dd>
<dt>Change Controller:</dt> <dd>IETF</dd>
<dt>Security and privacy considerations:</dt> <dd>this document, <xref target="security-considerations" /></dd>
</dl>
</section>
</section>

</middle>
<back>
<references><name>Normative References</name>
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8030.xml"/>
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"/>
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8620.xml"/>
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8621.xml"/>
</references>
<references><name>Informative References</name>
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8474.xml"/>
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.9051.xml"/>
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.9698.xml"/>
</references>

</back>

</rfc>
