├── README.md ├── coi-server-spec.md ├── LICENSE ├── webpush-spec.md └── coi-client-spec.md /README.md: -------------------------------------------------------------------------------- 1 | # COI-Specs 2 | The open specification for COI compatible clients. 3 | 4 | * [COI Client Spec](coi-client-spec.md) 5 | * [COI Server Spec](coi-server-spec.md) 6 | * [WebPush IMAP Extension Spec](webpush-spec.md) 7 | * [SMTP: Submission Token Extension Draft](https://datatracker.ietf.org/doc/draft-slusarz-extra-smtp-submission-token/) 8 | 9 | # What is COI 10 | COI is an open chat communication standard built on top of IMAP and SMTP. 11 | COI is a combination of the COI Standard plus compatible Client Apps and Email Servers. 12 | COI works with all email servers, but IMAP servers can be enhanced with extra COI capabilities. 13 | 14 | # COI Principles 15 | The principle of COI is very simple: COI uses IMAP/SMTP as the transport mechanism for a chat application. 16 | The generic steps are as follows: 17 | 1. Establish a connection with an SMTP server (Send) and an IMAP server (Receive) 18 | 2. Establish the capabilities of the IMAP server. This determines how you communicate with it 19 | 3. Send chat messages over SMTP, receive messages over IMAP 20 | 21 | # COI Now & Soon 22 | Today, you can use COI to communicate with other compatible messengers over existing IMAP and SMTP servers. 23 | Soon, additional functionalities will be made available by COI compatible IMAP servers. Example for such features are automated filtering between normal mail messages and chat messages, server-side blocking of contacts, support for push notifications, channels, WebRTC and much more. 24 | 25 | # Required Knowledge 26 | To build a COI application you need to know the following: 27 | • How to communicate with IMAP and SMTP servers - This is usually done by using a native email library. 28 | • A good understanding of the COI protocol in both its variants (COI over simple IMAP servers and COI over COI extended IMAP servers). 29 | • Know how to build your desired application. 30 | • A basic understanding of the structure of SMTP/IMAP messages - Specifically an working knowledge of RFC 5322, but reading the COI protocol should give you most of what you need. 31 | 32 | # What you need 33 | As a client developer, you have several options: 34 | • Communicate with the email server using an IMAP library for your preferred language & platform – or even communicate directly when you feel adventurous. 35 | • Base your work on Delta Chat Core, an MPL licensed library that abstracts away IMAP communication and that will become COI compliant. 36 | • Base your work on an existing COI compatible app, like the cross-platform OX Talk app. 37 | 38 | Visist https://coi-dev.org for more details. 39 | -------------------------------------------------------------------------------- /coi-server-spec.md: -------------------------------------------------------------------------------- 1 | # COI Server Spec v1.0 2 | 3 | ## Status & Discussion 4 | Status: DRAFT 5 | 6 | ## Introduction 7 | COI - Chat Over IMAP - provides a basis for realizing modern messaging services on top of the existing email infrastructure. COI leverages the existing open and federated email infrastructure to provide an open chat functionality accessible to everyone with an email address. 8 | 9 | COI is designed to work (fallback mode) with existing, non COI-compliant IMAP4rev1 servers and IMAP4rev1 clients. A COI-compliant server provides additional, optional features and optimizations recommended to both improve the COI user experience and make server handling of COI messages more efficient. This specification describes the functionality of a COI-compliant server. 10 | 11 | COI is not limited to IMAP; it is abstracted to allow any message accessing protocol (e.g. JMAP) to handle the data. However, non COI-compliant server behavior was modeled on a base IMAP4rev1 server, as it is the most ubiquitous message retrieval protocol at the time it was designed, so this version of the specification focuses exclusively on IMAP behavior. A future version of the spec may be extended to other protocols. 12 | 13 | ## Conventions Used in This Document 14 | In examples, "C:" indicates lines sent by a client that is connected to a server. "S:" indicates lines sent by the server to the client. 15 | 16 | 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](https://tools.ietf.org/html/bcp14) [[RFC2119](https://tools.ietf.org/html/rfc2119)] [[RFC8174](https://tools.ietf.org/html/rfc8174)] when, and only when, they appear in all capitals, as shown here. 17 | 18 | ## COI Actors 19 | In a typical COI setup the following actors are involved: 20 | 21 | * A service/protocol ("server") for retrieving the message data, e.g. IMAP. The server may or may not be COI-compatible. A COI compatible server is called "COI server" or just "server" in this specification. 22 | * An SMTP service for sending messages. Sending services are also called Mail Transfer Agents (MTAs). 23 | * Clients that access the server. 24 | 25 | ## Required Standards 26 | ### IMAP 27 | An IMAP COI server MUST implement the following standards: 28 | 29 | * IMAP 4rev1 [[RFC 3501](https://tools.ietf.org/html/rfc3501)] 30 | A subset of IMAP METADATA Extension [[RFC 5464](https://tools.ietf.org/html/rfc5464)]; REQUIRES support for private annotations, see below 31 | * [IMAP WebPush Extension](webpush-spec.md) 32 | 33 | #### Scope of METADATA Support 34 | A COI server MUST support the following subset of the IMAP METADATA Extension [[RFC 5464](https://tools.ietf.org/html/rfc5464)] standard: 35 | 36 | * `SETMETADATA` calls with the paths and value restrictions defined in this document as well as in the IMAP WebPush Extension v1.0. 37 | * `GETMETADATA` calls with the paths defined in this document as well as in the IMAP WebPush Extension v1.0, this included support for the `DEPTH` parameter. 38 | 39 | A COI server MAY announce the METADATA capability to clients. A COI server MAY reject any paths that are not defined in this document or in IMAP WebPush Extension v1.0. 40 | 41 | ## Recommended Standards 42 | ### IMAP 43 | The following standards are RECOMMENDED to be supported by a COI server: 44 | 45 | * IMAP4 IDLE Command [[RFC 2177](https://tools.ietf.org/html/rfc2177)] and IMAP NOTIFY Extension [[RFC 5465](https://www.rfc-archive.org/getrfc.php?rfc=5465)] 46 | 47 | *Used to poll for new messages* 48 | * IMAP4 Binary Content Extension [[RFC 3516](https://tools.ietf.org/html/rfc3516)] 49 | 50 | *Used to reduce traffic between client and server* 51 | * IMAP Extension for Referencing the Last SEARCH Result [[RFC 5182](https://tools.ietf.org/html/rfc5182)] and IMAP ESORT Extension [[RFC 5267](https://tools.ietf.org/html/rfc5267)] 52 | 53 | *Improves efficiency of client sync* 54 | * IMAP4 Quick Flag Changes Resynchronization (CONDSTORE) and Quick Mailbox Resynchronization (QRESYNC) [[RFC 7162](https://tools.ietf.org/html/rfc7162)] 55 | 56 | *Improves efficiency of client sync* 57 | 58 | ## COI Capability 59 | As COI implements functionality layered on top of the standard messaging protocols, it is necessary to be able to query a server to determine whether that server is COI-compatible. 60 | 61 | ### IMAP 62 | A COI IMAP server will advertise it's COI compatibility via the IMAP `CAPABILITY` response. 63 | 64 | For a COI server, the following capabilities MUST be listed in the response: 65 | 66 | * COI 67 | * WEBPUSH 68 | 69 | 70 | *Example:* 71 | 72 | ``` 73 | S: * OK IMAP Server 74 | C: a CAPABILITY 75 | S: * CAPABILITY IMAP4rev1 76 | S: a OK 77 | C: b LOGIN foo bar 78 | S: b OK Authentication successful. 79 | C: c CAPABILITY 80 | S: * CAPABILITY IMAP4rev1 COI WEBPUSH 81 | S: c OK 82 | ``` 83 | 84 | ## Getting COI Namespace Configuration 85 | Servers can be customized to use different namespaces. 86 | 87 | ### IMAP 88 | Servers MUST provide the configuration using a `GETMETADATA` call with using the `/private/vendor/vendor.dovecot/coi/config` path prefix. 89 | 90 | The following settings can be available under this config path, details are explained in the subsequent sections: 91 | 92 | * `mailbox-root` whose value contains the root mailbox name for COI-related messages. Servers MAY allow to set a user-individual `mailbox-root`. In the following the value of this setting is called *\*. 93 | * `enabled` which defines if COI is enabled for this user. 94 | * `message-filter` which defines the filtering of COI messages. 95 | Only mailbox-root MUST exist for any user of a COI server. 96 | 97 | *Example for reading configuration:* 98 | 99 | ``` 100 | C: a5 GETMETADATA (DEPTH 1) "" (/private/vendor/vendor.dovecot/coi/config) 101 | S: * METADATA "" (/private/vendor/vendor.dovecot/coi/config/enabled {3} 102 | yes /private/vendor/vendor.dovecot/coi/config/mailbox-root {3} 103 | COI /private/vendor/vendor.dovecot/coi/config/message-filter {6} 104 | active) 105 | S: a5 OK Getmetadata completed (0.001 + 0.000 secs). 106 | ``` 107 | 108 | *Example for unsuccessfully setting the `mailbox-root`:* 109 | 110 | ``` 111 | C: a SETMETADATA "" (/private/vendor/vendor.dovecot/coi/config/mailbox-root myroot) 112 | S: a NO [CANNOT] unable to set /private/vendor/vendor.dovecot/coi/config/mailbox-root 113 | ``` 114 | 115 | ## Configure COI Usage 116 | As COI implements functionality layered on top of the standard messaging protocols, it is necessary to enable COI behavior only in accounts that will use that behavior. 117 | 118 | ### IMAP 119 | Clients indicate their desire for a mail account to begin supporting server-side COI optimizations by issuing the `SETMETADATA` command using the `/private/vendor/vendor.dovecot/coi/config/enabled` path. 120 | 121 | Allowed values are: 122 | 123 | * `yes` for enabling COI. It is RECOMMENDED that this value is treated case-sensitive, i.e. only lower-case value are valid. 124 | * `NIL` for disabling COI. This removes the setting. 125 | 126 | Other values SHOULD result into a NO response. Any other value than `yes` SHOULD be interpreted as COI being disabled. 127 | 128 | When reading the state, clients should check if the path `/private/vendor/vendor.dovecot/coi/config/enabled` is present and if the value for it is `yes`. Only when both statements are true, COI is enabled for the user. 129 | 130 | When the COI is enabled by the client and before returning a tagged OK response, the server MUST do the following: 131 | 132 | * Check for the existence and create the following folders if they do not yet exist: 133 | * *\/Contacts* for retrieving configuration values from clients. By default this is the *COI/Contacts* folder. The folder MAY be marked as subscribed on behalf of the user. 134 | * *\/Chats* for storing chat messages. By default this is the *COI/Chats* folder. The folder SHOULD be marked as subscribed on behalf the user. Compare the message filtering section below for details. It is RECOMMENDED that this folder cannot be renamed by clients - or only renamed (moved) to the trash folder. 135 | * Evaluates the `/private/vendor/vendor.dovecot/coi/config/message-filter` configuration and initiates filtering accordingly, compare the filtering configuration section below. When the configuration is not specified, the default value `none` is assumed. 136 | 137 | When COI is disabled, the server SHOULD stop filtering COI messages. The server MAY stop adding the `$Chat` keyword to detected COI messages. The server MAY remove webpush registrations that apply to COI messages only. 138 | 139 | *Example for enabling COI:* 140 | 141 | ``` 142 | C: a SETMETADATA "" (/private/vendor/vendor.dovecot/coi/config/enabled yes) 143 | S: a OK SETMETADATA complete 144 | ``` 145 | 146 | *Example for disabling COI:* 147 | 148 | ``` 149 | C: a SETMETADATA "" (/private/vendor/vendor.dovecot/coi/config/enabled NIL) 150 | S: a OK SETMETADATA complete 151 | ``` 152 | 153 | *Example for invalid value:* 154 | ``` 155 | C: a SETMETADATA "" (/private/vendor/vendor.dovecot/coi/config/enabled true) 156 | S: a NO [CANNOT] invalid value for /private/vendor/vendor.dovecot/coi/config/enabled: "true" 157 | ``` 158 | 159 | ### Indirectly Disabling and Enabling COI 160 | It is RECOMMENDED that servers treat the deletion of the *\/Chats* folder as an indirect request to disable COI for the user. This allows users to disable COI without needing to use a COI compliant client. A deletion can either happen either directly with the IMAP `DELETE` command or indirectly by a `RENAME` operation that moves the *Chats* folder under a `\Trash` special-use or the default trash folder. It is RECOMMENDED to not allow other `RENAME` operations, such attempts are RECOMMENDED to be answered with NO. 161 | 162 | It is RECOMMENDED that servers treat the creation of the *\/Chats* folder as an indirect request to enable COI for the user. The creation can be done either with a `CREATE` or with a `RENAME` call. 163 | 164 | If the server indirectly enables or disables COI, it MUST also update the corresponding METADATA setting under `/private/vendor/vendor.dovecot/coi/config/enabled`. 165 | 166 | ## Configure Message Filtering 167 | For non-COI compatible servers, messages are required to be organized into the COI folder namespace via COI-client behavior. However, on COI compliant servers this can be done by the server. Once a user enables COI for an account, messages can be filtered automatically by the server at delivery, preventing the overhead of manual message manipulation on the client-side. 168 | 169 | COI messages are detected by having at least one these characteristics: 170 | 171 | * The `Chat-Version` header is present. 172 | * The `Message-ID` header starts with `chat$`. 173 | * The first message-ID in the `References` header starts with `chat$`. 174 | 175 | When a `message-filter` value of `active` or `seen` is present, a server MUST check for the existence and create the following folder if they do not yet exist: 176 | 177 | * *\/Chats* for moving COI messages, this defaults to *COI/Chats*. The folder SHOULD be marked as subscribed by the user. 178 | 179 | ### IMAP 180 | Clients configure the filtering for new incoming COI messages by using `SETMETADATA` command using the `/private/vendor/vendor.dovecot/coi/config/message-filter` path. 181 | 182 | The following filter modes MUST be supported using this meta data: 183 | 184 | * `none`: messages are not separated at all. This is the default value. 185 | * `active`: messages are moved to *\/Chats* folder. By default this is *COI/Chats*. 186 | * `seen`: messages stay in the *INBOX* folder until they are flagged with `\Seen` flag. When the COI server receives a `\Seen` flag for a COI message, then it will move the message like in the active mode. 187 | 188 | Servers MAY respond with NO when a different value is encountered. It is RECOMMENDED that values are treated case-sensitive, i.e. only lower-case values are valid. 189 | 190 | When a COI message has been detected, the server MUST mark the message with the *$Chat* keyword. 191 | 192 | If the server supports Sieve or other filtering mechanisms, COI message filter rules are RECOMMENDED be applied before any user-defined filtering rules are evaluated. Global filtering rules MAY be executed before applying COI message filter rules. It is RECOMMENDED to understand the Sieve keep rule so that COI messages will stay within *\/Chats* when the `message-filter` is set to `active`. 193 | 194 | COI message filter rules MUST be applied before the message is actually stored in the target mailbox, so that an existing IMAP `IDLE` command is not triggered for the *INBOX*, when a COI message is received and the `message-filter` rule is set to `active`. 195 | 196 | *Example for enabling active filtering:* 197 | 198 | ``` 199 | C: a SETMETADATA "" (/private/vendor/vendor.dovecot/coi/config/message-filter active) 200 | S: a OK SETMETADATA complete 201 | ``` 202 | 203 | *Example for invalid filtering value:* 204 | ``` 205 | C: a SETMETADATA "" (/private/vendor/vendor.dovecot/coi/config/message-filter inactive) 206 | S: a NO [CANNOT] invalid value for /private/vendor/vendor.dovecot/coi/config/message-filter: inactive 207 | ``` 208 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /webpush-spec.md: -------------------------------------------------------------------------------- 1 | # IMAP WebPush Extension v1.0 2 | ## Status & Discussion 3 | Status: DRAFT 4 | 5 | ## Introduction 6 | Historically, IMAP clients have used `IDLE` or `NOTIFY` to be notified about new messages. These methods require a persistent connection, which may be difficult for mobile clients. These mobile clients often require an external service that listens for incoming messages on behalf of the user; such services may require the user's credentials, which poses a security threat. 7 | 8 | This document describes a method to deliver push message to clients without storing user credentials and without persistent connections. 9 | 10 | ## Conventions Used in This Document 11 | In examples, "C:" indicates lines sent by a client that is connected to a server. "S:" indicates lines sent by the server to the client. 12 | 13 | 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](https://tools.ietf.org/html/bcp14) [[RFC2119](https://tools.ietf.org/html/rfc2119)] [[RFC8174](https://tools.ietf.org/html/rfc8174)] when, and only when, they appear in all capitals, as shown here. 14 | 15 | ## IMAP WebPush Actors 16 | In a typical setup the following actors are involved: 17 | 18 | * An IMAP WebPush-compatible client. Also called just "WebPush client" or "client" or "MUA" (Mail User Agent). 19 | * An IMAP server that supports WebPush as described in this specification. Such a compatible server is called "WebPush server" or just "server" in this specification. 20 | * A client-specific WebPush compliant web push service that allows clients to register push resources and that accepts push requests from the WebPush server. 21 | 22 | The following figure informs about the main flows in the push architecture. 23 | 24 | ``` 25 | +-------+ +--------------+ +--------------+ 26 | | MUA | | Push Service | | IMAP WebPush | 27 | +-------+ +--------------+ | Server | 28 | | | +--------------+ 29 | | Subscribe | | 30 | |--------------------->| | 31 | | Monitor | | 32 | |<====================>| | 33 | | | | 34 | | Distribute Push Resource | 35 | |-------------------------------------------->| 36 | | | | 37 | | | Validation Message | 38 | | Validation Message |<---------------------| 39 | |<---------------------| | 40 | | | | 41 | | Validate Push Resource | 42 | |-------------------------------------------->| 43 | : : : 44 | | | Push Message | 45 | | Push Message |<---------------------| 46 | |<---------------------| | 47 | | | | 48 | ``` 49 | Figure 1: IMAP WebPush Architecture 50 | 51 | ## Required Standards 52 | The IMAP WebPush Extension is based on the following standards: 53 | * Generic Event Delivery Using HTTP Push [[RFC 8030](https://tools.ietf.org/html/rfc8030)] 54 | * Voluntary Application Server Identification (VAPID) for Web Push [[RFC 8292](https://tools.ietf.org/html/rfc8292)] 55 | * Message Encryption for Web Push [[RFC 8291](https://tools.ietf.org/html/rfc8292)] 56 | 57 | ### IMAP 58 | These IMAP extensions are REQUIRED: 59 | * IMAP4rev1 [[RFC 3501](https://tools.ietf.org/html/rfc3501)] 60 | * A subset of IMAP METADATA Extension [[RFC 5464](https://tools.ietf.org/html/rfc5464)]; REQUIRES support for private annotations (see below) 61 | 62 | These IMAP extensions are RECOMMENDED: 63 | * IMAP4 Non-synchronizing Literals [[RFC 7888](https://tools.ietf.org/html/rfc5464)] 64 | 65 | #### Scope of METADATA Support 66 | A WebPush server MUST support the following subset of the IMAP METADATA Extension [[RFC 5464](https://tools.ietf.org/html/rfc5464)] standard: 67 | 68 | * `SETMETADATA` calls with the paths and value restrictions defined in this document. 69 | * `GETMETADATA` calls with the paths defined in this document and support for the `DEPTH` parameter. 70 | 71 | A WebPush server is not required to announce the `METADATA` capability to clients. A WebPush server MAY reject any paths that are not defined in this document. 72 | 73 | In this specification draft, a vendor specific prefix is used as part of the `METADATA` path (*vendor.dovecot*). It is planned that this path will change in the future (e.g. to *webpush*) once this standard is officially recognized. 74 | 75 | ## Capability 76 | The server MUST advertise the `WEBPUSH` capability to announce compliance with this specification. This capability SHOULD NOT be advertised in non-authenticated state. 77 | 78 | *Example:* 79 | ``` 80 | S: * OK IMAP Server 81 | C: a CAPABILITY 82 | S: * CAPABILITY IMAP4rev1 83 | S: a OK 84 | C: b LOGIN foo bar 85 | S: b OK [CAPABILITY IMAP4rev1 WEBPUSH] Authentication successful. 86 | ``` 87 | 88 | ## VAPID Key 89 | Push services need to verify if a push request is coming from a valid source. This is done by signing the push request headers with the VAPID key (see [[RFC 8292](https://tools.ietf.org/html/rfc8292)] for details). 90 | 91 | Clients can determine the VAPID key by using the `GETMETADATA` command. The VAPID key MAY be user-specific or shared among all clients connected to an IMAP server. It is located at */private/vendor/vendor.dovecot/webpush/vapid*. 92 | 93 | The server MUST return the VAPID key in the base 64-encoded form of the PEM encoded key, for details compare [[RFC 1421](https://tools.ietf.org/html/rfc1421)]. 94 | 95 | *Example:* 96 | ``` 97 | C: a GETMETADATA "" /private/vendor/vendor.dovecot/webpush/vapid 98 | S: * METADATA "" (/private/vendor/vendor.dovecot/webpush/vapid {133} 99 | S: -----BEGIN PUBLIC KEY----- 100 | S: MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgACYHfTQ0biATut1VhK/AW2KmZespz+ 101 | S: DEQ1yH3nvbayCuY= 102 | S: -----END PUBLIC KEY-----) 103 | S: a OK Getmetadata completed (0.130 + 0.000 + 0.129 secs). 104 | ``` 105 | ## Subscriptions 106 | WebPush subscriptions are stored in the */private/vendor/vendor.dovecot/webpush/subscriptions/* path. Clients can register and manage subscriptions. 107 | 108 | ### Subscribe 109 | A WebPush server MUST support subscribing to push events. 110 | 111 | Clients can subscribe to push notifications by storing a subscription with a `SETMETADATA` call that specifies the push details as a server annotation. The metadata entry name MUST start with */private/vendor/vendor.dovecot/webpush/subscriptions/* followed by the client-generated, unique ID of the push registration. 112 | 113 | The push registration ID MUST follow the following constraints: 114 | 115 | * The push registration ID MUST only contain ASCII alphanumeric or minus or underline characters: `[0-9A-Za-z_-]`. 116 | * The push registration ID MUST be at least 10 and at most 36 characters long. 117 | 118 | Accepted contents for the data is a JSON-serialized object with the following entries: 119 | 120 | * `client`: the name of the client (string, max-length is 128 octets) 121 | * `device`: the name of the device (string, max-length is 128 octets) 122 | * `msgtype`: string, the type of messages for which notifications are requested. Possible values are: 123 | * `"chat"`: for chat messages, for the purpose of this documentation a chat email message is marked with the $Chat keyword . Compare for example the [COI Server Specification v1.0](coi-server-spec.md) for how to detect chat messages. 124 | * `"mail"`: for standard mail messages, excluding chat email messages. 125 | * `"all"`: for both standard mail and chat messages. 126 | * resource: object, the push resource as specified by [[RFC 8030](https://tools.ietf.org/html/rfc8030)] and [[RFC 8292](https://tools.ietf.org/html/rfc8292)] with the children `endpoint` and `keys`. 127 | * `endpoint` specifies the URL for sending push requests (string, max length is 512 octets). 128 | * `keys` specifies the encryption keys: 129 | * `p256dh`: contains the client-generated key for encryption message payload. The key used Elliptic Curve Diffie-Hellman (ECDH) on the P-256 curve as defined by [[RFC 8291](https://tools.ietf.org/html/rfc8291)] (string, max-length is 256 octets). 130 | * `auth`: 16-octets long client-generated symmetric secret used for the key generation as defined by [[RFC 8291 section 3.2](https://tools.ietf.org/html/rfc8291#section-3.2)]. 131 | 132 | It is RECOMMENDED to treat `msgtype` values case sensitive and to not allow any other values than specified above. 133 | 134 | The server SHOULD ignore unknown key value pairs in the provided JSON structure, meaning they will not be saved. 135 | 136 | When the server has received a new subscription, the server MUST add the created JSON element, which is a [[ISO 8601](https://tools.ietf.org/html/rfc8291#section-3.2)] formatted date time with the server's date and time of the subscription creation. The server MAY create the `validated` JSON element, which is false by default until the subscription has been validated, compare the "Validate New Subscriptions" section. 137 | 138 | A server MUST allow several clients to be subscribed at the same time. The server is, however, RECOMMENDED to limit the number of concurrent subscriptions. If the maximum number is hit, it MUST answer a subscription request with `NO`. The client then needs to remove an existing subscription first. 139 | 140 | 141 | 142 | *Example for subscribing for receiving push notifications when Literal+ is supported [[RFC 7888](https://tools.ietf.org/html/rfc7888)]:* 143 | ``` 144 | C: a SETMETADATA "" (/private/vendor/vendor.dovecot/webpush/subscriptions/31754ee7-d3ee-4226-b112-6895ed26fcf8 {370+} 145 | { 146 | "client": "My awesome WebPush App", 147 | "device": "My Favorite Smartphone", 148 | "msgtype": "chat", 149 | "resource": 150 | { 151 | "endpoint": "https://my-push-service.com/some-kind-of-unique-id-1234/v2/", 152 | "keys": { 153 | "p256dh": "BNcRdreALRFXTkOOUHK1E...P7DkM=", 154 | "auth": "tBHItJI5svbpez7KI4CCXg==" 155 | } 156 | } 157 | } 158 | ) 159 | S: a OK SETMETADATA complete 160 | ``` 161 | 162 | ### Validate New Subscriptions 163 | Every actor within a web push subscription has an interest to validate push subscriptions to ensure that every actor is legitimate. 164 | 165 | This is done by using the following steps: 166 | 167 | * The server sends a validation push message request. 168 | * This allows the push service to validate that a newly created push resource is actively being used. The push service also forwards the validation message to the client. 169 | * This allows the client to validate that the server is actually fully webpush compliant. The client decrypts the validation message and uses that to validate the original subscription with the server. 170 | * This last step allows the server to validate that the whole webpush chain is compliant. 171 | 172 | #### Sending a Validation Push Message 173 | When a new subscription is registered, the server initiates the validation by sending a push notification with a simple `Application/JSON` payload that contains the single `validation` element. This element contains a text with a maximum size of 1kB that allows the server to validate the subscription later. How the server creates the validation is explicitly not specified. A server MAY sign a text and timestamp and use the signature for validation, for example. 174 | 175 | Additionally, the request towards the push service requires the additional HTTP header `WebPush-Validation` without any value. 176 | 177 | *Example payload:* 178 | ``` 179 | { 180 | "validation": "abc$123$..." 181 | } 182 | ``` 183 | #### Validating A Push Subscription 184 | When the client receives a validation message, it will validate the previous subscription by calling `SETMETADATA` with the same path as the original subscription followed by */validate*. The value is the received value of the validation JSON element of the validation message. 185 | 186 | When this `SETMETADATA` call is received within a certain timeframe - RECOMMENDED is 5 minutes - of sending the validation push message and with the correct value for the given subscription ID, the server MUST respond with OK. When more than the timeframe has passed, or the validate text is invalid or the subscription ID does not match, the server MUST respond with NO. 187 | 188 | When no validation is received within the timeframe after creation, the server SHOULD discard the subscription and the client needs to regenerate it. 189 | 190 | *Example code for validating a subscription within the required timeframe:* 191 | ``` 192 | C: a SETMETADATA "" (/private/vendor/vendor.dovecot/webpush/subscriptions/31754ee7-d3ee-4226-b112-6895ed26fcf8/validate "abc$123$...") 193 | S: a OK SETMETADATA complete 194 | ``` 195 | *Example code for validating a subscription outside of the required timeframe or with an invalid value:* 196 | ``` 197 | C: a SETMETADATA "" (/private/vendor/vendor.dovecot/webpush/subscriptions/31754ee7-d3ee-4226-b112-6895ed26fcf8/validate "ZZZ000...") 198 | S: a NO [CANNOT] invalid validation 199 | ``` 200 | 201 | ### Unsubscribe 202 | To unsubscribe from push notification set the previously push annotation to `NIL`. 203 | 204 | *Example for unsubscribing from push notifications: * 205 | ``` 206 | C: a SETMETADATA "" (/private/vendor/vendor.dovecot/webpush/subscriptions/31754ee7-d3ee-4226-b112-6895ed26fcf8 NIL) 207 | S: a OK SETMETADATA complete 208 | ``` 209 | 210 | ### List Existing Subscriptions 211 | To list existing subscriptions, call `GETMETADATA` with a `DEPTH` of 1 to the path */private/vendor/vendor.dovecot/webpush/subscriptions*. 212 | 213 | Note that the server will also list the `created` key using a [[RFC 3339](https://tools.ietf.org/html/rfc3339)] format timestamp value and the `validated` key, which is either `true` or `false`. 214 | 215 | *Example for listing existing push notification subscriptions:* 216 | ``` 217 | C: a GETMETADATA (DEPTH 1) "" (/private/vendor/vendor.dovecot/webpush/subscriptions) 218 | S: * METADATA "" (/private/vendor/vendor.dovecot/webpush/subscriptions/123-123-123-123-123123 {380} 219 | S: {"created":"2019-10-16T16:14:17+00:00","validated":true,"client":"OX COI Messenger","device":"mydevicename","msgtype":"chat","resource":{"endpoint":"https://example.com:443/push/send/123-123-123-123","keys":{"p256dh":"keydata=","auth":"Authdata="}}}) 220 | a OK Getmetadata completed (0.002 + 0.000 + 0.001 secs). 221 | S: a OK GETMETADATA complete 222 | ``` 223 | 224 | ## Push Notification Payload 225 | An incoming message that matches subscription requirements and that is not a disposition notification message MUST trigger a notification of the corresponding endpoint of that subscription. 226 | 227 | ### Payload Data Format 228 | The server SHOULD include the following fields in an JSON object that is the payload. Note that if string fields have to be truncated, they MUST NOT truncated in the middle of an UTF8 sequence or the middle of any escape sequence such as `\uXXXX` or `\"`. 229 | 230 | * `from-email`: the lowercase UTF8 email address extracted from the `From` header, at least the first 100 bytes as a JSON string, if truncated followed by an ellipsis `U+2026`. 231 | * `from-name`: the name extracted from the `From` header, at least the first 100 bytes as a JSON string, if truncated followed by an ellipsis `U+2026`. If there is no name given, then this field SHOULD be omitted. 232 | * `subject`: as specified in the `Subject` header, at least the first 100 bytes as a JSON string, if truncated followed by an ellipsis `U+2026`. If no or only an empty Subject is defined, then this field SHOULD be omitted. 233 | * `content`: if the final encrypted payload stays under 4kB, the full body will be included. 234 | * `content-type`: if `content` is specified, then `content-type` SHOULD be specified, at the least the first 200 bytes as a JSON string, if truncated followed by an ellipsis `U+2026`. If `content-type` is `text/plain` this field SHOULD be omitted. 235 | * `content-encoding`: if `content` is specified, then `content-encoding` SHOULD be specified, unless it is `8bit`. 236 | * `date`: the date of the message in [[RFC 3339](https://tools.ietf.org/html/rfc3339)]-compatible timestamp, if no `Date` header is present, this field SHOULD be omitted. 237 | * `msg-id`: the ID of the incoming message (ASCII text), at least the first 100 bytes as a JSON string, if truncated followed by an ellipsis `U+2026`. 238 | * `uid`: the UID of the incoming message (32 bit integer) 239 | * `uidvalidity`: the UID validity of the folder (32 bit integer) 240 | * `folder`: the mailbox of the incoming message, if longer than 200 bytes as a JSON string this field SHOULD be omitted. 241 | 242 | When the server is compatible with the [COI Client Specification v1.0](coi-client-spec.md), then it SHOULD additionally provide the following fields: 243 | * `group-id`: the ID of the group extracted from the Message-ID or the References header, compare https://github.com/coi-dev/coi-specs/blob/master/coi-client-spec.md#group-messages. This field SHOULD be only present when the message is actually part of a group discussion. Max-length is 128 octets for this field. 244 | 245 | A push service is not required to support more than 4096 octets of payload body (see [Section 7.2 of [RFC8030](https://tools.ietf.org/html/rfc8030#section-7.2)]). Absent header (86 octets), padding (minimum 1 octet), and expansion for AEAD_AES_128_GCM (16 octets), this equates to, at most, 3993 octets of plaintext. 246 | 247 | *Example:* 248 | ``` 249 | { 250 | "from-email": "sender@domain.com", 251 | "from-name": "Alice", 252 | "subject": "Chat: Hello", 253 | "content": "--------------MIME-BOUNDARY------------\nContent-Type: application/octet-stream; name=\"encrypted.asc\"[...]", 254 | "content-encoding": "multipart/encryptedl;protocol=\"application/pgp-encrypted\";boundary=\"--------------MIME-BOUNDARY------------\"" 255 | "date": "2019-12-31T23:20:50.52Z", 256 | "msg-id": "chat$2923892892@domain.com", 257 | "uid": 2398293, 258 | "uidvalidity": 123287, 259 | "folder": "COI/Chats" 260 | } 261 | ``` 262 | ### Push Message Encryption 263 | Encrypting a push message uses Elliptic Curve Diffie-Hellman (ECDH) on the P-256 curve to establish a shared secret and a symmetric secret for authentication. 264 | 265 | A user agent generates an ECDH key pair and authentication secret that it associates with each subscription it creates. The ECDH public key and the authentication secret are sent to the application server with other details of the push subscription. 266 | 267 | When sending a message, an webpush server generates an ECDH key pair and a random salt. The ECDH public key is encoded into the `keyid` parameter of the encrypted content coding header, and the salt is encoded into the `salt` parameter of that same header (see [Section 2.1 of [RFC8188](https://tools.ietf.org/html/rfc8188#section-2.1)]). The ECDH key pair MUST be discarded after encrypting the message. 268 | 269 | The content of the push message is encrypted or decrypted using a content encryption key and nonce. These values are derived by taking the `keyid` and `salt` as input to the process described in [Section 3 of [RFC 8291](https://tools.ietf.org/html/rfc8291#section-3)]. 270 | 271 | The processes and details are described in detail in [[RFC 8291](https://tools.ietf.org/html/rfc8291#section-3)]. 272 | 273 | ### Header Signing 274 | A WebPush server MUST authorize their push requests by using the vapid HTTP authentication scheme as defined by [[RFC 8292](https://tools.ietf.org/html/rfc8292)]. This scheme consists of JSON Web Token (JWT) that contains several claims and that is signed. 275 | 276 | The "t" parameter of the Authorization header field contains a JWT; the "k" parameter includes the base64-url-encoded key that signed that token. 277 | 278 | *Example for VAPID header:* 279 | ``` 280 | Authorization: vapid 281 | t=eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJodHRwczovL3 282 | B1c2guZXhhbXBsZS5uZXQiLCJleHAiOjE0NTM1MjM3NjgsInN1YiI6Im1ha 283 | Wx0bzpwdXNoQGV4YW1wbGUuY29tIn0.i3CYb7t4xfxCDquptFOepC9GAu_H 284 | LGkMlMuCGSK2rpiUfnK9ojFwDXb1JrErtmysazNjjvW2L9OkSSHzvoD1oA, 285 | k=BA1Hxzyi1RUM1b5wjxsn7nGxAszw2u61m164i3MrAIxHF6YK5h4SDYic-dR 286 | uU_RCPCfA5aq9ojSwk5Y2EmClBPs 287 | ``` 288 | ### Push Message Example 289 | ``` 290 | POST /p/JzLQ3raZJfFBR0aqvOMsLrt54w4rJUsV HTTP/1.1 291 | Host: push.example.net 292 | TTL: 30 293 | Content-Length: 136 294 | Content-Encoding: aes128gcm 295 | Authorization: vapid 296 | t=eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJodHRwczovL3 297 | B1c2guZXhhbXBsZS5uZXQiLCJleHAiOjE0NTM1MjM3NjgsInN1YiI6Im1ha 298 | Wx0bzpwdXNoQGV4YW1wbGUuY29tIn0.i3CYb7t4xfxCDquptFOepC9GAu_H 299 | LGkMlMuCGSK2rpiUfnK9ojFwDXb1JrErtmysazNjjvW2L9OkSSHzvoD1oA, 300 | k=BA1Hxzyi1RUM1b5wjxsn7nGxAszw2u61m164i3MrAIxHF6YK5h4SDYic-dR 301 | uU_RCPCfA5aq9ojSwk5Y2EmClBPs 302 | { encrypted push message } 303 | ``` 304 | 305 | ### Push Service Response Codes 306 | Push services MUST deliver one of the following response codes for push requests: 307 | 308 | * `201 Created`. The request to send a push message was received and accepted. 309 | * `429 Too many requests`. Meaning your application server has reached a rate limit with a push service. The push service should include a `Retry-After` header to indicate how long before another request can be made. 310 | * `400 Invalid request`. This generally means one of your headers is invalid or improperly formatted. 311 | * `404 Not Found`. This is an indication that the subscription is expired and can't be used. In this case you should delete the PushSubscription and wait for the client to resubscribe the user. 312 | * `410 Gone`. The subscription is no longer valid and should be removed from application server. This can be reproduced by unsubscribing a push subscription. 313 | * `413 Payload size too large`. The minimum size payload a push service must support is 4096 bytes (or 4kB). 314 | 315 | ## IANA Considerations 316 | The `WEBPUSH` capability has to be registered with IANA. 317 | 318 | ## Security Considerations 319 | The WebPush-capable IMAP server requires to be able to access the Internet, which poses additional risks. Proxies are commended to be used. 320 | 321 | Malicious web push services could be harming the IMAP server with the following means: 322 | * Delay responses to push requests 323 | * Do not respond at all 324 | 325 | A WebPush-capable IMAP server MAY unsubscribe push subscriptions that are having such bad-behaving push service implementations. Clients need to check subscriptions and re-subscribe them if required. 326 | 327 | Malicious clients could create many subscriptions that are invalid. The validation flow catches those problems, IMAP servers SHOULD introduce throttling of subscriptions to counter such behavior. If a client tries to register several invalid subscriptions, the server is RECOMMENDED to lock out that specific client or throttle subscriptions for the affected user. -------------------------------------------------------------------------------- /coi-client-spec.md: -------------------------------------------------------------------------------- 1 | # Status & Discussion 2 | *Status: DRAFT* 3 | 4 | Breaking changes: 5 | * 2019-07: we now use "chat$" for Message-ID based identification. 6 | 7 | Following topics need further discussion: 8 | * Hashing algorithm - for now we assume SHA3-256 for hashing email addresses, this might be changed in the future. 9 | * End-to-end encryption when the communication partners are on COI-enabled servers and use COI-compliant clients. [Message Layer Security](https://datatracker.ietf.org/wg/mls/about/) may provide a basis for that in the future. 10 | * We consider forwarding rules to help limiting the spread of fake news. 11 | * There are various todos spread throughout this document. 12 | 13 | # Table of Contents 14 | 15 | * [Introduction](#introduction) 16 | * [Conventions Used in This Document](#conventions-used-in-this-document) 17 | * [COI Actors](#coi-actors) 18 | * [Checking for Server Side COI Support](#checking-for-server-side-coi-support) 19 | * [Message Format](#message-format) 20 | * [Message Format Design Considerations](#message-format-design-considerations) 21 | * [Goals](#goals) 22 | * [Backwards Compatibility](#backwards-compatibility) 23 | * [COI-specific Message Header Fields](#coi-specific-message-header-fields) 24 | * [COI Base Formats](#coi-base-formats) 25 | * [Messages](#messages) 26 | * [Text Messages](#text-messages) 27 | * [Binary Messages](#binary-messages) 28 | * [Preview Message Parts](#preview-message-parts) 29 | * [Edit and Delete Messages](#edit-and-delete-messages) 30 | * [Read Receipts / Disposition Notification Reports](#read-receipts--disposition-notification-reports) 31 | * [Requesting Read Receipts](#requesting-read-receipts) 32 | * [Sending Read Receipts](#sending-read-receipts) 33 | * [Contact Storage Messages](#contact-storage-messages) 34 | * [Contact Storage Message Headers](#contact-storage-message-headers) 35 | * [Contact Storage Message Body](#contact-storage-message-body) 36 | * [Contact Storage Message Example](#contact-storage-message-example) 37 | * [Encrypting Contacts](#encrypting-contacts) 38 | * [Blocking Contacts](#blocking-contacts) 39 | * [Merging Contact Storage Messages](#merging-contact-storage-messages) 40 | * [User Profile Messages](#user-profile-messages) 41 | * [User Profile Storage Message](#user-profile-storage-message) 42 | * [User Profile Information Message Part](#user-profile-information-message-part) 43 | * [Requesting Profile Information](#requesting-profile-information) 44 | * [Processing Received Profiles](#processing-received-profiles) 45 | * [Group Messages](#group-messages) 46 | * [Sending a Chat Message to a Group](#sending-a-chat-message-to-a-group) 47 | * [Replying to a Group Message](#replying-to-a-group-message) 48 | * [Group Storage Message](#group-storage-message) 49 | * [Group Information Message Part](#group-information-message-part) 50 | * [Leaving a Group: Group Participant Left Message](#leaving-a-group-group-participant-left-message) 51 | * [Converting a 1:1 to a Group Conversation](#converting-a-11-to-a-group-conversation) 52 | * [Group Message Encryption](#group-message-encryption) 53 | * [Request Group Information](#request-group-information) 54 | * [Group Messaging and Mailing Lists](#group-messaging-and-mailing-lists) 55 | * [Mentions in Group Messages](#mentions-in-group-messages) 56 | * [Changing Group Definitions and Processing Changes](#changing-group-definitions-and-processing-changes) 57 | * [Processing Group Name Changes](#processing-group-name-changes) 58 | * [Processing Group Participants Changes](#processing-group-participants-changes) 59 | * [Processing Group Description and Avatar Changes](#processing-group-description-and-avatar-changes) 60 | * [Processing Group Participant Changes](#processing-group-participant-changes) 61 | * [Processing Group Changes](#processing-group-changes) 62 | * [Location Messages](#location-messages) 63 | * [Pinned Messages](#pinned-messages) 64 | * [Poll Messages](#poll-messages) 65 | * [Poll Initiation Message](#poll-initiation-message) 66 | * [Poll Vote Message](#poll-vote-message) 67 | * [Poll Closed Message](#poll-closed-message) 68 | * [Extension Messages](#extension-messages) 69 | * [Message Encryption](#message-encryption) 70 | * [Filter COI Messages](#filter-coi--messages) 71 | * [Configuring Message Filtering on COI Servers](#configuring-message-filtering-on-coi-servers) 72 | * [Manual Message Filtering](#manual-message-filtering) 73 | * [Folders](#folders) 74 | * [Security Considerations](#security-considerations) 75 | * [IANA Considerations](#iana-considerations) 76 | 77 | # Introduction 78 | COI - Chat Over IMAP - provides a basis for modern messaging services on top of the existing email infrastructure. COI leverages the existing open and federated email infrastructure to provide an open chat functionality accessible to everyone with an email address. 79 | 80 | COI will work with standard IMAP servers and IMAP clients and will work better with COI-aware clients and servers. Initially, most email servers will not provide support for COI, so we need ways how to realize the most important functions on top of the existing infrastructure. 81 | 82 | # Conventions Used in This Document 83 | In examples, "C:" indicates lines sent by a client that is connected to a server. "S:" indicates lines sent by the server to the client. 84 | 85 | 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](https://tools.ietf.org/html/bcp14) [[RFC2119](https://tools.ietf.org/html/rfc2119)] [[RFC8174](https://tools.ietf.org/html/rfc8174)] when, and only when, they appear in all capitals, as shown here. 86 | 87 | # COI Actors 88 | In a typical COI setup the following actors are involved: 89 | 90 | * A COI-compatible client, i.e. your app. Also called just "COI client" or "client". 91 | * An service for retrieving the message data, currently we use IMAP for that, but COI is not tied to IMAP and could be made available through JMAP too, for example. The IMAP server may or may not be COI-compatible. The IMAP service MUST be compatible with IMAP v4rev1 as defined in [RFC 3501](https://tools.ietf.org/html/rfc3501), which is the case for almost any IMAP service in production. 92 | * An SMTP service for sending messages. Sending services are also called Mail Transfer Agents (MTAs). 93 | * Other clients, which may or may not be COI-compatible. Clients are also called Mail User Agents (MUAs). 94 | Ideally, your client will be able to communicate with both COI-compatible and normal email clients, however this decision is your choice. You can also choose to only process COI-compliant messages in your app, which will reduce efforts but it might also reduce the potential audience for your users. 95 | 96 | A typical COI communication sequence includes the following steps: 97 | 98 | 1. Connect to your IMAP service and check for COI compliance - if it is supported, enable it for the currently signed in user. 99 | 2. Send specifically formatted mail messages over SMTP. 100 | 3. Listen for incoming messages, differentiate between chat, normal and blocked messages and move them to the respective folders. 101 | 4. Show chat messages to the end user. 102 | 103 | # Checking for Server Side COI Support 104 | A COI client should check for COI support from the server first. 105 | 106 | After signing into the IMAP service with your user credentials, call `CAPABILITY`. When the server returns the "COI" capability you will know that the server is COI compliant supported. 107 | Compare the [COI Server Spec](coi-server-spec.md) for details about how to enable and configure COI. 108 | 109 | # Message Format 110 | Any chat message MUST be compliant with the [RFC 5322](https://tools.ietf.org/html/rfc5322) definition. If binary data is transmitted, the message additionally needs to conform to the MIME message standard ([RFC 2045](https://tools.ietf.org/html/rfc2045), [RFC 2046](https://tools.ietf.org/html/rfc2046), and [RFC 2049](https://tools.ietf.org/html/rfc2049)). 111 | 112 | # Message Format Design Considerations 113 | ## Goals 114 | With the COI specification we try to achieve the following goals: 115 | 116 | * **Backwards Compatibility** 117 | Always have something to show for existing email clients. Each message SHOULD contain 118 | at least one text/plain part, 119 | additionally optionally a text/html part, or 120 | a binary part like image/jpeg. See below for more details. 121 | * **Open Standards** 122 | Use open and existing standards when possible, e.g. 123 | * [h-card microformat](http://microformats.org/wiki/h-card) for contact information 124 | * Disposition Notification Reports for read receipts 125 | * application/json attachments for structured data 126 | * **Secure Messaging** 127 | Allow clients to use any encryption mechanism like GPG or Autocrypt.org. 128 | Optional direct IMAP 2 IMAP communication 129 | 130 | * **Modern User Experience** 131 | Provide support for allowing a user experience that most people expect, e.g. 132 | * Easy cross device contact sync 133 | * Allow to block users 134 | * Edit & delete sent messages 135 | * Useful interactions like polls 136 | * Push (with COI enabled backend) 137 | * Typing notifications (when both parties use a COI-enabled servers) 138 | ## Backwards Compatibility 139 | COI messages are designed to be backwards compatible with existing email clients. While some COI functionalities will not work on such legacy clients, users of non-COI-compliant clients should still be informed about it. Therefore, each message MUST have at least one part that explains the content of this message. These part MIME types are RECOMMENDED: 140 | * text/plain for simple text 141 | * text/html, or 142 | * a common binary format like for example image/jpeg. 143 | 144 | For the same reason, the number of messages SHOULD be limited - ideally, instead of sending automated messages, a COI client only sends out user-generated messages and possibly enriches those. 145 | 146 | If possible, commonly understood MIME parts such as image/jpeg or text/vcard are used, so that again non-COI compliant clients can at least view nested content parts. For some messages, it is better not to include attachments directly but to embedd relevant data within the HTML message parts instead. In this way non-technical users are not confused by attachments they cannot understand. 147 | 148 | 149 | 150 | # COI-specific Message Header Fields 151 | COI-aware email clients and COI IMAP servers MUST send messages conforming to the header descriptions below: 152 | 153 | * A COI message MUST contain the `Chat-Version` header field with a value of "1.0". Note that further parameters MAY follow which will be separated by semicolons, e.g. `Chat-Version: 1.0;name=value`. 154 | * A COI message MUST only contain one address in the "From" field. 155 | * A COI message MUST contain a `Date` header field with a value adhering to [RFC 5322](https://tools.ietf.org/html/rfc5322#section-3.3). 156 | * A COI message MUST contain a `Message-ID` header field in the following format: "chat$" + domain-unique ID + "@" + mail domain, e.g. ``. 157 | * A COI message MUST contain `MIME-Version: 1.0` in the header. 158 | * A COI message SHOULD contain a `References` header field with the message-IDs of the initial message and the last message only. Note that this recommendations is contrary to the RFC 5322 recommendation, which results in all message-ID are all parent messages being referenced. However, in a chat conversation there will be way more messages than in a typical email thread, so it would be impractical to reference all previous messages. 159 | * A COI message SHOULD contain a `In-Reply-To` header when answering to a previous message. This header field contains the message-ID in of the replied message. 160 | * The `To` header contains the recipient(s) of the message. 161 | * The `From` header field of a COI message MUST only contain one sender. 162 | * A COI message SHOULD NOT have a `Sender` header field. 163 | * A COI message MAY contain a `Disposition-Notification-To` header field. If it is present the field content MUST be the same as the `From` header field. This is for requesting read reports. 164 | * A binary COI message MUST contain the `Content-Transfer-Encoding` header field. 165 | * A binary COI message SHOULD contain the `Content-Disposition: inline` header. It SHOULD also contain the filename and size parameters, for example `Content-Disposition: inline;filename="earth.jpg";size=2048`. 166 | * The `Chat-Content` header MAY be used in message headers and message part headers to identify the contents of a specific part. Possible values include: 167 | * *ignore* for parts that should not be shown to end users by a COI compliant client. 168 | * *status* for a part that contains the user status. 169 | * *editrequest* and *deleterequest* for edited and deleted messages. 170 | * *preview* for parts that contain a preview for a large message such as a video. 171 | * *contact* for a part that contains a full VCARD contact for syncing purposes. 172 | * *profile* for a part that contains information about the sending contact embedded in the HTML. 173 | * *profilerequest* for requesting contact information. 174 | * *group* for a message that contains group information for cross device syncing. 175 | * *groupprofile* for a part that contains information about a group embedded in the HTML. 176 | * *groupprofilerequest* for requesting group information. 177 | * *groupleft* for a request to leave a group conversation. 178 | * *poll* for sending a poll. 179 | * *pollvote* for voting in a poll. 180 | * *pollclose* for closing a poll. 181 | * *client specific value* for any extension message parts that are client specific. 182 | * Depending on the message contents or its encryption, additional headers MAY be set. 183 | * A COI client MAY set the `Subject` header field. 184 | 185 | # COI Base Formats 186 | A COI message will use one of these formats as specified in the `Content-Type` header field: 187 | 188 | * *text/plain*: for normal, user generated text messages without any additional data 189 | * *multipart/alternative*: for user generated messages in which some parts may be applicable for a COI client while the `text/plain` or `text/html` part is applicable for both non-COI-compliant clients and COI clients. 190 | * *multipart/mixed*: for creating more complex messages, e.g. a contact storage message that contains a `text/vcard` part of the sender as an attachment. 191 | * *multipart/signed*: a multipart message that is additionally signed. 192 | 193 | # Messages 194 | ## Text Messages 195 | User generated text messages SHOULD be delivered in the `text/plain` mime format with a UTF-8 encoding when possible. This is defined with following header field: `Content-Type: text/plain; charset=UTF-8; format="flowed"`. 196 | Note that incoming messages from existing email clients MAY be delivered in other formats but SHOULD still be shown. Any existing signatures and quote blocks SHOULD be either stripped away or folded out of view. A client MAY show an option to view the full message contents. 197 | 198 | *Example for a simple text message:* 199 | 200 | ``` 201 | From: Me Myself 202 | To: You 203 | Subject: 204 | Date: Mon, 4 Dec 2019 15:51:37 +0100 205 | Message-ID: 206 | Content-Type: text/plain; charset=UTF-8; format="flowed" 207 | References: 208 | Chat-Version: 1.0 209 | MIME-Version: 1.0 210 | Disposition-Notification-To: Me Myself 211 | 212 | Hello World 213 | My dear friend, this is a message to you! 214 | ``` 215 | 216 | When a client supports formatting messages e.g. with markdown, it should convert that message to HTML code. The client MAY additionally provide a `text/markdown` part in this case. Additionally, a client can mark parts with `Chat-Content: ignore`, to hide certain parts from COI compliant clients. 217 | 218 | Note that clients will choosewhich part they want to show based on client-specific considerations. Security-minded COI clients may prefer `text/plain` parts wheras others may prefer `text/markdown` or `text/html` parts for a richer experience. 219 | 220 | *Example for a formatted text message:* 221 | 222 | ``` 223 | From: Me Myself 224 | To: You 225 | Subject: 226 | Date: Mon, 4 Dec 2019 15:51:37 +0100 227 | Message-ID: 228 | Content-Type: multipart/alternative; 229 | boundary=unique-boundary-1 230 | References: 231 | Chat-Version: 1.0 232 | Disposition-Notification-To: Me Myself 233 | MIME-Version: 1.0 234 | 235 | --unique-boundary-1 236 | Content-Type: text/plain; charset=UTF-8 237 | 238 | hello COI world! 239 | 240 | 241 | --unique-boundary-1 242 | Content-Type: multipart/mixed; 243 | boundary=unique-boundary-2 244 | 245 | --unique-boundary-2 246 | Content-Type: text/html; charset=UTF-8 247 | 248 |

hello COI world!

249 | 250 | --unique-boundary-2 251 | Content-Type: text/html; charset=UTF-8 252 | Chat-Content: ignore 253 | 254 |

This is a chat message 255 | - consider using my awesome COI app for best experience!

256 | 257 | --unique-boundary-2-- 258 | 259 | --unique-boundary-1 260 | Content-Type: text/markdown; charset=UTF-8 261 | 262 | hello **COI** world! 263 | 264 | --unique-boundary-1-- 265 | ``` 266 | 267 | 268 | An initial message SHOULD contain contact information about the sender, please compare the Contact Messages section below for details. 269 | 270 | # Binary Messages 271 | 272 | Typical examples for binary messages are 273 | * photos: `image/webp`, `image/jpeg` and `image/png` SHOULD be supported by a COI-compatible client. `image/gif` is RECOMMENDED to be supported. 274 | * audio-recordings: `audio/webm` SHOULD be supported by a COI-compatible client. `audio/mp4` and `audio/aac` is RECOMMENDED to be supported. 275 | * videos: `video/webm` SHOULD be supported by a COI-compatible client. `video/mp4` is RECOMMENDED to be supported. 276 | 277 | In a chat environment, a single message typically only contains one binary message, but it MAY also contain several attachments at once. 278 | 279 | A binary message MUST contain the following additional fields: 280 | * `Content-Transfer-Encoding`: the encoding of the message, base64 MUST be supported, compare [RFC 4648](https://tools.ietf.org/html/rfc4648) for details. 281 | * `Content-Disposition`: the disposition of the binary data. It SHOULD have the value "inline". Additionally the parameters "filename" and "size" (in octets=bytes) SHOULD be defined. Compare [RFC 2183](https://tools.ietf.org/html/rfc2183) for details. 282 | * Clients SHOULD support messages with multiple files. In this case, the corresponding `multipart/mixed` messages need to be supported. If the COI client supports encryption, additionally `multipart/encrypted` messages MUST be supported. 283 | 284 | *Example 1: A message containing a single image.* 285 | 286 | ``` 287 | From: Me Myself 288 | To: You 289 | Subject: 290 | Date: Mon, 4 Dec 2019 15:51:37 +0100 291 | Message-ID: 292 | Content-Type: image/jpeg 293 | Content-Transfer-Encoding: base64 294 | Content-Disposition: inline;filename=earth.jpg;size=2048 295 | References: 296 | Chat-Version: 1.0 297 | Disposition-Notification-To: Me Myself 298 | MIME-Version: 1.0 299 | 300 | TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz 301 | IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg 302 | dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu 303 | dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo 304 | ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4= 305 | ``` 306 | 307 | *Example 2: A multipart message containing one audio recording and one image.* 308 | 309 | ``` 310 | From: Me Myself 311 | To: You 312 | Subject: 313 | Date: Mon, 4 Dec 2019 15:51:37 +0100 314 | Message-ID: 315 | Content-Type: multipart/mixed; 316 | boundary=unique-boundary-1 317 | References: 318 | Chat-Version: 1.0 319 | Disposition-Notification-To: Me Myself 320 | MIME-Version: 1.0 321 | 322 | --unique-boundary-1 323 | Content-Type: audio/webm 324 | Content-Transfer-Encoding: base64 325 | Content-Disposition: inline 326 | 327 | ... base64-encoded WebM audio data goes here ... 328 | 329 | --unique-boundary-1 330 | Content-Type: image/jpeg 331 | Content-Transfer-Encoding: base64 332 | Content-Disposition: inline; 333 | filename="venus.jpg";size=4096 334 | 335 | ... base64-encoded JPEG image data goes here ... 336 | 337 | --unique-boundary-1-- 338 | ``` 339 | 340 | ### Preview Message Parts 341 | 342 | For a large binary message such as a video or a high resolution photo, a COI-compatible client MAY add a preview message part. This allows clients with unstable or rate-limited network connections to show the message without needing to download the full message contents first. 343 | 344 | A COI client MUST be able to process such a preview part and not show two individual parts. It MAY ignore such message parts to be compliant. 345 | 346 | A preview message sets the `Chat-Content` header field to "preview" in the respective part: 347 | 348 | ``` 349 | Chat-Content: preview 350 | ``` 351 | 352 | A preview message part typically contains one lower resolution image. 353 | 354 | *Example: A video with an image as a preview:* 355 | 356 | ``` 357 | From: Me Myself 358 | To: You 359 | Subject: 360 | Date: Mon, 4 Dec 2019 15:51:37 +0100 361 | Message-ID: 362 | Content-Type: multipart/mixed; 363 | boundary=unique-boundary-1 364 | References: 365 | Chat-Version: 1.0 366 | Disposition-Notification-To: Me Myself 367 | MIME-Version: 1.0 368 | 369 | --unique-boundary-1 370 | Content-Type: image/jpeg 371 | Content-Transfer-Encoding: base64 372 | Content-Disposition: inline 373 | Chat-Content: preview 374 | 375 | ... base64-encoded jpeg data goes here ... 376 | 377 | --unique-boundary-1 378 | Content-Type: video/webm 379 | Content-Transfer-Encoding: base64 380 | Content-Disposition: inline; 381 | filename="bigbuckbunny.webm";size=4096 382 | 383 | ... base64-encoded webm video data goes here ... 384 | 385 | --unique-boundary-1-- 386 | ``` 387 | 388 | Clients should first download the envelope data of very large messages to detect preview parts. When such a part is available and network connectivity is limited, it is RECOMMENDED that only the preview part is downloaded until the user requests the full content. 389 | 390 | ## Edit and Delete Messages 391 | 392 | To allow users to change already sent messages, a follow up edit message can be send. A COI-compatible client SHOULD only show the latest edited message, but it MAY make the history available. An edit message MAY be empty, this means that the original message should be shown as deleted. A COI client SHOULD visualize the edited state of a message. 393 | 394 | An edit message MUST contain set the `Chat-Content` header field to "editrequest" and the `In-Reply-To` header field to the message-ID of the edited, for example: 395 | 396 | ``` 397 | Chat-Content: editrequest 398 | In-Reply-To: 399 | ``` 400 | If a message should be deleted, then the COI client MUST set the `Chat-Content` header field to "deleterequest": 401 | 402 | ``` 403 | Chat-Content: deleterequest; 404 | In-Reply-To: 405 | ``` 406 | 407 | A message can be edited and/or deleted several times and COI client SHOULD only show the latest version. An edit and delete message MAY contain a read receipt request, which SHOULD be processed normally. To not create a sense of false security, it is RECOMMENDED that clients show the history of edited and delete messages. A deleted message is RECOMMENDED to be shown as "this message has been deleted". 408 | 409 | A COI client MUST ensure that the referenced message is coming from the same sender as the original message. 410 | 411 | Multiple edits SHOULD reference the last edited message, not the original message. 412 | 413 | If a the referenced message is not found, e.g. because it is deleted, then the only new message SHOULD be shown. 414 | 415 | If a client decides not to support edit and delete message, it just shows all messages in their chronological order. 416 | 417 | *Example 1: A normal message is being sent with a typo:* 418 | 419 | ``` 420 | From: Me Myself 421 | To: You 422 | Subject: 423 | Date: Mon, 4 Dec 2019 15:51:37 +0100 424 | Message-ID: 425 | References: 426 | Content-Type: text/plain; charset=UTF-8 427 | Chat-Version: 1.0 428 | MIME-Version: 1.0 429 | Disposition-Notification-To: Me Myself 430 | 431 | My dear friend, this sdkalsk. 432 | ``` 433 | 434 | *Example 2: The above message is being edited with a follow up message:* 435 | 436 | ``` 437 | From: Me Myself 438 | To: You 439 | Subject: 440 | Date: Mon, 4 Dec 2019 15:51:37 +0100 441 | Message-ID: 442 | References: 443 | Content-Type: text/plain; charset=UTF-8 444 | Chat-Version: 1.0 445 | Chat-Content: edit; 446 | In-Reply-To: 456 | To: You 457 | Subject: 458 | Date: Mon, 4 Dec 2019 15:51:37 +0100 459 | Message-ID: 460 | References: 461 | Content-Type: text/plain; charset=UTF-8 462 | Chat-Version: 1.0 463 | Chat-Content: deleterequest 464 | In-Reply-To: 465 | MIME-Version: 1.0 466 | 467 | (original message marked as deleted) 468 | ``` 469 | 470 | ## Read Receipts / Disposition Notification Reports 471 | 472 | COI-compatible clients can request and send read notifications by following the disposition notification standards defined [RFC 8098](https://tools.ietf.org/html/rfc8098) and [RFC 3503](https://tools.ietf.org/html/rfc3503). 473 | 474 | ### Requesting Read Receipts 475 | You can can request read receipts by adding the `Disposition-Notification-To` header field with a value of your email address, for example: 476 | ``` 477 | Disposition-Notification-To: Me Myself 478 | ``` 479 | 480 | ### Sending Read Receipts 481 | If the user approves sending read requests, a COI-compatible client SHOULD send our corresponding reports when receiving a chat message that: 482 | * contains the `Disposition-Notification-To` header field, and 483 | this value is not equals the user's email address, and 484 | * the message has not set the $MDNSent keyword, and 485 | * the message has been shown to the user. 486 | 487 | A COI-compatible client SHOULD then sent out a message disposition notification using the following format: 488 | 489 | ``` 490 | From: Alice 491 | To: Bob 492 | Subject: Chat: Read receipt 493 | Date: Mon, 4 Dec 2019 15:51:37 +0100 494 | Message-ID: 495 | References: 496 | Chat-Version: 1.0 497 | Content-Type: multipart/report; 498 | report-type=disposition-notification; 499 | boundary="RAA14128.773615765/recipientdomain.com" 500 | Content-Disposition: notification 501 | MIME-Version: 1.0 502 | 503 | --RAA14128.773615765/recipientdomain.com 504 | Content-Type: message/disposition-notification 505 | 506 | Reporting-UA: joes-pc.cs.recipientdomain.com; Foomail 97.1 507 | Original-Recipient: rfc822;you@recipientdomain.com 508 | Final-Recipient: rfc822;you@recipientdomain.com 509 | Original-Message-ID: 510 | Disposition: manual-action/MDN-sent-manually; displayed 511 | 512 | --RAA14128.773615765/recipientdomain.com-- 513 | ``` 514 | 515 | To reduce traffic, a COI-compliant client SHOULD NOT include the original message like suggested by [RFC 8098](https://tools.ietf.org/html/rfc8098). 516 | 517 | After sending the read receipt, the client MUST set the `$MDNSent` keyword for the original message. 518 | 519 | *TODO describe how to do that.* 520 | 521 | ## Contact Storage Messages 522 | 523 | To synchronize contacts across devices, a client MAY store contacts as individual messages into the *COI/CONTACTS* folder. Note that on a COI-compatible IMAP server this folder is generated automatically, compare the COI server specification for details. Also, the *COI* folder prefix may be different depending on COI server configuration. 524 | 525 | To keep the user in control, a COI client SHOULD ask the user for permission, before storing contacts on the server. 526 | 527 | In order to allow even non-COI-compliant clients to view contact details, COI clients SHOULD use an extended version of the `h-card` microformat embedded in a `text/html` message (or message part). 528 | 529 | Clients SHOULD encrypt the message body to protect the contact data. 530 | 531 | ### Contact Storage Message Headers 532 | To efficiently process contact messages on the server side, some data must be stored in the headers, specifically the `From`, `Chat-Content`, `COI-Token` (`COI-TokenIn` and `COI-TokenOut`) and `COI-Blocked` header fields that are described below. 533 | 534 | * `From`: can contain the email address of the signed-in user. 535 | * `COI-From-Hash`: to allow servers to locate contact storage messages, the `COI-From-Hash` contains the SHA3-256 hash of the normalized form of the email address of the contact. Normalized form means removing quotes, using UTF-8 and lowercasing the email address. If the contact has several email addresses, one `COI-From-Hash` header is specified for each email address. 536 | * `To`: Optional the logged-in user's primary address for this contact. 537 | * `Subject`: "Contact" or some other informative text. 538 | * `Date`: Timestamp when the contact was last intentionally modified (which can be different from received-time, which is when it was uploaded to server) 539 | * `COI-Token` (`COI-TokenIn` and `COI-TokenOut`): COI compatible servers use tokens to allow direct IMAP server to IMAP server message transfers. There can be several COI-Token header fields for a single contact. The token structure is defined in the COI server specification. Clients SHOULD NOT use or change the token information. 540 | * `Chat-Content`: set to "contact" for contacts or to "profile" for profile information of the currently signed in user. 541 | * `Content-Type`: is either `text/html` or `multipart/alternative` or `multipart/encrypted`. 542 | 543 | ### Contact Storage Message Body 544 | 545 | 546 | A contact storage message SHOULD be a `text/html` message (or message part) with the following mandatory fields: 547 | 548 | * `p-name` the name of the user 549 | * `u-email` the email address of the user (can be repeated for several email addresses) 550 | 551 | The following optional fields are COI-specific or structured in a COI-specific way: 552 | * `p-category`: COI clients use the following predefined categories values. Several categories can be separated by a COMMA. 553 | * *friend* for friends 554 | * *family* for family members 555 | * *work* for work colleagues 556 | * *partner* for the partner 557 | * other value for client or user specific categorization, e.g. *sports*. 558 | * `p-status`: the status of the user e.g. "gone fishing" 559 | * `p-notification`: notification settings for this users with a SEMICOLON separated list of setting key-value pairs, each pair separated by an equals sign: 560 | * `enabled`: is deemed enabled unless set to "false" or "no". 561 | * `types`: a COMMA separated list of client specific type values like *sound* or *banner*. 562 | * `sounds`: a COMMA separated list of client specific sound values. RECOMMENDED values include the same values as the *categories* field. 563 | * `filters`: criteria when a notification should be shown. When missing and is_enabled is true, it is RECOMMENDED that a notification is shown for any new user generated message. Possible values are 564 | * *message* for any user generated message excluding read receipts, contact updates, etc, 565 | * *mention* for messages that contain a mention of this user, or a 566 | * client specific value 567 | 568 | Compare the [h-card microformat](http://microformats.org/wiki/h-card) specification for details. 569 | 570 | 571 | 572 | ### Contact Storage Message Example 573 | The following example shows a contact storage message for a contact with the email addresses *john.doe@coi-dev.org* and *john.doe@example.com*: 574 | 575 | 576 | ``` 577 | From: Alice 578 | COI-From-Hash: 74b3c446c189580045a942b90b7461128bc334b3b67e9f63c0c06189248c9bb0 579 | COI-From-Hash: 834d1654133366cef4d81e81a7099f413b1b85b9fc9dd62140491303dec56532 580 | Subject: Contact 581 | Date: Mon, 4 Dec 2019 17:51:37 +0100 582 | Message-ID: 583 | Content-Type: text/html; charset=UTF-8 584 | Chat-Version: 1.0 585 | MIME-Version: 1.0 586 | Chat-Content: contact 587 | 588 | 589 | 590 |

591 | 595 | John Doe
596 | Nickname: Johnny
597 | Email: john.doe@coi-dev.org
598 | Email: john.doe@example.com
599 | working from home... 600 | 601 | 602 | 604 |

605 | 606 | 607 | ``` 608 | 609 | ### Encrypting Contacts 610 | 611 | To protect the privacy of contact, the complete message body of a contact storage message SHOULD be encrypted. It is RECOMMENDED that clients use the user's GPG/PGP key for encrypting the message body. The `Content-Type` header of the message is then set to `multipart/encrypted`. 612 | 613 | ### Blocking Contacts 614 | To mark a contact as blocked a COI client MUST set the `COI-Blocked` header field of the corresponding contact storage message. The actual content of this header field is ignored but is RECOMMENDED to be set to "yes". When a contact is blocked, a COI client SHOULD move any incoming messages to the *Blocked* folder, unless the IMAP server is COI compliant, in which case the server does that. 615 | 616 | Before blocking a contact, the client SHOULD check the last received message of that contact for a DKIM header. In case there is no DKIM header, the client SHOULD warn the user about the possibility, that the sender address might be spoofed. This assumes that the server checks the DKIM header and rejects invalid headers. 617 | 618 | ### Merging Contact Storage Messages 619 | COI clients need to be able to merge mails if they find duplicates as identified by having a same `COI-From-Hash` header. 620 | 621 | * When finding a token, find it from all mails, even if they are duplicates 622 | * Contact is updated by `APPEND`-ing a new one and expunging the old one. 623 | * If mails are found that have duplicate `COI-From-Hash` headers, those mails should be merged. 624 | * Merging is done by merging all of those mails' headers. 625 | * All `COI-TokenIn` headers are preserved, except expired tokens can be dropped. 626 | * `COI-TokenOut` headers preserve the latest ones (newest create timestamp) for each unique "hash", while dropping others 627 | * All other headers are preserved. In case the of conflicts, use the newer mail's fields (newer Date header, or in case they equal then newer IMAP `UID`) 628 | 629 | 630 | ## User Profile Messages 631 | ### User Profile Storage Message 632 | 633 | A user profile storage message is structured like a contact storage message with the following differences: 634 | * There can be several message parts each containing a different profile description. This allows clients to differentiate the information they are sharing with a contact based on the category of a contact. As an example, users might want to share their birthday with their friends, but not with other contacts. 635 | * Each message part MUST contain the `Chat-Content: profile` header, with the optional `categories` parameter defining the COMMA separated group-categories, for which the profile is applicable, for example `Chat-Content: profile; categories=friend, family`. 636 | 637 | 638 | *Example for a user profile message with a profiles for three different audiences:* 639 | ``` 640 | From: Alice 641 | Subject: Profile 642 | Date: Mon, 4 Dec 2019 17:51:37 +0100 643 | Message-ID: 644 | Content-Type: multipart/mixed; 645 | boundary="SDKJK2323.23123/example.com" 646 | Chat-Version: 1.0 647 | MIME-Version: 1.0 648 | Chat-Content: profile 649 | 650 | --SDKJK2323.23123/example.com 651 | Content-Type: text/html; charset=UTF-8 652 | Chat-Content: profile; categories=friend,family 653 | 654 | 655 | 656 |

657 | 661 | Alice Angel
662 | Nickname: Al
663 | Email: alice@example.com
664 | Email: angel@work-example.com
665 | weekend here I come... 666 | 667 |

668 | 669 | 670 | 671 | --SDKJK2323.23123/example.com 672 | Content-Type: text/html; charset=UTF-8 673 | Chat-Content: profile; categories=work 674 | 675 | 676 | 677 |

678 | 682 | Alice Angel
683 | Email: angel@work-example.com
684 | working from home... 685 |

686 | 687 | 688 | 689 | 690 | --SDKJK2323.23123/example.com 691 | Content-Type: text/html; charset=UTF-8 692 | Chat-Content: profile 693 | 694 | 695 | 696 |

697 | 701 | Alice Angel
702 | Email: alice@example.com
703 | 704 |

705 | 706 | 707 | 708 | --SDKJK2323.23123/example.com-- 709 | 710 | ``` 711 | 712 | To protect the user's information, clients SHOULD encrypt the complete body of the profile storage message. It is RECOMMENDED that clients use the user's GPG/PGP key for encrypting the message body. The `Content-Type` of the message is then set to `multipart/encyrpted`. 713 | 714 | 715 | ### User Profile Information Message Part 716 | 717 | COI clients MAY use contact information messages to transmit profile data such as their image. This helps in setting up a good user experience. It is RECOMMENDED that clients send out updated profile data with new user generated messages only. However, a COI client MAY send this updated profile to all active contacts. What is deemed active and if a COI client differentiates between contacts is a client specific decision. It is RECOMMENDED that all contacts from which chat messages have been received in the last 30 days are deemed active. 718 | 719 | Profile information is embedded in the `text/html` part of a `multipart/alternative` message. The part MUST be marked with a `Chat-Content: profile` header. 720 | 721 | 722 | To reduce unnecessary traffic, it is RECOMMENDED that a COI client keeps track which contacts have received the profile information message already. COI clients MAY use a client specific header field in a contact storage message, e.g. `com_example_myawesesomeclient_TimeProfiletSent: 2019-03-19T07:22Z`. 723 | 724 | 725 | 726 | *Example for a message with a profile part:* 727 | ``` 728 | From: Alice 729 | To: bob@recipientdomain.com 730 | Subject: Chat: Hello my ... 731 | Date: Mon, 4 Dec 2019 15:51:37 +0100 732 | Message-ID: 733 | Content-Type: multipart/alternative; 734 | boundary="SDKJK2233.23278827/sample.com" 735 | Chat-Version: 1.0 736 | MIME-Version: 1.0 737 | 738 | --SDKJK2233.23278827/sample.com 739 | Content-Type: text/plain; charset=UTF-8; format="flowed" 740 | Content-Disposition: inline 741 | 742 | Hello my friend, this is my first COI message! 743 | 744 | --SDKJK2233.23278827/sample.com 745 | Content-Type: text/html; charset=UTF-8 746 | Content-Disposition: inline 747 | Chat-Content: profile 748 | 749 | 750 | 751 |

Hello my friend, this is my first COI message!

752 |
753 |

754 | 758 | Alice Angel
759 | Email: alice@example.com
760 | Birthday: --04-30
761 | working from home... 762 |

763 | 764 | 765 | 766 | --SDKJK2233.23278827/sample.com-- 767 | ``` 768 | 769 | 770 | 771 | ### Requesting Profile Information 772 | 773 | When a COI client has lost information about a contact and cannot restore the information neither from the COI/CONTACTS IMAP folder nor from the message history, it MAY request the contact information by setting the Chat-Content header field to "profilerequest". It is RECOMMENDED to send the request along with a normal user generated message. The receiving COI client SHOULD send the contact information to the requesting party. It is RECOMMENDED to ask the recipient for approval before sending the contact information. 774 | 775 | *Example for a profile request message:* 776 | ``` 777 | From: Bob 778 | To: Alice 779 | Subject: Chat 780 | Date: Mon, 4 Dec 2019 15:23:13 +0100 781 | Message-ID: 782 | Content-Type: text/plain; charset=UTF-8; format="flowed" 783 | References: 784 | Chat-Version: 1.0 785 | Chat-Content: profilerequest 786 | MIME-Version: 1.0 787 | Disposition-Notification-To: Me Myself 788 | 789 | Hi Alice, can you please advise me? 790 | ``` 791 | 792 | ### Processing Received Profiles 793 | *TODO describe parsing and storing contact informations through generating the respective HTML, checking the COI-From-Hash header of existing messages first, then encrypting the message body* 794 | 795 | 796 | ## Group Messages 797 | 798 | Sending messages to a group is simple in principle: just send message to several participants that are defined in the `To` field. 799 | 800 | A group must at least contain one recipient, this can be just the same as the sender. This allows user to create specific channels for themselves, e.g. "tasks" or "ideas". 801 | 802 | Each group has an assigned ID. The group ID MUST only contain alphanumeric , minus and underline characters: `[0-9A-Za-z_-]+`. A group ID MUST be case-sensitive and MUST contain at least 12 characters. 803 | 804 | To identify groups in replies from non-COI-compliant clients, the group ID is embedded into the message ID in the format `chat$group..@`, e.g. 805 | 806 | ``` 807 | Message-ID: 808 | ``` 809 | 810 | Groups are identified by parsing this `Message-ID` or - in the case of replies from non-COI-compliant clients - the first message-ID in the `References` header field. 811 | 812 | The group-ID is also acting as an identifier, i.e. COI clients MUST allow to have the same participants in different groups. As an example, users can start a topic-specific discussion by creating a new group, even if the group only contains two participants. 813 | 814 | It is RECOMMENDED that the group can be managed like email, i.e. any user can add or remove anyone from the list of recipients by changing either `To` or `CC`. Any group member SHOULD be able to change the group name, description and avatar. 815 | 816 | To enable group avatars, allow participants to leave a group, support to manage groups, etc., COI clients use additional, specifically formatted message parts that are described below. 817 | 818 | ### Sending a Chat Message to a Group 819 | A COI client sends a message to a group by adding several contacts to the `To` header field. If a group-name exists, a COI client SHOULD specify the group name with the `Subject` header field and the group participants in the `To` header field. To not accidentally spread user-specific nicknames for contacts, COI clients SHOULD either use names authorized by the participants or use the email addresses without names in the `To` header field. 820 | 821 | *Example for a message to a group called "My Crew" and a group ID of `4321dcba1234`:* 822 | 823 | ``` 824 | From: Me Myself 825 | To: alice@example.com; bob@example.com 826 | Subject: My Crew 827 | Date: Mon, 4 Dec 2019 15:51:37 +0100 828 | Message-ID: 829 | Content-Type: text/plain; charset=UTF-8 830 | References: 831 | Chat-Version: 1.0 832 | MIME-Version: 1.0 833 | Disposition-Notification-To: Me Myself 834 | 835 | Hi gang, hope you're doing fine! 836 | ``` 837 | 838 | ### Replying to a Group Message 839 | 840 | When replying to a group message, COI clients MUST reply to all group participants by default, similarly to the "reply all" function of most email clients. COI clients MAY offer switching to a 1:1 conversation based on a group participant's message or from the group participant's list. 841 | 842 | 843 | ### Group Storage Message 844 | 845 | To sync group information across devices, a client MAY use group storage messages. 846 | 847 | 848 | Group storage messages are identified by a `Chat-Content: group` header. The `Content-Type` is set to `multipart/mixed` or `multipart/encrypted`. The message contains one `text/html` part. 849 | 850 | A group storage message contains the following data in the parent element `h-group`: 851 | 852 | * `p-Id`: The ID of the group. 853 | * `p-name`: The name of the group. 854 | * `p-description`: the optional description of the group 855 | * `u-photo`: the optional group avatar 856 | * `p-notification`: The notification settings for this group, which has the same key value pairs structure as for contact storage messages. 857 | * `e-participants`: A list of participants, each one either identified by a `h-card`. An optional hash of the email address acts as a pointer to a corresponding contact storage message. The hash is a SHA3-256 hash of the normalized email address; compare the definition of the `COI-From-Hash` header of contact storage messages. 858 | 859 | 860 | Group storage messages SHOULD be stored in the *COI/CONTACTS* folder, note that this depends on the COI server configuration. Compare the COI server spec for details. 861 | 862 | *Example for a group storage message:* 863 | ``` 864 | From: Me Myself 865 | Subject: Group 866 | Date: Mon, 4 Dec 2019 15:51:37 +0100 867 | Message-ID: 868 | Content-Type: text/html; charset=UTF-8 869 | Chat-Version: 1.0 870 | MIME-Version: 1.0 871 | Chat-Content: group 872 | 873 | 874 | 875 |

876 | 900 | Name: My Crew
901 | Description: This is just a fun place to hang out virtually
902 |

903 | 904 |
905 |

Participants

906 |
907 |

908 |

909 | 913 | Alice Angel
914 | Email: alice@example.com
915 | PGP: ...base64 key data...
916 | Birthday: --04-30
917 | working from home... 918 |

919 |

920 | 924 | John Doe
925 | Email: john.doe@example.com
926 | PGP: ...base64 key data...
927 |

928 |

929 | 933 | Caroll
934 | Email: carrol@example.com
935 | PGP: ...base64 key data...
936 |

937 |
938 |

939 | 940 | 941 | ``` 942 | 943 | ### Group Information Message Part 944 | 945 | When creating a new group, COI clients SHOULD include the group description in the first user generated message. 946 | 947 | The group information is embedded in a `text/html` part that is additionally taggged with a `Chat-Content: groupinfo` header. 948 | 949 | The `groupinfo` message part uses a similar data structure like the group storage message but uses a [microformat](http://microformats.org/wiki/microformats2) for rendering the information: 950 | * `h-group` is the parent element for the group 951 | * `u-photo` (optional) group avatar image 952 | * `p-description` (optional) group description 953 | * `p-participants` contains the list of participants, each in an individual `h-card` element. Compare the contact information message for details about that format. 954 | 955 | Depending on the message content, the message SHOULD either be `multipart/alternative` for text-based contents or `multipart/mixed` for binary contents or when additionally a `contactinfo` part is sent. Encrypted messages will use the `multipart/encrypted` content type. 956 | 957 | 958 | *Example for a message to a group that contains a groupinfo part:* 959 | 960 | ``` 961 | From: Alice 962 | To: john.doe@example.com; carrol@example.com 963 | Subject: My Crew 964 | Date: Mon, 4 Dec 2019 15:51:37 +0100 965 | Message-ID: 966 | Content-Type: multipart/alternative; 967 | boundary="A22090S.123213/example.com" 968 | Chat-Version: 1.0 969 | MIME-Version: 1.0 970 | 971 | --A22090S.123213/example.com 972 | Content-Type: text/plain; charset=UTF-8; format="flowed" 973 | Content-Disposition: inline 974 | 975 | Hello folks, let's chat! 976 | 977 | --A22090S.123213/example.com 978 | Content-Type: text/html; charset=UTF-8 979 | Content-Disposition: inline 980 | Chat-Content: groupinfo 981 | 982 | 983 | 984 |

Hello folks, let's chat!

985 |
986 |
987 |

988 | 1012 |

This is just a fun place to hang out virtually

1013 |
1014 |

Participants

1015 |
1016 |

1017 | 1021 | Alice Angel
1022 | Email: alice@example.com
1023 | PGP: ...base64 key data...
1024 | Birthday: --04-30
1025 | working from home... 1026 |

1027 |

1028 | 1032 | John Doe
1033 | Email: john.doe@example.com
1034 | PGP: ...base64 key data...
1035 |

1036 |

1037 | 1041 | Caroll
1042 | Email: carrol@example.com
1043 | PGP: ...base64 key data...
1044 |

1045 |
1046 |

1047 |
1048 | 1049 | 1050 | 1051 | --A22090S.123213/example.com-- 1052 | ``` 1053 | 1054 | ### Leaving a Group: Group Participant Left Message 1055 | 1056 | Any user in a group can pro-actively leave a group chat. 1057 | 1058 | When doing so, a COI client MUST send a group participant left message. The `Chat-Content` header field MUST be set to `groupleft`. A COI client SHOULD include a short description about what happened, this MAY be a user-generated reason. A receiving COI client MUST update the internal represenation of the group and remove the leaving sender of a a `groupleft` message. The `Reply-To` header MAY be set to remaining group participants, so that users on non-COI-compatible clients will answer by default to only the remaining group participants. 1059 | 1060 | A COI client SHOULD also send a `groupleft` message to a recipient that has been removed from a group by another user. 1061 | 1062 | Note that a COI client user MAY receive further group messages after being removed from a group, for example when another group member was offline in between and had messages for that group waiting in a queue. A user might also be added at a later point again by another user. 1063 | 1064 | *Example for a group participant left message:* 1065 | ``` 1066 | From: Bob Barr 1067 | To: alice@example.com; carrol@example.com; dean@example.com; 1068 | Subject: My Crew 1069 | Date: Mon, 4 Dec 2019 15:51:37 +0100 1070 | Message-ID: 1071 | In-Reply-To: 1072 | References: 1073 | 1074 | Content-Type: text/plain; charset=UTF-8 1075 | Chat-Version: 1.0 1076 | Chat-Content: groupleft 1077 | Reply-To: alice@example.com; carrol@example.com; dean@example.com; 1078 | MIME-Version: 1.0 1079 | 1080 | hi guys, I think you can now roll this project on your own! Bye! 1081 | ``` 1082 | 1083 | 1084 | #### Converting a 1:1 to a Group Conversation 1085 | When a COI client wants to convert a 1:1 to a group conversation, it MUST create a corresponding group with at least accompanying new `References` and `Message-ID` header fields in the first message. COI clients SHOULD also sent fitting `groupinfo` message parts. 1086 | 1087 | However, a non-COI-compatible client is not aware about the semantics and would basically keep the `References` and use a non-group-identifying `Message-ID` header field. 1088 | 1089 | In that case, a COI client SHOULD generate a new group: 1090 | * The group name SHOULD be based on `Subject` field cleared any reply-notations like "RE:". 1091 | * The group participants SHOULD be extracted from the `To` and `CC` fields. 1092 | * The group-ID SHOULD be generated. 1093 | 1094 | When replying to such a message, a COI client SHOULD create a new thread by using no or a new `References` header field, a new `Message-ID` header field and the group-name in the `Subject` field. 1095 | 1096 | ### Group Message Encryption 1097 | If the group conversation should be encrypted, the originating client MUST include the `key` field for each group participants' `h-card` element. If the public keys are known for all group participants, a COI client SHOULD encrypt messages for the group by default. 1098 | 1099 | ### Request Group Information 1100 | When a COI client lost the group information and cannot restore it neither from the *COI/CONTACTS* IMAP folder nor from the message history, then it MAY create the group definition based on a newly received message: 1101 | * The group-ID is detected from the `Message-ID` header field. 1102 | * The group-name is taken from the `Subject` header field. 1103 | * The participants are determinedfrom the `To` and `CC` header fields. 1104 | 1105 | In that case, it is RECOMMENDED to request the group information. This is done by setting the `Chat-Content` header field to `grouprequested` with the next user-generated message. 1106 | 1107 | A receiving COI client in that group SHOULD send the information with the next user-generated message. 1108 | 1109 | *Example for requesting the group information:* 1110 | ``` 1111 | From: Alice 1112 | To: bob@example.com; carrol@example.com; dean@example.com; 1113 | Subject: My Crew 1114 | Date: Mon, 4 Dec 2019 15:51:37 +0100 1115 | Message-ID: 1116 | Content-Type: text/plain; charset=UTF-8; format="flowed" 1117 | References: 1118 | 1119 | In-Reply-To: 1120 | Chat-Version: 1.0 1121 | Chat-Content: grouprequested 1122 | MIME-Version: 1.0 1123 | Disposition-Notification-To: Alice 1124 | 1125 | hey folks, I might be late, but I look forward to meet you today! 1126 | ``` 1127 | 1128 | 1129 | ### Group Messaging and Mailing Lists 1130 | A mailing list discussion is from a clients view like a 1:1 chat with one person. Sometimes, users answer to both to the sender of a message and to the mailing list. It is RECOMMENDED that a COI client detects such duplicate messages and only shows the message list message, not additionally a 1:1 chat with the sender. This can be detected by looking at the first message-ID given in the `References` or `Reply-To` header fields. 1131 | 1132 | ### Mentions in Group Messages 1133 | It is RECOMMENDED that COI clients allow to mention users and that mentions for the current users are highlighted. Additionally, it is RECOMMEND to trigger a notifications for a mentioned participant even when the participant has muted the corresponding group conversation. 1134 | 1135 | Mentions follow the scheme `@"?NAME"?:EMAILADDRESS`, e.g. `@Gabe:gabe+private@example.com` or `@"Gabe Lastname":gabe+private@example.com`. 1136 | 1137 | Additionally, the ``@all`` mention SHOULD be supported. This mention should trigger a notification for any group participant. 1138 | 1139 | It is RECOMMENDED that COI clients only show the name-part of the mention text, not the full mention with the email address. Note that mentions can be done in both the plain text as well as the HTML part of a message. 1140 | 1141 | In HTML the representation MUST be done with a link using the `mention` CSS class: 1142 | ``` 1143 | @Gabe 1144 | ``` 1145 | It is RECOMMENDED to show profile details of a mentioned participant along with some options such as starting a direct chat, when a user interacts with the mention. 1146 | 1147 | ### Changing Group Definitions and Processing Changes 1148 | Any group member can update a group, i.e. change the name, description, avatar or participants. So like email, a COI group chat has no hierarchy. 1149 | 1150 | Hierarchical group communication will be added at a later point to COI with a *channels* concept, but this will require a COI-compatible IMAP server. 1151 | 1152 | In case of group definition changes a COI client SHOULD update the corresponding group storage message, by `APPEND`-ing the new message, then mark the original message with the `\Deleted` flag, and then `EXPUNGE`-ing deleted messages. 1153 | 1154 | #### Processing Group Name Changes 1155 | As the group name is specified in the `Subject` field, it is easy for traditional email users to change the name. When the subject has changed, a COI client SHOULD display the new group name. It is RECOMMENDED to ignore typical reply notations such as a preceding "RE:", "AW:" (German), "SV:" (Svedish/Norwegian), etc. Compare https://en.wikipedia.org/wiki/List_of_email_subject_abbreviations for a list of typical reply abbreviations. 1156 | 1157 | #### Processing Group Participants Changes 1158 | Group participants can be changed in different ways: 1159 | * By changing the recipients in the `To` or `CC` header fields of a group message. If a COI-compatile client does this, a corresponding `Chat-Content: groupinfo` message part MUST be added, when one or more participants are added or removed. 1160 | * By leaving the group with a `Chat-Content: groupleft` message. 1161 | 1162 | When a participant is being added, clients SHOULD check if that participant has previously sent a `groupleft` message. In that case, the client SHOULD check if the `Reply-To` header of the adding message refers to a message older than the `groupleft` message. If that is the case, the re-addition of the user SHOULD be ignored. 1163 | 1164 | When a non-COI-compatible client replies to a group message and this would result into removing any other participant apart from the recipient, a COI client SHOULD assume that a user selected the *reply* rather than the *reply all* option and SHOULD discard that group participant change. Instead, this message SHOULD be shown within the respective 1:1 chat conversation with the sender. 1165 | 1166 | 1167 | #### Processing Group Description and Avatar Changes 1168 | Clients can also change the group description and avatar with a corresponding `groupinfo` message part at any time. Ideally, each change is accompanied by a user-generated message. A client SHOULD only use the latest `groupinfo` that has been received. 1169 | 1170 | #### Processing Group Participant Changes 1171 | To protect a group participant from changes made by other participants, clients MUST use received participant information only, when they have not received the information from the participants directly. 1172 | 1173 | #### Processing Group Changes 1174 | *TODO: describe extracting participant information, generating respective contact storage messages or keeping the information within the group definition, re-generating the group information and then encrypting the message* 1175 | 1176 | ## Location Messages 1177 | Sometimes it is useful to share your location with other users. Clients SHOULD support sending and displaying location messages. 1178 | 1179 | For transmitting the information, the [h-geo microformat](http://microformats.org/wiki/h-geo) is used which can be identified with a `Chat-Content: location` header field. It is RECOMMENDED to inlude an image that displays the area and the position of the user. 1180 | 1181 | When receiving such a message, a client SHOULD provide an option to process this information further, for example by opening a corresponding mapping application. 1182 | 1183 | *Example for a location message:* 1184 | ``` 1185 | From: Alice 1186 | To: john.doe@example.com 1187 | Subject: Chat: 1188 | Date: Mon, 4 Dec 2019 15:51:37 +0100 1189 | Message-ID: 1190 | Content-Type: multipart/alternative; 1191 | boundary="BKKHJ222.123213/example.com" 1192 | Chat-Version: 1.0 1193 | MIME-Version: 1.0 1194 | 1195 | --BKKHJ222.123213/example.com 1196 | Content-Type: text/plain; charset=UTF-8; format="flowed" 1197 | 1198 | Let's meet here. 1199 | - 1200 | Position: 53.07516, 8.80777 1201 | 1202 | --BKKHJ222.123213/example.com 1203 | Content-Type: text/html; charset=UTF-8 1204 | Chat-Content: location 1205 | 1206 | 1207 | 1208 |

Let's meet here.

1209 |
1210 |

Position:

1211 |

1212 | 53.07516, 1213 | 8.80777 1214 |

1215 | 1216 | 1217 | 1218 | --BKKHJ222.123213/example.com-- 1219 | ``` 1220 | 1221 | 1222 | ## Pinned Messages 1223 | To allow highlighting important messages, any chat message may be pinned. To achieve this, the `Content-Disposition` header field is set to "pinned". Optionally, a "timeout" parameter can be specified that contains a datetime until the message should be pinned. 1224 | 1225 | COI clients SHOULD keep a pinned message in visible view area until: 1226 | 1227 | * The specified timeout occurred, or 1228 | * a new pinned message arrived in a conversation, or 1229 | * the user locally unpinned a message. 1230 | 1231 | *Example for a pinned message:* 1232 | ``` 1233 | From: Me Myself 1234 | To: You 1235 | Subject: Chat: Hello COI... 1236 | Date: Mon, 4 Dec 2019 15:51:37 +0100 1237 | Message-ID: 1238 | Content-Type: text/plain; charset=UTF-8 1239 | Content-Disposition: pinned; 1240 | timeout=Tue, 5 Dec 2019 0:00:00 +0100 1241 | References: 1242 | Chat-Version: 1.0 1243 | MIME-Version: 1.0 1244 | Disposition-Notification-To: Me Myself 1245 | 1246 | Hello COI world, this message is pinned! 1247 | ``` 1248 | 1249 | ## Poll Messages 1250 | Polls are an integral part of social communication, e.g. for finding a suitable date or selecting a preferred option. To provide support for this interaction, COI clients are RECOMMENDED to support displaying and voting for polls. 1251 | 1252 | Note that polls are a *client-only feature*, so clients are solely responsible for managing votes and results. 1253 | 1254 | A poll has the following characteristics: 1255 | * A title 1256 | * An optional description 1257 | * A list of options with at least 2 entries, each one consisting of either 1258 | * Text 1259 | * Datetime 1260 | * Image 1261 | * Any other binary, e.g. voice or video 1262 | * A potential background image or video 1263 | * A definition whether multiple options or only a single option can be chosen. By default multiple options can be selected. 1264 | * A definition whether participants may vote only once or multiple times. By default participants can vote multiple times, but each vote will override the previous vote. 1265 | * `p-poll-option` for a text option, e.g. `
  • E.T.
  • ` 1266 | * `dt-poll-option` for a datetime object object, e.g. `
  • 2019-12-31
  • `. 1267 | 1268 | ### Poll Initiation Message 1269 | *Example for a poll initiation message:* 1270 | ``` 1271 | 1272 | ``` 1273 | 1274 | ### Poll Vote Message 1275 | 1276 | 1277 | ### Poll Closed Message 1278 | 1279 | 1280 | 1281 | 1282 | 1283 | 1284 | ## Extension Messages 1285 | COI clients MAY introduce client specific messages. Those messages SHOULD always include a text/plain, text/html or binary inline part explaining the contents for users of non COI compliant clients. COI clients MAY use the "Chat-Content" header field for their data message parts. To ensure uniqueness of "Chat-Content" header values, clients MUST start the value with a client-specific name. A reverse domain for the value start is RECOMMENDED, for example: 1286 | ``` 1287 | Chat-Content: com.awesomeclient.MyCustomMessage 1288 | ``` 1289 | 1290 | # Message Encryption 1291 | A COI-compliant client SHOULD support the [Autocrypt.org](https://autocrypt.org) standard to ease end to end encryption scenarios. 1292 | 1293 | Further encryption mechanisms will be defined in the future. 1294 | 1295 | 1296 | # Filter COI Messages 1297 | There are different scenarios for handling mail messages: 1298 | * Some clients may treat all mail messages the same and provide a chat-centric experience for each one. 1299 | * Other clients may want to differentiate between a traditional mail experience and a chat experience depending on the message or contact type. 1300 | 1301 | Depending on the client's and user's needs, clients MAY offer one of the following differentiation options: 1302 | 1303 | 1. No differentiation, every new message ends up by default in the *Inbox*. 1304 | 2. Strict separation, chat messages will be moved to the *COI/Chats* folder. 1305 | 3. Separation after having read. Chat messages will be moved to the *COI/Chats* folder after having marked as seen. 1306 | 1307 | ### Configuring Message Filtering on COI Servers 1308 | Compare the [COI Server Spec](coi-server-spec.md) to learn how message filtering is automated by COI compatible IMAP services. 1309 | 1310 | 1311 | ### Manual Message Filtering 1312 | 1313 | Depending on the above scenarios, COI clients MAY move chat messages to the *COI/Chats* folder. In that case, replies from non-COI compliant clients to COI messages SHOULD be moved to the *COI/Chats* folder as well. 1314 | 1315 | COI messages are detected by having at least one these characteristics: 1316 | 1317 | * The `Chat-Version` header is present. 1318 | * The `Message-ID` header starts with `chat$`. 1319 | * The first message-ID in the `References` header starts with `chat$` 1320 | 1321 | 1322 | For moving the message to *COI/Chats* a COI client has the following options: 1323 | 1324 | * Client listens for incoming mails on *INBOX* either using IMAP IDLE or IMAP NOTIFY, and then moves matching chat mails manually to *COI/Chats*. 1325 | * Pending the user's approval, a service could monitor incoming mails and do that. 1326 | 1327 | After moving a message that originates from the user herself/himself, identified either with the primary email address or a valid alias address, this message should be marked as read at the same time: 1328 | 1329 | *Example pseudo code for moving incoming messages:* 1330 | ``` 1331 | onNewIncomingMessage(msg) { 1332 | if (msg.from == me && msg.to != me) { 1333 | // this is a message from me to other users 1334 | markMessageAsRead(msg); 1335 | if (isCoiMessage(msg)) { 1336 | if (isConfigurationMoveToCoiChats()) { 1337 | moveToCoiChats(msg); 1338 | } else { 1339 | moveToSent(msg); 1340 | } 1341 | } else { 1342 | moveToSent(msg); 1343 | } 1344 | } else if (isCoiMessage(msg) 1345 | && isConfigurationMoveToCoiChats()) 1346 | { 1347 | moveToCoiChats(msg); 1348 | } 1349 | } 1350 | } 1351 | ``` 1352 | 1353 | 1354 | # Folders 1355 | When a COI client connects to a non-COI IMAP server, it might need to create several folders initially: 1356 | 1357 | * *COI/Chats* for storing all chat messages. This folder SHOULD be marked as subscribed by the user. 1358 | * *COI/Contacts* for storing contacts. 1359 | * *Blocked* for storing messages originating from blocked contacts. 1360 | 1361 | A COI-compliant folders generates these folders automatically when a client calls the respective `SETMETADATA` IMAP command, compare the [COI Server Spec](coi-server-spec.md) for details. 1362 | 1363 | 1364 | *TODO describe IMAP details like subscription status* 1365 | 1366 | # Security Considerations 1367 | The security consideration of the referenced standards also apply to this COI client specification definition. 1368 | 1369 | # IANA Considerations 1370 | The "pinned" value of the "Content-Disposition" header field should be registered with IANA. 1371 | --------------------------------------------------------------------------------