JMAP recoverable mail
The Nixt Server JMAP extension for listing and putting back mail a person deleted that can still be got back.
This page defines a small JMAP extension. Its capability is named by this page’s address:
https://nixtoffice.com/docs/server/jmap-recoverable
With it, an app shows a person the mail they deleted that can still be got back, and puts it back. Nixt Mail uses it for Recover items deleted from Trash, and any JMAP client may. What happens to deleted mail on a Nixt Server is described in Getting deleted mail back.
The capability
The session lists the capability, with an empty object, in capabilities and in the accountCapabilities of the person’s own account:
"https://nixtoffice.com/docs/server/jmap-recoverable": {}
An account the person reaches as somebody else’s delegate does not offer it: a person’s deleted mail is theirs alone, and a request naming such an account is refused.
A request that uses the methods below names the capability in using, beside urn:ietf:params:jmap:core and urn:ietf:params:jmap:mail.
The deleted mail is kept in a mailbox that is never listed, so no mail app sees it as a mailbox or its messages as Email objects. These methods are the only way to it.
RecoverableEmail/get
Lists what can be got back, the most recently deleted first.
| Argument | Type | Meaning |
|---|---|---|
accountId | Id | The account. |
search | String or null | Words the sender, the subject or the folder it was deleted from must contain, in any case. |
after | UTCDate or null | Only mail deleted at or after this moment. |
before | String or null | The next value a previous answer gave, to read the next page. |
limit | UnsignedInt or null | How many to answer, at most 500. |
The answer:
| Property | Type | Meaning |
|---|---|---|
accountId | Id | The account. |
list | Object[] | The deleted messages, each with id (the Email id it had, and has again once put back), from, subject, receivedAt, deletedAt, size and mailboxName, the folder it was deleted from. |
next | String or null | Pass as before for the next page; null when there is no more. |
total | UnsignedInt | How many messages can be got back. |
size | UnsignedInt | How many bytes they take, which count toward the account’s quota until the window ends. |
windowDays | UnsignedInt | The organisation’s window, in days. |
RecoverableEmail/restore
Puts messages back.
| Argument | Type | Meaning |
|---|---|---|
accountId | Id | The account. |
ids | Id[] | The messages to put back, by the id from RecoverableEmail/get. |
Each message goes back to the mailbox it was deleted from, or to the Inbox if that mailbox is gone, without the $deleted keyword. The answer:
| Property | Type | Meaning |
|---|---|---|
accountId | Id | The account. |
restored | Id[Object] | For each message put back, mailboxId, the mailbox it is in now, and whereItWas, whether that is the one it was deleted from. |
notRestored | Id[SetError] | For each id that is not deleted mail that can be got back, a notFound error. |
oldState, newState | String | The account’s Email state before and after, since putting mail back changes it. |
RecoverableEmail/destroy
Deletes messages for good, before the recovery window ends.
| Argument | Type | Meaning |
|---|---|---|
accountId | Id | The account. |
ids | Id[] | The messages to delete for good, by the id from RecoverableEmail/get. |
The messages can’t be got back afterwards. If the organisation keeps the account’s mail under a legal hold or a retention policy, the server still keeps them, out of the person’s sight, as it would at the end of the window. The answer:
| Property | Type | Meaning |
|---|---|---|
accountId | Id | The account. |
destroyed | Id[] | The messages deleted for good. |
notDestroyed | Id[SetError] | For each id that is not deleted mail that can be got back, a notFound error. |
oldState, newState | String | The account’s Email state before and after. |
Example
[["RecoverableEmail/get", {
"accountId": "a1",
"search": "invoice",
"limit": 20
}, "0"]]
[["RecoverableEmail/restore", {
"accountId": "a1",
"ids": ["m42"]
}, "1"]] Something unclear or out of date on this page? Tell us.