Network Working Group J. Coffey Internet-Draft Coffey Labs LLC Intended status: Standards Track 27 October 2026 Expires: 30 April 2027 JMAP Undelete: Recovering Destroyed Objects draft-coffey-jmap-undelete-00 Abstract This document specifies an extension to the JSON Meta Application Protocol (JMAP) that lets a client find and restore objects that were permanently destroyed within a server-defined retention period. It defines a new capability, a DeletedItem data type that describes a destroyed object of any supported data type, and a DeletedItem/ restore method that recreates it. Rules are given for Email, ContactCard, CalendarEvent, FileNode, and SieveScript objects. Servers can already keep destroyed data for a time. This extension gives clients an interoperable way to show what can be recovered, for how long, and to recover it. About This Document This note is to be removed before publishing as an RFC. Discussion of this document takes place on the JMAP Working Group mailing list (jmap@ietf.org). Status of This Memo This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79. Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet- Drafts is at https://datatracker.ietf.org/drafts/current/. Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." This Internet-Draft will expire on 30 April 2027. Coffey Expires 30 April 2027 [Page 1] Internet-Draft JMAP Undelete October 2026 Copyright Notice Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/ license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License. Table of Contents 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 1.1. Notational Conventions . . . . . . . . . . . . . . . . . 3 1.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 3 1.3. Addition to the Capabilities Object . . . . . . . . . . . 4 2. Keeping Deleted Items . . . . . . . . . . . . . . . . . . . . 5 3. DeletedItem . . . . . . . . . . . . . . . . . . . . . . . . . 5 3.1. Snapshot Properties . . . . . . . . . . . . . . . . . . . 6 3.2. Blob Representations . . . . . . . . . . . . . . . . . . 7 3.3. Access in Shared Accounts . . . . . . . . . . . . . . . . 8 3.4. DeletedItem/get . . . . . . . . . . . . . . . . . . . . . 8 3.5. DeletedItem/changes . . . . . . . . . . . . . . . . . . . 8 3.6. DeletedItem/query . . . . . . . . . . . . . . . . . . . . 8 3.7. DeletedItem/queryChanges . . . . . . . . . . . . . . . . 9 3.8. DeletedItem/set . . . . . . . . . . . . . . . . . . . . . 9 3.9. DeletedItem/restore . . . . . . . . . . . . . . . . . . . 10 3.9.1. Containers . . . . . . . . . . . . . . . . . . . . . 11 3.9.2. Email . . . . . . . . . . . . . . . . . . . . . . . . 12 3.9.3. FileNode and SieveScript . . . . . . . . . . . . . . 12 4. Expiry . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 5. Quotas . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 6. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . 13 7. Security Considerations . . . . . . . . . . . . . . . . . . . 15 8. Privacy Considerations . . . . . . . . . . . . . . . . . . . 16 9. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 16 9.1. JMAP Capability Registration for "undelete" . . . . . . . 16 9.2. JMAP Data Type Registration for "DeletedItem" . . . . . . 16 10. Implementation Status . . . . . . . . . . . . . . . . . . . . 17 11. References . . . . . . . . . . . . . . . . . . . . . . . . . 17 11.1. Normative References . . . . . . . . . . . . . . . . . . 17 11.2. Informative References . . . . . . . . . . . . . . . . . 18 Appendix A. Open Issues . . . . . . . . . . . . . . . . . . . . 19 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 19 Coffey Expires 30 April 2027 [Page 2] Internet-Draft JMAP Undelete October 2026 1. Introduction Deleting data by mistake is common. A user empties the Trash mailbox, a filter removes the wrong messages, a client expunges a folder, or a synchronisation error destroys contacts or calendar events. Many servers keep destroyed data for some time so that an administrator can recover it, but there is no standard way for a client to see what is recoverable or to recover it. Each server that offers recovery to end users does so through its own interface. This document defines that interface for JMAP [RFC8620]. When a server supports it, destroying an object of a supported data type leaves behind a DeletedItem record for a retention period. The DeletedItem describes the destroyed object, gives access to its content as a blob, and can be restored with the DeletedItem/restore method, which recreates the object in its original place where that is still possible. When the retention period ends, or when the user purges the DeletedItem, the object is gone for good. The extension is generic: any data type registered in the "JMAP Data Types" registry [IANA-JMAP] can take part. This document gives specific rules for Email [RFC8621], ContactCard [RFC9610], CalendarEvent [I-D.ietf-jmap-calendars], FileNode [I-D.ietf-jmap-filenode], and SieveScript [RFC9661]. This extension is about mistakes. It is not a backup mechanism, since it does not protect against loss of the server, and it is not a legal hold, since a user can purge their own deleted items. See Section 8. 1.1. Notational Conventions 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 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here. Type signatures, examples, and property descriptions in this document follow the conventions established in Section 1.1 of [RFC8620]. Data types defined in the core specification are also used in this document. 1.2. Terminology Destroy: To remove an object from an account permanently, so that it Coffey Expires 30 April 2027 [Page 3] Internet-Draft JMAP Undelete October 2026 no longer appears in that data type's /get or /query results. This includes a JMAP /set destroy and removals made through any other protocol, such as an IMAP [RFC9051] EXPUNGE. Moving an object to a mailbox, calendar, or folder with a "trash" role is not destroying it. Deleted item: The record that a server keeps of a destroyed object, as described by a DeletedItem object (Section 3). Container: The object or objects that hold an object of a given data type: Mailboxes for an Email, AddressBooks for a ContactCard, Calendars for a CalendarEvent, the parent FileNode for a FileNode. A SieveScript has no container. Retention period: The length of time for which a deleted item stays restorable. Purge: To destroy a deleted item before its retention period ends. 1.3. Addition to the Capabilities Object The capability "urn:ietf:params:jmap:undelete" is added to the Session object's "capabilities" property. Its value in the "capabilities" property of the Session object is an empty object. An account supports this extension if this capability is present in the account's "accountCapabilities" property. Its value there is an object with the following properties: objectTypes: String[] The names of the data types for which this account keeps deleted items, from the "JMAP Data Types" registry or defined by a private extension. The list MUST NOT be empty. A data type appears here only if the server keeps deleted items for it at the time the Session object is fetched. retentionPeriod: UnsignedInt|null The number of seconds a newly destroyed object stays restorable, or null if the server does not keep deleted items for a fixed time (for example, because the period depends on the object). Clients use this to tell the user how long they have to change their mind. The "expiresAt" property of each DeletedItem is authoritative. mayPurge: Boolean Whether the user may purge deleted items in this account with DeletedItem/set (Section 3.8). Coffey Expires 30 April 2027 [Page 4] Internet-Draft JMAP Undelete October 2026 2. Keeping Deleted Items While an account advertises this capability, a server MUST create a DeletedItem whenever an object of a data type listed in "objectTypes" is destroyed in that account, whatever protocol or process destroyed it. This includes, for example, an Email destroyed with Email/set, expunged over IMAP, deleted over POP3, removed by the automatic emptying of a Trash mailbox, or destroyed because its only Mailbox was destroyed with "onDestroyRemoveEmails" (Section 2.5 of [RFC8621]). A server MUST NOT create a DeletedItem: * for an object that never existed in the account, such as a message rejected before delivery; * when a DeletedItem is itself purged or expires; or * when an object is moved between accounts with a /copy method that has "onSuccessDestroyOriginal" set to true, because the object still exists in the destination account. Modifying an object, including removing it from some but not all of its containers, does not create a DeletedItem. This extension recovers destroyed objects. It does not recover earlier versions of objects that still exist. When an account stops advertising a data type in "objectTypes", or stops advertising the capability, deleted items already kept SHOULD remain restorable until their own "expiresAt" time. A server MUST NOT shorten the "expiresAt" of an existing DeletedItem because its retention settings changed. A user who was told that an object could be recovered until a given time should be able to rely on it. 3. DeletedItem A DeletedItem object describes one destroyed object. It has the following properties: id: Id (immutable; server-set) The id of the DeletedItem. objectType: String (immutable; server-set) The name of the data type of the destroyed object, as registered in the "JMAP Data Types" registry, for example, "Email". The naming follows the ShareNotification object of [RFC9670]. Coffey Expires 30 April 2027 [Page 5] Internet-Draft JMAP Undelete October 2026 objectId: Id (immutable; server-set) The id the destroyed object had. Clients can use this to offer "undo" for an object they have just destroyed (see Section 3.6). deletedAt: UTCDate (immutable; server-set) When the object was destroyed. expiresAt: UTCDate|null (immutable; server-set) When the deleted item stops being restorable, or null if the server keeps it until it is purged. After this time the server MUST NOT restore it. size: UnsignedInt (immutable; server-set) The size, in octets, of the blob referenced by "blobId". blobId: Id|null (immutable; server-set) The id of a blob holding the destroyed object's content in the representation given in Section 3.2, or null if the server does not offer one for this data type. The blob can be downloaded without restoring the object, for example to preview it. snapshot: Object (immutable; server-set) Some of the destroyed object's properties as they were when it was destroyed, with the names and values the object's own /get method would have returned. The server MUST include the properties listed for the data type in Section 3.1 where the object had them, and MAY include others. The "id" property is not included, because it is given by "objectId". 3.1. Snapshot Properties The following properties MUST appear in "snapshot" for the data types defined so far. They give a client enough to show a useful list ("what was it, and where was it") without restoring anything. Coffey Expires 30 April 2027 [Page 6] Internet-Draft JMAP Undelete October 2026 +===============+===================================+ | objectType | Properties | +===============+===================================+ | Email | mailboxIds, keywords, receivedAt, | | | size, subject, from, preview | +---------------+-----------------------------------+ | ContactCard | addressBookIds, name, kind | +---------------+-----------------------------------+ | CalendarEvent | calendarIds, title, start, | | | duration, timeZone | +---------------+-----------------------------------+ | FileNode | parentId, name, type, size | +---------------+-----------------------------------+ | SieveScript | name, isActive | +---------------+-----------------------------------+ Table 1: Required Snapshot Properties A specification that adds a data type to this extension SHOULD list its required snapshot properties in the same way. 3.2. Blob Representations When "blobId" is not null, the blob holds the destroyed object in the following representation: +===============+===========================================+ | objectType | Representation | +===============+===========================================+ | Email | The message as stored, as the Email's own | | | "blobId" referenced it (message/rfc822) | +---------------+-------------------------------------------+ | ContactCard | The JSContact Card [RFC9553] | | | (application/jscontact+json) | +---------------+-------------------------------------------+ | CalendarEvent | The JSCalendar Event [RFC8984] | | | (application/jscalendar+json) | +---------------+-------------------------------------------+ | FileNode | The file's content, as the FileNode's own | | | "blobId" referenced it; a FileNode with | | | no content (a folder) has null | +---------------+-------------------------------------------+ | SieveScript | The script, as the SieveScript's own | | | "blobId" referenced it (application/ | | | sieve) | +---------------+-------------------------------------------+ Table 2: Deleted Item Blob Representations Coffey Expires 30 April 2027 [Page 7] Internet-Draft JMAP Undelete October 2026 A server MAY return the same blobId the destroyed object had. The blob MUST remain downloadable for as long as the DeletedItem exists. 3.3. Access in Shared Accounts In an account the user owns, every DeletedItem is visible to them. In an account shared with the user [RFC9670], a DeletedItem MUST be visible only if, when the object was destroyed, the user had the right to read it in at least one of its containers. A server MAY limit visibility further, for example to the account's owner only. A DeletedItem that is not visible to the user MUST be treated as if it did not exist by every method in this document. 3.4. DeletedItem/get This is a standard "/get" method as described in Section 5.1 of [RFC8620]. A DeletedItem past its "expiresAt" time MUST be returned in "notFound", even if the server has not yet removed it. 3.5. DeletedItem/changes This is a standard "/changes" method as described in Section 5.2 of [RFC8620]. A DeletedItem that is restored, purged, or expires is reported as destroyed. Since DeletedItem objects are immutable, they are never reported as updated. 3.6. DeletedItem/query This is a standard "/query" method as described in Section 5.5 of [RFC8620]. A *FilterCondition* object has the following properties, any of which may be omitted: objectType: String The "objectType" property must be equal to this. objectIds: Id[] The "objectId" property must be in this list. deletedBefore: UTCDate The "deletedAt" property must be before this date-time. Coffey Expires 30 April 2027 [Page 8] Internet-Draft JMAP Undelete October 2026 deletedAfter: UTCDate The "deletedAt" property must be the same as or after this date- time. inContainer: Id The destroyed object must have been in this container: its snapshot's "mailboxIds", "addressBookIds", or "calendarIds" must contain this id, or its "parentId" must equal it. The container does not have to exist any more. text: String Looks for the text in the string values of the snapshot. For an Email, this includes the subject and the names and addresses of the "from" property. A server MAY also search the content of the blob. If more than one property is given, the deleted item must match all of them. The following values for the "property" field of a Comparator object MUST be supported for sorting: * "deletedAt" * "expiresAt" * "size" If no sort is given, the results are sorted by "deletedAt", newest first. 3.7. DeletedItem/queryChanges This is a standard "/queryChanges" method as described in Section 5.6 of [RFC8620]. 3.8. DeletedItem/set This is a standard "/set" method as described in Section 5.3 of [RFC8620], used only to purge deleted items. DeletedItem objects cannot be created or updated with this method: the server MUST reject every create and every update with a "forbidden" SetError. Coffey Expires 30 April 2027 [Page 9] Internet-Draft JMAP Undelete October 2026 Destroying a DeletedItem purges it. The server MUST then make the object unrecoverable through this extension and MUST release the blob as for any destroyed object. If the account's "mayPurge" is false, or the user does not have the right to remove the object from the containers it was in, the server MUST reject the destroy with a "forbidden" SetError. 3.9. DeletedItem/restore This method recreates the objects described by one or more DeletedItems. It takes the following arguments: accountId: Id The id of the account to use. ids: Id[] The ids of the DeletedItems to restore. The number of ids MUST NOT exceed the "maxObjectsInSet" limit of the core capability. ifInState: String|null As for /set (Section 5.3 of [RFC8620]), against the DeletedItem state. The response has the following arguments: accountId: Id The id of the account used for the call. oldState: String|null The DeletedItem state before the call. newState: String The DeletedItem state after the call. restored: Id[Object]|null A map from the id of each DeletedItem that was restored to an object with two properties: "objectType", the data type of the object, and "object", an object holding the "id" of the recreated object and any other properties whose values differ from the snapshot (for example, the containers it was restored to, or a new name). This is null if nothing was restored. notRestored: Id[SetError]|null A map from the id of each DeletedItem that could not be restored to a SetError, or null if there were none. The following SetError types may be returned in "notRestored": Coffey Expires 30 April 2027 [Page 10] Internet-Draft JMAP Undelete October 2026 * "notFound": The DeletedItem does not exist, is not visible to the user, or is past its "expiresAt" time. * "forbidden": The user may not create the object in any container it could be restored to. * "overQuota": Restoring the object would take the account past a quota. * "tooLarge": The object is larger than the server now accepts for that data type. Restoring is atomic for each DeletedItem: either the object is recreated and the DeletedItem is removed, or neither happens. If the same id appears more than once in "ids", or a restore of the same DeletedItem is already in progress, the object is restored once. A restored object is a new object of its data type, created by the server. It gets a new id, which may or may not equal "objectId". The data type's state changes as for any created object, so clients learn about it through the usual /changes calls and push notifications. A client MUST NOT assume that the restored object has its old id. A restored object MUST have the property values in its snapshot, and the server SHOULD restore the other properties it had, except where the following sections say otherwise. Server-set properties (such as an Email's "threadId") are set as for a new object. 3.9.1. Containers An object is restored to the containers it was in when it was destroyed, leaving out any that no longer exist or that the user may not add objects to. If none remain, it is restored to the default container for its type: * Email: the Mailbox with the "inbox" role. * ContactCard: the AddressBook with "isDefault" true. * CalendarEvent: the Calendar with "isDefault" true. * FileNode: the root of the file tree. If the user may not add objects to the default container either, the restore fails with "forbidden". Coffey Expires 30 April 2027 [Page 11] Internet-Draft JMAP Undelete October 2026 An Email that was only in the Mailbox with the "trash" role when it was destroyed is restored there. An Email that was in the Trash and other Mailboxes is restored to the other Mailboxes only. This follows what the user most likely intends: the message was emptied from the Trash, or deleted from a folder it was filed in. 3.9.2. Email A restored Email MUST have the "keywords" it had when destroyed, including "$seen", and the same "receivedAt". It joins a thread according to the server's normal threading rules, so it will usually rejoin its earlier conversation. A restored Email is not new mail: the server MUST NOT run delivery-time processing (such as Sieve [RFC5228] scripts, spam filtering, or vacation responses) on it. 3.9.3. FileNode and SieveScript If a FileNode's name is already in use in the folder it is restored to, or a SieveScript's name is already in use, the server MUST choose a new name for the restored object and report it in the "object" of the "restored" entry. How the new name is formed is up to the server. A folder FileNode is restored without its content. Its children that were destroyed with it have DeletedItems of their own, and a client restores them by restoring each one, parents first. A client can find them with the "inContainer" filter. A restored SieveScript MUST NOT be active, even if it was active when destroyed. Activating a script changes how incoming mail is handled, so the user must do it on purpose. 4. Expiry When a DeletedItem's "expiresAt" time passes, the server MUST stop offering it through every method in this document at once, and SHOULD destroy it and release its blob soon after. It is reported as destroyed by DeletedItem/changes no later than the next state change after its expiry. 5. Quotas A server decides whether deleted items count toward an account's quotas. Counting them is NOT RECOMMENDED, since a user who deletes data to free space would otherwise gain nothing until the retention period ends. A server that does count them and supports JMAP Quotas [RFC9425] SHOULD include "DeletedItem" in the "types" of each Quota they count toward. Coffey Expires 30 April 2027 [Page 12] Internet-Draft JMAP Undelete October 2026 A restored object counts toward quotas as a new object would, whether or not the DeletedItem did. 6. Examples A client shows a "Recently deleted" view of email: [[ "DeletedItem/query", { "accountId": "u1", "filter": { "objectType": "Email" }, "sort": [{ "property": "deletedAt", "isAscending": false }], "limit": 50 }, "0" ], [ "DeletedItem/get", { "accountId": "u1", "#ids": { "resultOf": "0", "name": "DeletedItem/query", "path": "/ids" } }, "1" ]] The server responds: Coffey Expires 30 April 2027 [Page 13] Internet-Draft JMAP Undelete October 2026 [[ "DeletedItem/query", { "accountId": "u1", "queryState": "q73", "canCalculateChanges": true, "position": 0, "ids": [ "d42" ] }, "0" ], [ "DeletedItem/get", { "accountId": "u1", "state": "s9", "list": [{ "id": "d42", "objectType": "Email", "objectId": "M8f2", "deletedAt": "2026-10-26T18:03:11Z", "expiresAt": "2026-11-25T18:03:11Z", "size": 48211, "blobId": "G3a91", "snapshot": { "mailboxIds": { "mb-inbox": true, "mb-invoices": true }, "keywords": { "$seen": true, "$flagged": true }, "receivedAt": "2026-10-20T09:15:00Z", "size": 48211, "subject": "Invoice 2026-118", "from": [{ "name": "Accounts", "email": "accounts@example.com" }], "preview": "Please find attached the invoice for October..." } }], "notFound": [] }, "1" ]] The user restores it. The "invoices" Mailbox has since been destroyed, so the message goes back to the Inbox only: [[ "DeletedItem/restore", { "accountId": "u1", "ids": [ "d42" ] }, "0" ]] Coffey Expires 30 April 2027 [Page 14] Internet-Draft JMAP Undelete October 2026 [[ "DeletedItem/restore", { "accountId": "u1", "oldState": "s9", "newState": "s10", "restored": { "d42": { "objectType": "Email", "object": { "id": "M9c07", "mailboxIds": { "mb-inbox": true } } } }, "notRestored": null }, "0" ]] A client that has just destroyed an Email with id "M8f2" offers "Undo" by looking up its DeletedItem: [[ "DeletedItem/query", { "accountId": "u1", "filter": { "objectIds": [ "M8f2" ] } }, "0" ]] 7. Security Considerations All security considerations of JMAP [RFC8620] and of the specifications defining each supported data type apply. Deleted items extend the time for which data stays reachable through the account. Anyone who gains access to an account, through stolen credentials or a delegated session, can read recently destroyed data as well as current data. Deleting something sensitive does not protect it from such a person until it has been purged. Clients SHOULD make purging easy to find. In shared accounts, deleted items can disclose what another user deleted and when. The visibility rule in Section 3.3 limits this to people who could already read the object. A server that cannot track this reliably SHOULD show deleted items only to the account's owner. Restoring an object recreates content that may have been destroyed because it was harmful, such as a phishing message removed by an administrator or by a filter. Servers MAY refuse to keep deleted items for objects removed for such reasons, and MAY refuse to restore them with "forbidden". Coffey Expires 30 April 2027 [Page 15] Internet-Draft JMAP Undelete October 2026 Restoring a SieveScript must not change how incoming mail is handled without the user's deliberate action. This is why a restored script is always inactive (Section 3.9.3). DeletedItem/restore can create many objects in one call. Servers apply the "maxObjectsInSet" limit and their normal rate limits to it, as they would to /set. 8. Privacy Considerations Users expect deletion to remove data. Keeping deleted data, even for a short time, has to be visible to the user and under their control. This extension does both: "retentionPeriod" and "expiresAt" say how long data is kept, and DeletedItem/set lets the user purge it at once when "mayPurge" is true. Servers SHOULD set "mayPurge" to true for the account's owner, so that a user can make a deletion final. Operators may have legal or contractual reasons to keep data longer than the user can see it, such as a litigation hold. Such retention is outside the scope of this extension. A server that keeps data after a purge or after expiry MUST NOT offer it through this extension, and operators are expected to tell users of such policies through other means. The "snapshot" and the blob hold the same personal data as the destroyed object. Data protection rules that apply to the object apply equally to them. 9. IANA Considerations 9.1. JMAP Capability Registration for "undelete" IANA is requested to register the "undelete" JMAP Capability as follows: Capability Name: urn:ietf:params:jmap:undelete Specification document: this document Intended use: common Change Controller: IETF Security and privacy considerations: this document, Section 7 and Section 8 9.2. JMAP Data Type Registration for "DeletedItem" IANA is requested to register "DeletedItem" in the "JMAP Data Types" registry as follows: Type Name: DeletedItem Coffey Expires 30 April 2027 [Page 16] Internet-Draft JMAP Undelete October 2026 Can Reference Blobs: Yes Can Use for State Change: Yes Capability: urn:ietf:params:jmap:undelete Reference: this document 10. Implementation Status This section is to be removed before publishing as an RFC. This section records the status of known implementations of the protocol defined by this specification at the time of posting of this Internet-Draft, and is based on a proposal described in [RFC7942]. inbuxa server, an open-source (AGPL-3.0) mail and collaboration server from Coffey Labs, keeps and restores deleted Email, ContactCard, CalendarEvent, FileNode, and SieveScript objects with the restoration rules described here, through its own interface. The JMAP interface in this document is not implemented yet. An implementation is planned. 11. References 11.1. Normative References [I-D.ietf-jmap-calendars] Jenkins, N. and M. Douglass, "JSON Meta Application Protocol (JMAP) for Calendars", Work in Progress, Internet-Draft, draft-ietf-jmap-calendars-33, 13 October 2026, . [I-D.ietf-jmap-filenode] Gondwana, B., "JMAP File Storage extension", Work in Progress, Internet-Draft, draft-ietf-jmap-filenode-19, 28 October 2026, . [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, . [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, . Coffey Expires 30 April 2027 [Page 17] Internet-Draft JMAP Undelete October 2026 [RFC8620] Jenkins, N. and C. Newman, "The JSON Meta Application Protocol (JMAP)", RFC 8620, DOI 10.17487/RFC8620, July 2019, . [RFC8621] Jenkins, N. and C. Newman, "The JSON Meta Application Protocol (JMAP) for Mail", RFC 8621, DOI 10.17487/RFC8621, August 2019, . [RFC8984] Jenkins, N. and R. Stepanek, "JSCalendar: A JSON Representation of Calendar Data", RFC 8984, DOI 10.17487/RFC8984, July 2021, . [RFC9553] Stepanek, R. and M. Loffredo, "JSContact: A JSON Representation of Contact Data", RFC 9553, DOI 10.17487/RFC9553, May 2024, . [RFC9610] Jenkins, N., Ed., "JSON Meta Application Protocol (JMAP) for Contacts", RFC 9610, DOI 10.17487/RFC9610, December 2024, . [RFC9661] Murchison, K., "The JSON Meta Application Protocol (JMAP) for Sieve Scripts", RFC 9661, DOI 10.17487/RFC9661, September 2024, . [RFC9670] Jenkins, N., Ed., "JSON Meta Application Protocol (JMAP) Sharing", RFC 9670, DOI 10.17487/RFC9670, November 2024, . 11.2. Informative References [IANA-JMAP] IANA, "JSON Meta Application Protocol (JMAP)", . [RFC5228] Guenther, P., Ed. and T. Showalter, Ed., "Sieve: An Email Filtering Language", RFC 5228, DOI 10.17487/RFC5228, January 2008, . [RFC7942] Sheffer, Y. and A. Farrel, "Improving Awareness of Running Code: The Implementation Status Section", BCP 205, RFC 7942, DOI 10.17487/RFC7942, July 2016, . Coffey Expires 30 April 2027 [Page 18] Internet-Draft JMAP Undelete October 2026 [RFC9051] Melnikov, A., Ed. and B. Leiba, Ed., "Internet Message Access Protocol (IMAP) - Version 4rev2", RFC 9051, DOI 10.17487/RFC9051, August 2021, . [RFC9425] Cordier, R., Ed., "JSON Meta Application Protocol (JMAP) for Quotas", RFC 9425, DOI 10.17487/RFC9425, June 2023, . Appendix A. Open Issues This section is to be removed before publishing as an RFC. * Should a restored object keep its old id when the server can guarantee it was never reused? Keeping it helps clients that cached the object; a new id is simpler and matches what clients already handle for created objects. * Destroyed containers (Mailbox, AddressBook, Calendar) are not recoverable here; only their contents are. Is container recovery needed, or is restoring contents to the default container enough? * Restoring large FileNode trees may need an asynchronous form, or a "restore with children" option. * Should a /set destroy response optionally return the ids of the DeletedItems it created, to save the "Undo" lookup? * Whether an IMAP or WebDAV counterpart is wanted, or JMAP alone is enough. Author's Address John Coffey Coffey Labs LLC Arizona United States of America Email: john@coffeylabs.org URI: https://coffeylabs.org Coffey Expires 30 April 2027 [Page 19]