Inbox
When a messaging client starts, it typically builds a UI showing a list of recent chats, with metadata attached to them like, whether any chat has new messages and how many, or if it is fully read, or if they are for example muted and until when. In MongooseIM this functionality is provided by mod_inbox.
Terminology:
The Inbox
It is personal to a given user and represents the current status of the conversations of that user. It's the front-page of the chat feature.
Inbox entry
It is a specific conversation, that the user can identify by the recipient jid, that is, the user jid in case of a one-to-one chat, or the room jid in case of a group-chat.
Box (also referred to as "folder")
A category where entries can be classified. The default box is the active box, simply called inbox. There is a second box, called archive, where entries can be thrown into and not displayed by default. More boxes can be created through configuration.
Entity Use Cases
Discovering Inbox Services
An entity can discover the inbox service via a Features Discovery request:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Fetching the inbox
Querying
The inbox is fetched using regular XMPP Data Forms. To request the supported form, the client should send:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
To fetch the inbox, the client should send:
1 2 3 |
|
Then the client should receive:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
message
stanzas are sent to the requesting resource describing each inbox entry, and a final iq-fin
stanza marks the end of the inbox query,
Inbox query result IQ stanza returns the following values:
count
: the total number of conversations (ifhidden_read
value was set to true, this value will be equal toactive_conversations
)unread-messages
: total number of unread messages from all conversationsactive-conversations
: the number of conversations with unread message(s)
Note that the queryid
field is optional, and if not provided, the answers will fall back to the id
field of the IQ query.
Filtering and ordering
Inbox query results may be filtered by time range and box, and sorted by timestamp.
By default, mod_inbox
returns all conversations, listing the ones updated most recently first.
A client may specify the following parameters:
- variable
start
: Start date for the result set (value: ISO timestamp) - variable
end
: End date for the result set (value: ISO timestamp) - variable
order
: Order by timestamp (values:asc
,desc
) - variable
hidden_read
: Show only conversations with unread messages (values:true
,false
) - variable
box
: Indicate which box is desired. Supported areall
,inbox
,archive
andbin
. More boxes can be implemented, see mod_inbox – Boxes. If not provided, all except the bin are returned. - variable
archive
[deprecated, preferbox
]: whether to query the archive inbox.true
means querying only the archive box,false
means querying only the active box. If the flag is not set, it is assumed all entries are requested. This is kept for backwards compatibility reasons, use thebox
flag instead.
They are encoded inside a standard XMPP Data Forms format.
Dates must be formatted according to XMPP Date and Time Profiles.
It is not mandatory to add an empty data form if a client prefers to use default values (<inbox/>
element may be empty).
However, the IQ type must be "set", even when the data form is missing.
Limiting the query
It can happen that the amount of inbox entries is too big for a given user, even after filtering by start
and end
as already available in mod_inbox. Hence, we need to set a fixed limit of the number of entries that are requested. For this, we can use a <max>
attribute as defined in XEP-0059: #2.1 Limiting the Number of Items:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Max
is a non-negative integer.
Inbox also has partial support for pagination as described in XEP-0059. Note that therefore there are two ways to denote pages, the standard RSM mechanism and the custom inbox form. If both are used, the RSM marker will override the respective inbox form, as in, before
will override start
, and after
will override end
.
Note
Inbox pagination does not support total count nor indexes as described in XEP-0059: #2.6 Retrieving a Page Out of Order.
Properties of an entry
Given an entry, certain properties are defined for such an entry:
Box
Clients usually have two different boxes for the inbox: the regular one, simply called the inbox (or the active inbox), and an archive box, where clients can manually throw conversations they don't want displayed in the default UI. A third box is the trash bin, where deleted entries go and are cleaned up in regular intervals.
It is expected that entries will reside in the archive until they're either manually moved back to the active box, or they receive a new message: in such case the entry should jump back to the active box automatically.
More boxes can be implemented, see mod_inbox#boxes. Movement between boxes can be achieved through the right XMPP IQ, no more automatic movements are developed as in the case of inbox-archive.
Read
Entries keep a count of unread messages that is incremented automatically upon receiving a new message, and (in the current implementation) set to zero upon receiving either a message by one-self, or an appropriate chat marker as defined in XEP-0333 (which markers reset the count is a matter of configuration, see doc).
This property can also be manually set to zero or to one using the appropriate requests as explained below.
Muted
Entries can be muted for given periods of time, and likewise, unmuted. This changes the UI representation, and also, means that the user won't get PNs (Push Notifications) for this entry, until the time set expires, or the user sets otherwise. Knowledge of this is necessary to help build the UI.
Expected times can be extended before the period has expired, without the need to first unmuting. When muting a conversation, the final timestamp will be calculated by the server as the current time plus the requested period, in seconds, to centralise knowledge of UTC clocks. When muting an already muted conversation, the timestamp is simply overridden following the previous specification.
Other properties
No more properties are expected, but one could envisage notions of flagging conversations with different colours, for example according to their urgency, or a client-specific category (work, personal, fitness, and whatnot), or pins to denote an entry should be always displayed (possibly in a special format, like on top of the box). The design of the protocol, and the implementation, aims to leave room for future extensions.
Getting properties
To fetch all supported properties, a classic Data Form is used. Upon the client sending an iq-get without a jid:
1 2 3 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
If the properties of a certain entry were to be fetched, it can easily be done with:
1 2 3 |
|
1 2 3 4 5 6 7 8 |
|
If an entire entry wanted to be queried, and not only its attributes, a complete='true'
can be provided:
1 2 3 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Setting properties
Setting properties is done using the standard XMPP pattern of iq-query
and iq-result
, as below:
1 2 3 4 5 6 |
|
Property
and Value
are a list of key-value pairs as follows:
box
:inbox
,archive
, or a custom value if this has been extended.archive
:true
orfalse
mute
: number of seconds to mute for. Choose0
for unmuting.read
(adjective, not verb):true
orfalse
. Setting to true essentially sets the unread-count to0
,false
sets the unread-count to1
(if it was equal to0
, otherwise it lefts it unchanged). No other possibilities are offered, to reduce the risk of inconsistencies or problems induced by a faulty client.
Note that resetting the inbox count will not be forwarded. While a chat marker will be forwarded to the interlocutor(s), (including the case of a big groupchat with thousands of participants), this reset stanza will not.
If the query was successful, the server will answer with two stanzas, following the classic pattern of broadcasting state changes. First, it would send a message with a <x>
children containing all new configuration, to the bare-jid of the user: this facilitates broadcasting to all online resources to successfully synchronise their interfaces.
1 2 3 4 5 6 7 8 |
|
<mute>
may contain either a zero, to denote unmuted, or a RFC3339 timestamp, as in 2021-02-25T08:44:14.323836Z
.
To the requesting resource, a simple iq-result would be then sent to notify of success, as required by the iq directives of the XMPP RFCs:
1 |
|
If the request was not successful, the server would then answer as in:
1 2 3 4 5 |
|
Type
will usually be modify
or cancel
, as explained in https://xmpp.org/rfcs/rfc6120.html#stanzas-error-syntax, and Condition
is as explained in https://xmpp.org/rfcs/rfc6120.html#stanzas-error-conditions, bad-request
being the most common.
This final syntax for the protocol has been chosen as it allows for better pipelining of requests, and it remains consistent with how, for example, rooms are configured for MUC-Light.
Examples: archiving an entry
To put an entry into the archived box, the client can send:
1 2 3 4 5 |
|
1 2 3 4 5 6 7 8 |
|
1 2 3 4 5 |
|
Examples: emptying the trash bin
A user can empty his trash bin, through the following request:
1 2 3 |
|
1 2 3 4 5 |
|
Examples: muting an entry
To mute an entry for a full day (86400 seconds in a day, 604800 in a week, for example), a client can send:
1 2 3 4 5 |
|
1 2 3 4 5 6 7 8 |
|
1 2 3 4 5 |
|
1 2 3 4 5 |
|
Examples: reading an entry
To set an entry as read, the client can send:
1 2 3 4 5 |
|
1 2 3 4 5 6 7 8 |
|
1 2 3 4 5 |
|
1 2 3 4 5 |
|
Deprecated reset entry stanza:
You can reset the inbox with the following stanza:
1 2 3 |
|
jid
is the bare jid of the user whose inbox we want to reset. This action
does not change the last message stored in inbox; meaning that neither this
stanza nor anything given within will be stored; the only change is the inbox
unread_count
is set to zero.
Example request
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
|
Example error response
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|