RFC 5804

A Protocol for Remotely Managing Sieve Scripts

๐Ÿ“… published July 2010, from ietf
part 1 of 10, more parts coming ๐Ÿ’–

๐Ÿ“„ RFC 5804: A Protocol for Remotely Managing Sieve Scripts

Who wrote it: A. Melnikov, Ed. (Isode Limited) and T. Martin (BeThereBeSquare, Inc.) Category: Standards Track ISSN: 2070-1721 Date: July 2010 Obsoletes / Updates: nothing is listed in the header ๐Ÿซถ

Abstract โœจ

okay so Sieve scripts are how you filter your incoming email ๐Ÿ“ฌ but a lot of mail stores are sealed-off servers, so you literally can't log in to them to fix your scripts ๐Ÿ˜ญ this doc defines a protocol called "ManageSieve" that lets you manage your Sieve scripts on a remote server safely ๐Ÿ” you can have more than one script, and it'll also tell you when a script has a syntax error. iconic behavior ๐Ÿ’…

Status of This Memo

this is an Internet Standards Track document ๐ŸŽ€

it's a product of the Internet Engineering Task Force (IETF) and it represents the consensus of the IETF community ๐Ÿค it got public review and was approved by the Internet Engineering Steering Group (IESG) ๐Ÿ‘‘ if you want more on Internet Standards, check out Section 2 of RFC 5741 ๐Ÿ“š

for the current status, errata, and how to send feedback, go to http://www.rfc-editor.org/info/rfc5804 ๐Ÿ”—

Copyright (c) 2010 IETF Trust and the persons identified as the document authors. All rights reserved. ๐ŸŒธ

this doc is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) as they were in effect when it was published. please read them carefully, because they explain your rights and restrictions for this document ๐Ÿ“– any Code Components pulled out of this document must include Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come with no warranty, as described in the Simplified BSD License ๐Ÿงš

Table of Contents

1. Introduction ....................................................3
   1.1. Commands and Responses .....................................3
   1.2. Syntax .....................................................3
   1.3. Response Codes .............................................3
   1.4. Active Script ..............................................6
   1.5. Quotas .....................................................6
   1.6. Script Names ...............................................6
   1.7. Capabilities ...............................................7
   1.8. Transport ..................................................9
   1.9. Conventions Used in This Document .........................10
2. Commands .......................................................10
   2.1. AUTHENTICATE Command ......................................11
        2.1.1. Use of SASL PLAIN Mechanism over TLS ...............16
   2.2. STARTTLS Command ..........................................16
        2.2.1. Server Identity Check ..............................17
   2.3. LOGOUT Command ............................................20
   2.4. CAPABILITY Command ........................................20
   2.5. HAVESPACE Command .........................................20
   2.6. PUTSCRIPT Command .........................................21
   2.7. LISTSCRIPTS Command .......................................23
   2.8. SETACTIVE Command .........................................24
   2.9. GETSCRIPT Command .........................................25
   2.10. DELETESCRIPT Command .....................................25
   2.11. RENAMESCRIPT Command .....................................26
   2.12. CHECKSCRIPT Command ......................................27
   2.13. NOOP Command .............................................28
   2.14. Recommended Extensions ...................................28
        2.14.1. UNAUTHENTICATE Command ............................28
3. Sieve URL Scheme ...............................................29
4. Formal Syntax ..................................................31
5. Security Considerations ........................................37
6. IANA Considerations ............................................38
   6.1. ManageSieve Capability Registration Template ..............39
   6.2. Registration of Initial ManageSieve Capabilities ..........39
   6.3. ManageSieve Response Code Registration Template ...........41
   6.4. Registration of Initial ManageSieve Response Codes ........41
7. Internationalization Considerations ............................46
8. Acknowledgements ...............................................46
9. References .....................................................47
   9.1. Normative References ......................................47
   9.2. Informative References ....................................48

1. Introduction โœจ

1.1. Commands and Responses ๐Ÿ’ฌ

a ManageSieve connection is set up as a client/server network connection, then the server sends an initial greeting, then the client and server interact ๐Ÿค each interaction is a client command, server data, and a server completion result response.

everything the client and server send is a line, meaning a string that ends with a CRLF ๐Ÿ“ the protocol receiver on a ManageSieve client or server is either reading a line, or reading a sequence of octets with a known count followed by a line ๐Ÿง 

1.2. Syntax ๐ŸŽ€

ManageSieve is a line-oriented protocol, kinda like [IMAP] or [ACAP], and it runs over TCP ๐Ÿฆ‹ there are three data types: atoms, numbers and strings. Strings can be quoted or literal. check out [ACAP] for the detailed descriptions of these types ๐Ÿ“š

each command is an atom (the command name) followed by zero or more strings and numbers, ending with a CRLF ๐Ÿ’…

every client query gets answered with an OK, NO, or BYE response ๐ŸŒˆ each response can be followed by a response code (see Section 1.3) and a string of human-readable text in the local language (the one returned by the LANGUAGE capability, see Section 1.7), encoded in UTF-8 [UTF-8]. the string SHOULD be shown to the user ,and implementations MUST NOT attempt to parse the message for meaning ๐Ÿ™ˆ

the text is for humans, not for code. don't try to parse it for meaning ๐Ÿ’€

the BYE response SHOULD be used when the server wants to close the connection ๐Ÿ‘‹ a server might want to do this if the client has been idle for too long, or if there were too many failed authentication attempts ๐Ÿฅฒ a BYE can show up at any time and should be immediately followed by a server hang-up of the connection ๐Ÿ“ด if a server has an inactivity timeout that causes client autologout, it MUST be no less than 30 minutes after successful authentication ๐Ÿ•’ the inactivity timeout MAY be less before authentication ๐Ÿ“


(part 1 ends here, part 2 is coming soon bestie ๐Ÿงšโœจ)

1.3. Response Codes โœจ

okay so an OK, NO, or BYE response from the server MAY contain a response code ๐ŸŽ€ It's basically extra machine-parsable detail about what just happened, and it's written as an atom inside parentheses, optionally followed by a space and some arguments ๐Ÿ’–

Response codes only exist when there's a specific action a client can take based on the extra info ๐Ÿงš To leave room for future extensions, the response code is a slash-separated (Solidus, %x2F) hierarchy, and each level adds more detail about the error ๐ŸŒธ Response codes MUST NOT start with the Solidus character ๐Ÿ™ˆ Clients MUST tolerate additional hierarchical detail they don't understand, so if a client knows QUOTA but not QUOTA/MAXSCRIPTS, it should treat QUOTA/MAXSCRIPTS as QUOTA ๐Ÿ’… That's the vibe, bestie: be chill about the stuff you don't recognize.

Client implementations MUST tolerate (ignore) response codes they don't recognize ๐Ÿซถ

Here are the response codes that are defined right now ๐Ÿ‘‘

AUTH-TOO-WEAK ๐Ÿ”’

This one comes back in the NO or BYE response from an AUTHENTICATE command. It means the site's security policy forbids the requested mechanism for that authentication identity ๐Ÿ™…โ€โ™€๏ธ

ENCRYPT-NEEDED ๐Ÿ”

This one also shows up in the NO or BYE response from an AUTHENTICATE command. It means site security policy requires a strong encryption mechanism for that authentication identity and mechanism ๐Ÿ’œ

QUOTA ๐Ÿ“ฆ

If this shows up in the NO/BYE response, the command would have pushed the user over the site-defined quota constraints ๐Ÿ˜ญ If it shows up in the OK response, it can mean the user's storage is near its quota, OR the account went over quota but the server is letting it slide (the server supports so-called soft quotas) ๐Ÿ™ˆ QUOTA has two more detailed variants: QUOTA/MAXSCRIPTS (the maximum number of per-user scripts) and QUOTA/MAXSIZE (the maximum script size) ๐Ÿ“

REFERRAL ๐Ÿฆ‹

This one may come back with a BYE result from any command, and it includes a mandatory parameter that says which server to use to manage this user's Sieve scripts โœจ That server is specified by a Sieve URL (see Section 3). The scriptname portion of the URL MUST NOT be specified ๐Ÿšซ The client should authenticate to the specified server and use it for all further commands in the current session ๐Ÿ’…

SASL ๐Ÿง

This can occur in the OK response to a successful AUTHENTICATE command, and it includes the optional final server response data from the server as specified by [SASL] ๐ŸŒˆ

TRANSITION-NEEDED ๐Ÿ”„

This one occurs in a NO response to an AUTHENTICATE command. It means the user name is valid, but the entry in the authentication database needs an update before the user can authenticate with the specified mechanism ๐Ÿ˜ค This is typically handled by establishing a secure channel using TLS, verifying the server identity as specified in Section 2.2.1, and then authenticating once using the [PLAIN] authentication mechanism ๐Ÿ” The selected mechanism SHOULD then work for authentications in subsequent sessions โœจ

This condition can happen if a user has an entry in a system authentication database such as Unix /etc/passwd, but doesn't have credentials suitable for the specified mechanism ๐Ÿคทโ€โ™€๏ธ

TRYLATER โฐ

A command failed because of a temporary server failure. The client MAY keep using local information and try the command later ๐Ÿซ  This response code only makes sense in a NO/BYE response.

ACTIVE ๐ŸŸข

A command failed because it's not allowed on the active script, for example, DELETESCRIPT on the active script ๐Ÿ™…โ€โ™€๏ธ This response code only makes sense in a NO/BYE response.

NONEXISTENT ๐Ÿ‘ป

A command failed because the referenced script name doesn't exist ๐Ÿ’€ This response code only makes sense in a NO/BYE response.

ALREADYEXISTS ๐Ÿ‘ฏ

A command failed because the referenced script name already exists ๐Ÿ™ˆ This response code only makes sense in a NO/BYE response.

TAG ๐Ÿท๏ธ

This response code name is followed by a string specified in the command. See Section 2.13 for a possible use case ๐Ÿงš

WARNINGS โš ๏ธ

This one MAY be returned by the server in the OK response (though it might come back with the NO/BYE response too) ๐Ÿ‘€ It signals the client that even though the script is syntactically valid, it might contain errors the script writer didn't intend ๐Ÿ˜ฌ This is typically returned in response to PUTSCRIPT and/or CHECKSCRIPT commands. A client seeing this response code SHOULD present the returned warning text to the user ๐Ÿซถ


1.4. Active Script ๐ŸŒŸ

A user can have multiple Sieve scripts on the server, but only ONE script can be used for filtering incoming messages ๐Ÿ’… That one is the active script. Users may have zero or one active script, and they MUST use the SETACTIVE command (described below) to change the active script or to disable Sieve processing ๐Ÿ”„ For example, someone might have an everyday script they use normally and a special script for when they go on vacation ๐ŸŒด Users can switch which script is running without downloading and uploading a script stored somewhere else. Iconic efficiency โœจ

1.5. Quotas ๐Ÿ“ฆ

Servers SHOULD impose quotas to stop malicious users from overflowing available storage ๐Ÿ›ก๏ธ If a command would put a user over a quota setting, servers that impose such quotas MUST reply with a NO response containing the QUOTA response code ๐Ÿšจ Client implementations MUST be able to handle commands that fail because of quota restrictions ๐Ÿ’ช

1.6. Script Names ๐Ÿ“

A Sieve script name is a sequence of Unicode characters encoded in UTF-8 [UTF-8]. A script name MUST comply with Net-Unicode Definition (Section 2 of [NET-UNICODE]), with the extra restriction that it prohibits the following Unicode characters ๐Ÿšซ

  • 0000-001F; [CONTROL CHARACTERS]
  • 007F; DELETE
  • 0080-009F; [CONTROL CHARACTERS]
  • 2028; LINE SEPARATOR
  • 2029; PARAGRAPH SEPARATOR

Sieve script names MUST be at least one octet (and therefore one Unicode character) long ๐Ÿซง A zero-octet script name has a special meaning (see Section 2.8) ๐Ÿคซ Servers MUST allow names of up to 128 Unicode characters in length (which can take up to 512 bytes when encoded in UTF-8, not counting the terminating NUL), and they MAY allow longer names ๐Ÿ’– A server that gets a script name longer than its internal limit MUST reject the corresponding operation. In particular, it MUST NOT truncate the script name ๐Ÿ™…โ€โ™€๏ธ No chopping names, periodt โœ‚๏ธ

1.7. Capabilities ๐ŸŽ€

Server capabilities are sent automatically by the server when a client connects, or after successful STARTTLS and AUTHENTICATE (which establishes a Simple Authentication and Security Layer (SASL)) commands ๐Ÿ” Capabilities may change right after a successfully completed STARTTLS command, and/or right after a successfully completed AUTHENTICATE command, and/or after a successfully completed UNAUTHENTICATE command (see Section 2.14.1). Capabilities MUST remain static at all other times ๐ŸงŠ

Clients MAY request the capabilities later by issuing the CAPABILITY command described further on ๐Ÿ“ฃ The capabilities are a series of lines, each with one or two strings. The first string is the capability name, which is case-insensitive. The second, optional string is the value associated with that capability ๐Ÿ’… The order of capabilities is arbitrary, but each capability name can appear at most once ๐ŸŒธ

Here are the capabilities defined in this document ๐Ÿงš

IMPLEMENTATION ๐Ÿ› ๏ธ The name of the implementation and its version. This capability MUST always be returned by the server ๐Ÿ’–

SASL ๐Ÿ”‘ A list of SASL mechanisms supported by the server, each separated by a space. This list can be empty if and only if STARTTLS is also advertised ๐Ÿคฏ That means the client must negotiate TLS encryption with STARTTLS first, and at that point the SASL capability will list a non-empty list of SASL mechanisms ๐Ÿ”

SIEVE ๐Ÿง  A list of space-separated Sieve extensions (as listed in the Sieve "require" action [SIEVE]) supported by the Sieve engine. This capability MUST always be returned by the server โœจ

STARTTLS ๐Ÿ”’ Whether TLS [TLS] is supported by this implementation. Before advertising this capability, a server MUST verify to the best of its ability that TLS can be successfully negotiated by a client using common cipher suites. Specifically, a server should verify that a server certificate has been installed and that the TLS subsystem has successfully initialized ๐Ÿง This capability SHOULD NOT be advertised once STARTTLS or AUTHENTICATE command completes successfully. Client and server implementations MUST implement the STARTTLS extension ๐Ÿซถ

MAXREDIRECTS โ†ช๏ธ The limit on the number of Sieve "redirect" actions a script can perform during a single evaluation. Note that this is different from the total number of "redirect" actions a script can contain ๐Ÿ‘€ The value is a non-negative number represented as a ManageSieve string.

NOTIFY ๐Ÿ”” A space-separated list of URI schema parts for supported notification methods. This capability MUST be specified if the Sieve implementation supports the "enotify" extension [NOTIFY] ๐Ÿ“ฌ

LANGUAGE ๐ŸŒ The language (<Language-Tag> from [RFC5646]) currently used for human-readable error messages. If this capability is not returned, the "i-default" [RFC2277] language is assumed. Note that the current language MAY be configurable per user (i.e., it MAY change after authentication) ๐Ÿ—ฃ๏ธ

OWNER ๐Ÿ‘‘ The canonical name of the logged-in user (the SASL "authorization identity") encoded in UTF-8. This capability MUST NOT be returned in the unauthenticated state, and SHOULD be returned once the AUTHENTICATE command succeeds ๐Ÿ™‹โ€โ™€๏ธ

VERSION ๐Ÿท๏ธ This capability MUST be returned by servers compliant with this document or its successor. For servers compliant with this document, the capability value is the string "1.0". Lack of this capability means the server predates this specification and therefore doesn't support the following commands: RENAMESCRIPT, CHECKSCRIPT, and NOOP ๐Ÿ•ฐ๏ธ

Section 2.14 defines some additional ManageSieve extensions and their respective capabilities ๐Ÿงฉ

A server implementation MUST return the SIEVE, IMPLEMENTATION, and VERSION capabilities ๐Ÿซถ A client implementation MUST ignore any listed capabilities it does not understand ๐Ÿ’…

Here's what that looks like ๐Ÿ‘‡

S: "IMPlemENTATION" "Example1 ManageSieved v001"
S: "SASl" "DIGEST-MD5 GSSAPI"
S: "SIeVE" "fileinto vacation"
S: "StaRTTLS"
S: "NOTIFY" "xmpp mailto"
S: "MAXREdIRECTS" "5"
S: "VERSION" "1.0"
S: OK

And after successful authentication, it might look like this ๐Ÿ”“

S: "IMPlemENTATION" "Example1 ManageSieved v001"
S: "SASl" "DIGEST-MD5 GSSAPI"
S: "SIeVE" "fileinto vacation"
S: "NOTIFY" "xmpp mailto"
S: "OWNER" "alexey@example.com"
S: "MAXREdIRECTS" "5"
S: "VERSION" "1.0"
S: OK

1.8. Transport ๐Ÿš—

okay so ManageSieve is built on the idea of a reliable data stream, like what TCP gives you. when TCP is the transport, a ManageSieve server typically hangs out on port 4190 ๐Ÿฆ‹

before the client even opens the TCP connection, the ManageSieve client MUST first resolve the Domain Name System (DNS) hostname tied to the receiving entity and figure out the right TCP port to talk to it on. here's how it goes ๐Ÿ’…

  1. step one is trying to resolve the hostname with a [DNS-SRV] Service of sieve and a Proto of tcp for the target domain (like example.net). that gives you records such as _sieve._tcp.example.net. ๐Ÿ“ if the SRV lookup works, you get one or more combos of port and hostname. the ManageSieve client MUST resolve the returned hostnames to IPv4/IPv6 addresses according to the returned SRV record weight. the IP addresses from the first successfully resolved hostname (paired with the port from the SRV lookup) are used to connect. if connecting with one of those IP addresses fails, the next resolved IP address gets tried. if connecting to all of the resolved IP addresses fails, the resolve/connect process repeats for the next hostname from the SRV lookup ๐Ÿ”ฅ
  2. if the SRV lookup fails, the fallback SHOULD be a normal IPv4 or IPv6 address record resolution to find the IP address. the port used is the default ManageSieve port of 4190 ๐ŸŒธ

1.9. Conventions Used in This Document ๐Ÿ“š

the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [KEYWORDS] ๐Ÿค“

in examples, C: and S: show lines sent by the client and server respectively. line breaks that don't start a new C: or S: are there for editorial reasons, not because they mean anything ๐Ÿซถ

examples of authentication in this document use the DIGEST-MD5 [DIGEST-MD5] and GSSAPI [GSSAPI] SASL mechanisms โœจ


2. Commands ๐Ÿ’–

this section and its subsections describe the valid ManageSieve commands ๐ŸŽ€ when you first connect to the server, your session is in the non-authenticated state. before successful authentication, only the AUTHENTICATE, CAPABILITY, STARTTLS, LOGOUT, and NOOP (see Section 2.13) commands are valid ๐Ÿ” ManageSieve extensions MAY define other commands that are valid in the non-authenticated state. servers MUST reject all other commands with a NO response ๐Ÿšซ

clients may pipeline commands (send more than one command at a time without waiting for the first one to finish) ๐Ÿš€ however, a group of commands sent together MUST NOT have an AUTHENTICATE (*), a STARTTLS, or a HAVESPACE command anywhere but the last command in the list ๐Ÿ‘‘

(*) - the only exception to this rule is when the AUTHENTICATE command contains an initial response for a SASL mechanism that lets clients send data first, the mechanism is known to complete in one round trip, and the mechanism doesn't negotiate a SASL security layer. two examples of these SASL mechanisms are PLAIN [PLAIN] and EXTERNAL [SASL] ๐Ÿงš

2.1. AUTHENTICATE Command ๐Ÿ”

Arguments:  String - mechanism
            String - initial data (optional)

okay so the AUTHENTICATE command is how the client tells the server which SASL [SASL] mechanism it wants to use ๐Ÿ’…. If the server supports that mechanism, they run an authentication exchange to identify and authenticate the user. Optionally, they can also negotiate a security layer for what comes next ๐Ÿ”ฅ. If the mechanism isn't supported, the server rejects the command with the NO response ๐Ÿ™ˆ.

The exchange is a back-and-forth of server challenges and client responses, and they're specific to whichever mechanism got picked ๐Ÿฆ‹. A server challenge is a string (quoted or literal) followed by a CRLF, and its contents are the base-64 encoding [BASE64] of the SASL data. A client response is a string (quoted or literal) holding the base-64 encoding of the SASL data, followed by a CRLF. If the client wants to cancel the exchange, it sends a string containing a single "*". If the server gets that, it MUST reject the AUTHENTICATE command with a NO reply ๐Ÿ›‘.

An empty challenge or response is sent as an empty string. If the mechanism says the final response comes from the server, that data MAY go inside the data portion of the SASL response code, which saves a round trip โœจ.

The optional initial-response argument is there to save a round trip, but only for mechanisms that send no data in the initial challenge ๐Ÿงš. When it's used with one of those mechanisms, the empty initial challenge isn't sent to the client, and the server treats the initial-response data as if it had been sent in reply to that empty challenge. If the initial-response argument is used with a mechanism that does send data in the initial challenge, the server MUST reject the AUTHENTICATE command by sending the NO response.

The service name for this protocol's profile of SASL is "sieve" ๐ŸŽ€.

Reauthentication is not supported by the ManageSieve protocol's profile of SASL ๐Ÿ™…โ€โ™€๏ธ. So once an AUTHENTICATE command has completed successfully, no more AUTHENTICATE commands may be issued in that session. After a successful AUTHENTICATE command, the server MUST reject any further AUTHENTICATE commands with a NO reply.

But note that a server may implement the UNAUTHENTICATE extension described in Section 2.14.1. So it's not totally off the table, just a different command ๐Ÿ‘€.

If a security layer is negotiated through the SASL exchange, it takes effect right after the CRLF that ends the successful exchange for the client, and the CRLF of the OK response for the server ๐Ÿ”.

When a security layer takes effect, the ManageSieve protocol resets to its initial state (the state a client is in right after connecting to the server) ๐Ÿ”„. The server MUST discard any knowledge it got from the client that didn't come from the SASL (or TLS) negotiation itself. The client MUST do the same thing in reverse, discarding any knowledge it got from the server, such as the list of ManageSieve extensions, unless that came from the SASL (and/or TLS) negotiation itself. (Also, a client MAY compare the advertised SASL mechanisms before and after authentication to detect an active down-negotiation attack. More on that below ๐Ÿ‘€.)

Once a SASL security layer is established, the server MUST re-issue the capability results, followed by an OK response ๐Ÿ”. This protects against man-in-the-middle attacks that alter the capabilities list before SASL negotiation happens. The capability results MUST include all SASL mechanisms the server was able to negotiate with that client, so the client can spot an active down-negotiation attack. If a user-oriented client detects one, it SHOULD either notify the user (it MAY let the user carry on with the ManageSieve session in that case) or close the transport connection and say that a down-negotiation attack might be in progress ๐Ÿšจ. If an automated client detects one, it SHOULD return or log an error saying a possible attack might be in progress, and/or SHOULD close the transport connection.

When both [TLS] and SASL security layers are in effect, the TLS encoding MUST be applied (when sending data) after the SASL encoding ๐Ÿ“.

Server implementations SHOULD support SASL proxy authentication, so an administrator can manage a user's scripts ๐Ÿซถ. Proxy authentication is when a user authenticates as themselves but asks the server to act (authorize) as another user.

The authorization identity generated by this [SASL] exchange is a "simple username" (in the sense defined in [SASLprep]). Both client and server MUST use the [SASLprep] profile of the [StringPrep] algorithm to prepare these names before sending or comparing them ๐Ÿงผ. If preparing the authorization identity fails, or the result is an empty string (unless it was transmitted as the empty string), the server MUST fail the authentication ๐Ÿ’€.

If an AUTHENTICATE command fails with a NO response, the client MAY try another mechanism by sending another AUTHENTICATE command. So the client can ask for authentication types in decreasing order of preference ๐Ÿชœ.

A failed (NO) response to the AUTHENTICATE command may contain one of these response codes: AUTH-TOO-WEAK, ENCRYPT-NEEDED, or TRANSITION-NEEDED. See Section 1.3 for a detailed description of those conditions ๐Ÿ“–.

To make sure things interoperate, both client and server implementations of the ManageSieve protocol MUST implement the SCRAM-SHA-1 [SCRAM] SASL mechanism, as well as [PLAIN] over [TLS] ๐ŸŒˆ.

Note: using PLAIN over TLS reflects how PLAIN over TLS is currently used in other email-related protocols. Still, a longer-term goal is to move email-related protocols from PLAIN over TLS to the SCRAM-SHA-1 mechanism ๐ŸŒธ.

Here are some examples! (Long lines are folded for readability and are not part of the protocol exchange ๐Ÿ™)

S: "IMPLEMENTATION" "Example1 ManageSieved v001"
S: "SASL" "DIGEST-MD5 GSSAPI"
S: "SIEVE" "fileinto vacation"
S: "STARTTLS"
S: "VERSION" "1.0"
S: OK
C: Authenticate "DIGEST-MD5"
S: "cmVhbG09ImVsd29vZC5pbm5vc29mdC5leGFtcGxlLmNvbSIsbm9uY2U9Ik
   9BNk1HOXRFUUdtMmhoIixxb3A9ImF1dGgiLGFsZ29yaXRobT1tZDUtc2Vz
   cyxjaGFyc2V0PXV0Zi04"
C: "Y2hhcnNldD11dGYtOCx1c2VybmFtZT0iY2hyaXMiLHJlYWxtPSJlbHdvb2
   QuaW5ub3NvZnQuZXhhbXBsZS5jb20iLG5vbmNlPSJPQTZNRzl0RVFHbTJo
   aCIsbmM9MDAwMDAwMDEsY25vbmNlPSJPQTZNSFhoNlZxVHJSayIsZGlnZX
   N0LXVyaT0ic2lldmUvZWx3b29kLmlubm9zb2Z0LmV4YW1wbGUuY29tIixy
   ZXNwb25zZT1kMzg4ZGFkOTBkNGJiZDc2MGExNTIzMjFmMjE0M2FmNyxxb3
   A9YXV0aA=="
S: OK (SASL "cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZ
   mZmZA==")

A slightly different variant of the same exchange looks like this:

S: "IMPLEMENTATION" "Example1 ManageSieved v001"
S: "SASL" "DIGEST-MD5 GSSAPI"
S: "SIEVE" "fileinto vacation"
S: "VERSION" "1.0"
S: "STARTTLS"
S: OK
C: Authenticate "DIGEST-MD5"
S: {136}
S: cmVhbG09ImVsd29vZC5pbm5vc29mdC5leGFtcGxlLmNvbSIsbm9uY2U9Ik
   9BNk1HOXRFUUdtMmhoIixxb3A9ImF1dGgiLGFsZ29yaXRobT1tZDUtc2Vz
   cyxjaGFyc2V0PXV0Zi04
C: {300+}
C: Y2hhcnNldD11dGYtOCx1c2VybmFtZT0iY2hyaXMiLHJlYWxtPSJlbHdvb2
   QuaW5ub3NvZnQuZXhhbXBsZS5jb20iLG5vbmNlPSJPQTZNRzl0RVFHbTJo
   aCIsbmM9MDAwMDAwMDEsY25vbmNlPSJPQTZNSFhoNlZxVHJSayIsZGlnZX
   N0LXVyaT0ic2lldmUvZWx3b29kLmlubm9zb2Z0LmV4YW1wbGUuY29tIixy
   ZXNwb25zZT1kMzg4ZGFkOTBkNGJiZDc2MGExNTIzMjFmMjE0M2FmNyxxb3
   A9YXV0aA==
S: {56}
S: cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZA==
C: ""
S: OK

Another example shows the SASL PLAIN mechanism under TLS. It also shows the SASL "initial response" (the second parameter to the Authenticate command) in action ๐Ÿง:

S: "IMPLEMENTATION" "Example1 ManageSieved v001"
S: "VERSION" "1.0"
S: "SASL" ""
S: "SIEVE" "fileinto vacation"
S: "STARTTLS"
S: OK
C: STARTTLS
S: OK
<TLS negotiation, further commands are under TLS layer>
S: "IMPLEMENTATION" "Example1 ManageSieved v001"
S: "VERSION" "1.0"
S: "SASL" "PLAIN"
S: "SIEVE" "fileinto vacation"
S: OK
C: Authenticate "PLAIN" "QJIrweAPyo6Q1T9xu"
S: NO
C: Authenticate "PLAIN" "QJIrweAPyo6Q1T9xz"
S: NO
C: Authenticate "PLAIN" "QJIrweAPyo6Q1T9xy"
S: BYE "Too many failed authentication attempts"
<Server closes connection>

The next one shows a SASL "initial response" in use. It also shows an empty response being sent as a literal, and a SASL security layer making the server re-issue its capabilities ๐Ÿคฉ:

C: AUTHENTICATE "GSSAPI" {1488+}
C: YIIE[...1480 octets here ...]dA==
S: {208}
S: YIGZBgkqhkiG9xIBAgICAG+BiTCBhqADAgEFoQMCAQ+iejB4oAMCARKic
   [...114 octets here ...]
   /yzpAy9p+Y0LanLskOTvMc0MnjgAa4YEr3eJ6
C: {0+}
C:
S: {44}
S: BQQF/wAMAAwAAAAAYRGFAo6W0vIHti8i1UXODgEAEAA=
C: {44+}
C: BQQE/wAMAAwAAAAAIsT1iv9UkZApw471iXt6cwEAAAE=
S: OK
<Further commands/responses are under SASL security layer>
S: "IMPLEMENTATION" "Example1 ManageSieved v001"
S: "VERSION" "1.0"
S: "SASL" "PLAIN DIGEST-MD5 GSSAPI"
S: "SIEVE" "fileinto vacation"
S: "LANGUAGE" "ru"
S: "MAXREDIRECTS" "3"
S: ok

2.1.1. Use of SASL PLAIN Mechanism over TLS ๐Ÿ›ก๏ธ

This section is normative for ManageSieve client implementations that support SASL [PLAIN] over [TLS] ๐Ÿ“œ.

If a ManageSieve client is willing to use SASL PLAIN over TLS to authenticate to the ManageSieve server, the client MUST verify the server identity (see Section 2.2.1) ๐Ÿ•ต๏ธโ€โ™€๏ธ. If the server identity can't be verified (for example, the server hasn't provided any certificate, or the certificate verification fails), the client MUST NOT attempt to authenticate using the SASL PLAIN mechanism ๐Ÿ™…โ€โ™€๏ธ๐Ÿ’–

2.2. STARTTLS Command

okay so STARTTLS is optional for servers ๐Ÿ’… Servers that do support it announce it with the "STARTTLS" capability, see Section 1.7 ๐ŸŽ€

The STARTTLS command asks to start a TLS [TLS] negotiation โœจ The negotiation kicks off right after the CRLF in the OK response. Once a client sends STARTTLS, it MUST NOT send any more commands until it has seen a server response and the TLS negotiation is done ๐Ÿซถ

STARTTLS only works in the non-authenticated state ๐Ÿ”’ The server stays non-authenticated even if the client hands over credentials during the TLS negotiation. The SASL [SASL] EXTERNAL mechanism MAY be used to authenticate once TLS client credentials have been exchanged successfully. Servers that support STARTTLS are not required to support EXTERNAL though, so don't panic if it's missing ๐Ÿฆ‹

After the TLS layer is up, the server MUST send the capability results again, followed by an OK response. This is there to guard against man-in-the-middle attacks that tamper with the capabilities list before STARTTLS happens ๐Ÿ‘€ And these capability results MUST NOT include the STARTTLS capability ๐Ÿ™…โ€โ™€๏ธ

The client MUST throw out its cached capability info and replace it with the new stuff. The server MAY advertise different capabilities after STARTTLS ๐ŸŒˆ

Example:

C: StartTls S: oK <TLS negotiation, further commands are under TLS layer> S: "IMPLEMENTATION" "Example1 ManageSieve v001" S: "SASL" "PLAIN DIGEST-MD5 GSSAPI" S: "SIEVE" "fileinto vacation" S: "VERSION" "1.0" S: "LANGUAGE" "fr" S: ok

2.2.1. Server Identity Check

Okay this part is serious but also iconic ๐Ÿ•ต๏ธโ€โ™€๏ธ During the TLS negotiation, the ManageSieve client MUST check its understanding of the server hostname/IP address against the server's identity as shown in the server Certificate message. This is how we stop man-in-the-middle attacks ๐Ÿ›ก๏ธ In this section, the client's understanding of the server's identity is called the "reference identity".

Checking follows these rules:

  • If the reference identity is a hostname:
    1. If a subjectAltName extension of the SRVName [X509-SRV], dNSName [X509] (in that order of preference) type is present in the server's certificate, then it SHOULD be used as the source of the server's identity. Matching is done as described in Section 2.2.1.1, except that no wildcard matching is allowed for the SRVName type. If the certificate has multiple names (for example, more than one dNSName field), then a match with any one of those fields is good enough โœ…
    2. The client MAY use other types of subjectAltName for the comparison ๐Ÿ’œ
    3. The server's identity MAY also be verified by comparing the reference identity to the Common Name (CN) [RFC4519] value in the leaf Relative Distinguished Name (RDN) of the subjectName field of the server's certificate. This comparison uses the rules for comparing DNS names in Section 2.2.1.1, below. Using the Common Name is existing practice, but it is deprecated, and Certification Authorities are encouraged to provide subjectAltName values instead ๐Ÿ™ƒ Also, the TLS implementation may represent DNs in certificates according to X.500 or other conventions. For example, some X.500 implementations order the RDNs in a DN using a left-to-right (most significant to least significant) convention instead of LDAP's right-to-left convention ๐Ÿง 
  • When the reference identity is an IP address, the iPAddress subjectAltName SHOULD be used by the client for comparison. The comparison is done as described in Section 2.2.1.2 ๐ŸŒธ

If the server identity check fails, user-oriented clients SHOULD either notify the user (clients MAY give the user the chance to continue with the ManageSieve session in this case) or close the transport connection and indicate that the server's identity is suspect ๐Ÿšจ Automated clients SHOULD return or log an error saying that the server's identity is suspect, and/or SHOULD close the transport connection. Automated clients MAY offer a configuration setting that disables this check, but they MUST offer a setting that enables it ๐Ÿ”ฅ

Beyond the server identity check in this section, clients should be prepared to do further checking to make sure the server is authorized to provide the service it's asked to provide ๐Ÿ‘‘ The client may need to use local policy information to decide that.

2.2.1.1. Comparison of DNS Names

If the reference identity is an internationalized domain name, conforming implementations MUST convert it to the ASCII Compatible Encoding (ACE) format as specified in Section 4 of RFC 3490 [RFC3490] before comparing it with subjectAltName values of type dNSName. To be specific, conforming implementations MUST do the conversion operation from Section 4 of [RFC3490] like this:

  • in step 1, the domain name SHALL be considered a "stored string";
  • in step 3, set the flag called "UseSTD3ASCIIRules";
  • in step 4, process each label with the "ToASCII" operation; and
  • in step 5, change all label separators to U+002E (full stop).

After the "to-ASCII" conversion, the DNS labels and names MUST be compared for equality using the rules in Section 3 of [RFC3490]. In other words, once all label separators have been replaced with U+002E (dot), they're compared case-insensitively ๐Ÿ”ค

The * (ASCII 42) wildcard character is allowed in subjectAltName values of type dNSName, but only as the left-most (least significant) DNS label in that value. This wildcard matches any left-most DNS label in the server name. So the subject *.example.com matches the server names a.example.com and b.example.com, but it does not match example.com or a.b.example.com ๐ŸŒŸ

2.2.1.2. Comparison of IP Addresses

When the reference identity is an IP address, the identity MUST be converted to the "network byte order" octet string representation [RFC791][RFC2460]. For IP Version 4, as specified in RFC 791, the octet string will contain exactly four octets. For IP Version 6, as specified in RFC 2460, the octet string will contain exactly sixteen octets. That octet string is then compared against subjectAltName values of type iPAddress. A match happens if the reference identity octet string and the value octet string are identical ๐Ÿงฎ

2.2.1.3. Comparison of Other subjectName Types

Client implementations MAY support matching against subjectAltName values of other types, as described in other documents ๐Ÿฆ„

2.3. LOGOUT Command

The client sends the LOGOUT command when it's done with a connection and wants to end it ๐Ÿ‘‹ The server MUST reply with an OK response. The server MUST ignore any commands the client sends after LOGOUT ๐Ÿšซ

The client SHOULD wait for the OK response before closing the connection. This avoids the TCP connection going into the TIME_WAIT state on the server ๐ŸŒ™ To avoid going into the TIME_WAIT TCP state, the server MAY wait a short while for the client to close the TCP connection first. Whether or not the server waits, it MUST then close the connection itself ๐Ÿ’–

Example:

C: Logout S: Ok <connection is terminated>

2.4. CAPABILITY Command

The CAPABILITY command asks for the server capabilities, as described earlier in this document ๐ŸŽ€ It has no parameters.

Example:

C: CAPABILITY S: "IMPLEMENTATION" "Example1 ManageSieve v001" S: "VERSION" "1.0" S: "SASL" "PLAIN SCRAM-SHA-1 GSSAPI" S: "SIEVE" "fileinto vacation" S: "STARTTLS" S: OK

2.5. HAVESPACE Command

Arguments: String - name Number - script size

The HAVESPACE command is how you ask the server if there's room โœจ Clients give the name they want to save the script as, plus its size in octets. The server can use both parameters to check whether a script with that name and size fits within a user's quota(s). For example, the server MAY use the script name to see if a script would be replaced or a brand-new one would be created ๐Ÿง Servers reply with a NO if storing a script with that name and size would fail, or with OK otherwise. Clients SHOULD send this command before they try to put a script on the server ๐Ÿ“ฆ

Heads up though, an OK from HAVESPACE is NOT a promise ๐Ÿ™ˆ Server disk space can change between the HAVESPACE and the PUTSCRIPT commands. A QUOTA response code (see Section 1.3) is still a possible, albeit unlikely, reply to a later PUTSCRIPT with the same name and size ๐Ÿ’€

Example:

C: HAVESPACE "myscript" 999999 S: NO (QUOTA/MAXSIZE) "Quota exceeded"

C: HAVESPACE "foobar" 435 S: OK

2.6. PUTSCRIPT Command ๐Ÿ’–

Arguments:  String - Script name
            String - Script content

Okay so PUTSCRIPT is how the client sends a Sieve script up to the server ๐Ÿซถ

If the script already exists, the old one gets overwritten on success. Here's the important bit though: the old script MUST NOT be overwritten if PUTSCRIPT fails in any way ๐Ÿ˜ญ A script of zero length SHOULD be disallowed ๐Ÿ™…โ€โ™€๏ธ

This command just puts the script on the server. It doesn't change whether anything gets processed on incoming mail, unless it replaces the script that's already active. To mark a script as active, you use the SETACTIVE command โœจ

When you're submitting big scripts, clients SHOULD use the HAVESPACE command first to ask if the server is willing to accept a script that size ๐Ÿงš

Now the validity check, which is giving serious gatekeeper energy ๐Ÿ‘‘ The server MUST check the submitted script for validity. That includes checking that the script follows the Sieve grammar [SIEVE] and that every Sieve extension mentioned in the script's "require" statement(s) is supported by the Sieve interpreter. (Quick side note: if the Sieve interpreter supports the Sieve "ihave" extension [I-HAVE], then any unrecognized or unsupported extension mentioned in the "ihave" test MUST NOT cause the validation failure ๐Ÿฆ‹) Other checks, like validating the supplied command arguments for each command, MAY be performed. Basically, the validation SHOULD be the same as what happens when the script gets compiled for execution. Implementations that store compiled scripts in a binary representation can extend validation to a full compilation, so they don't have to validate uploaded scripts more than once ๐ŸŒธ

If the script fails validation, the server MUST reply with a NO response. Any script that fails the validity test MUST NOT be stored on the server ๐Ÿšซ The message with that NO response MUST be human readable and SHOULD include a specific error message giving the line number of the first error. Implementors should strive for helpful error messages, the kind you'd get from programming language compilers ๐Ÿ’… Client implementations should know this may be a multiline literal string with more than one error message, separated by CRLFs. The human-readable message is in the language returned in the latest LANGUAGE capability (or in "i-default"; see Section 1.7), and it's encoded in UTF-8 [UTF-8].

An OK response MAY contain the WARNINGS response code. When it does, the human-readable message after the OK response SHOULD contain a specific warning (or warnings) giving the line number(s) in the script that might have errors the script writer didn't intend โš ๏ธ Same language rule applies: the latest LANGUAGE capability (or "i-default"; see Section 1.7), encoded in UTF-8 [UTF-8]. A client that sees this response code SHOULD show the message to the user ๐ŸŽ€

Examples:

C: Putscript "foo" {31+}
C: #comment
C: InvalidSieveCommand
C:
S: NO "line 2: Syntax error"

C: Putscript "mysievescript" {110+}
C: require ["fileinto"];
C:
C: if envelope :contains "to" "tmartin+sent" {
C:   fileinto "INBOX.sent";
C: }
S: OK

C: Putscript "myforwards" {190+}
C: redirect "111@example.net";
C:
C: if size :under 10k {
C:     redirect "mobile@cell.example.com";
C: }
C:
C: if envelope :contains "to" "tmartin+lists" {
C:     redirect "lists@groups.example.com";
C: }
S: OK (WARNINGS) "line 8: server redirect action
        limit is 2, this redirect might be ignored"

2.7. LISTSCRIPTS Command ๐ŸŒˆ

This one lists the scripts the user has on the server ๐Ÿ“œ On success, you get back a list of CRLF-separated script names (each one a quoted or literal string), followed by an OK response. If there's an active script, the atom ACTIVE gets tacked onto that script's name. The atom ACTIVE MUST NOT appear on more than one response line ๐Ÿ’œ

Example:

C: Listscripts
S: "summer_script"
S: "vacation_script"
S: {13}
S: clever"script
S: "main_script" ACTIVE
S: OK

C: listscripts
S: "summer_script"
S: "main_script" active
S: OK

2.8. SETACTIVE Command โœจ

Arguments:  String - script name

This command sets a script to active ๐Ÿฆ‹ If the script name is the empty string (i.e., ""), then any active script gets disabled. Disabling an active script when there's no active script is not an error and MUST result in an OK reply ๐Ÿซถ

If the script doesn't exist on the server, the server MUST reply with a NO response. That reply SHOULD contain the NONEXISTENT response code ๐Ÿ™ˆ

Examples:

C: Setactive "vacationscript"
S: Ok

C: Setactive ""
S: Ok

C: Setactive "baz"
S: No (NONEXISTENT) "There is no script by that name"

C: Setactive "baz"
S: No (NONEXISTENT) {31}
S: There is no script by that name

2.9. GETSCRIPT Command ๐Ÿ“

Arguments:  String - script name

This command gets the contents of the script you ask for ๐Ÿ“– If the script doesn't exist, the server MUST reply with a NO response. That reply SHOULD contain the NONEXISTENT response code ๐Ÿ’€

On success, you get a string with the script's contents, followed by an OK response.

Example:

C: Getscript "myscript"
S: {54}
S: #this is my wonderful script
S: reject "I reject all";
S:
S: OK

2.10. DELETESCRIPT Command ๐Ÿ—‘๏ธ

Arguments:  String - script name

This command deletes a user's Sieve script. Servers MUST reply with a NO response if the script doesn't exist, and those responses SHOULD include the NONEXISTENT response code ๐Ÿ™…โ€โ™€๏ธ

Here's the drama: the server MUST NOT let the client delete an active script, so it MUST reply with a NO response if someone tries ๐Ÿ˜ค That response SHOULD contain the ACTIVE response code. If a client really wants to delete an active script, it should use the SETACTIVE command to disable the script first ๐Ÿ”ฅ

Example:

C: Deletescript "foo"
S: Ok

C: Deletescript "baz"
S: No (ACTIVE) "You may not delete an active script"

2.11. RENAMESCRIPT Command ๐ŸŽ€

Arguments:  String - Old Script name
            String - New Script name

This command renames a user's Sieve script โœ๏ธ Servers MUST reply with a NO response if the old script doesn't exist (in which case the NONEXISTENT response code SHOULD be included), or if a script with the new name already exists (in which case the ALREADYEXISTS response code SHOULD be included). Renaming the active script is allowed, and the renamed script stays active ๐ŸŒธ

Example:

C: Renamescript "foo" "bar"
S: Ok

C: Renamescript "baz" "bar"
S: No "bar already exists"

If the server doesn't support the RENAMESCRIPT command, the client can fake it by doing these steps:

  1. List the available scripts with LISTSCRIPTS. If the script with the new name exists, then the client should ask the user whether to abort the operation, to replace the script (by issuing DELETESCRIPT <newname> after that), or to choose a different name.
  2. Download the old script with GETSCRIPT <oldname>.
  3. Upload the old script under the new name: PUTSCRIPT <newname>.
  4. If the old script was active (as reported by LISTSCRIPTS in step 1), then make the new script active: SETACTIVE <newname>.
  5. Delete the old script: DELETESCRIPT <oldname>.

Heads up, though: these steps don't cover the other error conditions (for example, a NO response with the QUOTA response code in step 3). Error handling is left as an exercise for the reader ๐Ÿง 


2.12. CHECKSCRIPT Command ๐Ÿ”

Arguments:  String - Script content

The client uses CHECKSCRIPT to check that a Sieve script is valid without storing it on the server โœ…

The server MUST check the submitted script for syntactic validity. That includes checking that all Sieve extensions mentioned in the script's "require" statement(s) are supported by the Sieve interpreter. (Same deal as before: if the Sieve interpreter supports the Sieve "ihave" extension [I-HAVE], then any unrecognized or unsupported extension mentioned in the "ihave" test MUST NOT cause the syntactic validation failure.) If the script fails this test, the server MUST reply with a NO response. The message with that NO response MUST be human readable and SHOULD include a specific error message giving the line number of the first error. Implementors should strive for helpful error messages, like the ones programming language compilers give ๐Ÿ’– Client implementations should know this may be a multiline literal string with more than one error message, separated by CRLFs. The human-readable message is in the language returned in the latest LANGUAGE capability (or in "i-default"; see Section 1.7), encoded in UTF-8 [UTF-8].

Examples:

C: CheckScript {31+}
C: #comment
C: InvalidSieveCommand
C:
S: NO "line 2: Syntax error"

A ManageSieve server that supports this command MUST NOT check whether the script would put the current user over its quota limit ๐Ÿ™…โ€โ™€๏ธ

An OK response MAY contain the WARNINGS response code. When it does, the human-readable message after the OK response SHOULD contain a specific warning (or warnings) giving the line number(s) in the script that might have errors the script writer didn't intend. It's in the language returned in the latest LANGUAGE capability (or "i-default"; see Section 1.7), encoded in UTF-8 [UTF-8]. A client that sees this response code SHOULD show the message to the user ๐Ÿซถ


2.13. NOOP Command ๐Ÿ˜ด

Arguments:  String - tag to echo back (optional)

NOOP literally does nothing, except send back a response to the client ๐Ÿ™ƒ Clients can use it for protocol re-synchronization, or to reset the server's inactivity auto-logout timer โฑ๏ธ

The response to NOOP is always OK, followed by the TAG response code together with the supplied string. If no string was supplied in the NOOP command, the TAG response code MUST NOT be included ๐Ÿงš

Examples:

C: NOOP
S: OK "NOOP completed"

C: NOOP "STARTTLS-SYNC-42"
S: OK (TAG {16}
S: STARTTLS-SYNC-42) "Done"

The UNAUTHENTICATE extension (advertised with the "UNAUTHENTICATE" capability and no parameters) defines a new UNAUTHENTICATE command. It lets a client send the server back to the non-authenticated state ๐Ÿฆ‹ Support for this extension is RECOMMENDED ๐Ÿ’…

2.14.1. UNAUTHENTICATE Command ๐Ÿ”“

The UNAUTHENTICATE command returns the server to the non-authenticated state. It doesn't touch any TLS [TLS] or SASL (Section 2.1) security layer that was already set up ๐Ÿ”

The UNAUTHENTICATE command is only valid in the authenticated state. If it's issued in the wrong state, the server MUST reject it with a NO response โŒ

The UNAUTHENTICATE command has no parameters.

When UNAUTHENTICATE is issued in the authenticated state, it MUST NOT fail. In other words, it must never return anything other than OK or BYE ๐Ÿ˜ญ

3. Sieve URL Scheme ๐Ÿฆ‹

okay bestie, this section is all about sieve:// URLs, which are basically little addresses that point at a ManageSieve server or a specific Sieve script on it ๐ŸŒธ

  • URI scheme name: sieve
  • Status: permanent

For the syntax, the spec uses ABNF [ABNF], and a few pieces it borrows from [URI-GEN]. Here's the whole URL grammar ๐Ÿ’…

sieveurl = sieveurl-server / sieveurl-list-scripts /
           sieveurl-script

sieveurl-server = "sieve://" authority

sieveurl-list-scripts = "sieve://" authority ["/"]

sieveurl-script = "sieve://" authority "/"
                  [owner "/"] scriptname

authority = <defined in [URI-GEN]>

owner         = *ochar
                ;; %-encoded version of [SASL] authorization
                ;; identity (script owner) or "userid".
                ;;
                ;; Empty owner is used to reference
                ;; global scripts.
                ;;
                ;; Note that ASCII characters such as " ", ";",
                ;; "&", "=", "/" and "?" must be %-encoded
                ;; as per rule specified in [URI-GEN].

scriptname    = 1*ochar
                ;; %-encoded version of UTF-8 representation
                ;; of the script name.
                ;; Note that ASCII characters such as " ", ";",
                ;; "&", "=", "/" and "?" must be %-encoded
                ;; as per rule specified in [URI-GEN].

ochar         = unreserved / pct-encoded / sub-delims-sh /
                ":" / "@"
                ;; Same as [URI-GEN] 'pchar',
                ;; but without ";", "&" and "=".

unreserved = <defined in [URI-GEN]>

pct-encoded = <defined in [URI-GEN]>
sub-delims-sh = "!" / "$" / "'" / "(" / ")" /
                "*" / "+" / ","
                ;; Same as [URI-GEN] sub-delims,
                ;; but without ";", "&" and "=".

Now the vibe check. A sieve URL can point at a whole server, at the script list, or at one script ๐Ÿ’– The server form is what the REFERRAL response code uses (see Section 1.3) to send a client over to another server where it should do its business ๐Ÿฆ‹

The script form lets you GETSCRIPT, PUTSCRIPT, DELETESCRIPT, or SETACTIVE a named script, but honestly the main thing people do is just grab the script โœจ And if the script name is empty or left out, the URL is basically saying "hey, list what's available" using LISTSCRIPTS ๐Ÿงš

There's also an application/sieve MIME type from [SIEVE] that goes with the script form. The server form doesn't have a MIME type at all, so don't go looking for one ๐Ÿ™ˆ

The script name and owner (if they're there) are in UTF-8. Any non-US-ASCII UTF-8 octets MUST be percent-encoded as described in [URI-GEN] ๐Ÿซถ The US-ASCII characters like space, ;, &, =, /, and ? MUST be %-encoded too, also as described in [URI-GEN]. The & and ? are on that list just so future extensions have room to breathe ๐ŸŒˆ

Heads up on the empty owner vs. missing owner thing, it's lowkey important ๐Ÿ‘‘ sieve://example.com//script has an empty owner, and that's different from sieve://example.com/script, which has no owner at all. The empty one is reserved for global scripts โœจ

The user name in the authority part, if there is one, is also UTF-8, and any non-US-ASCII UTF-8 octets there MUST be percent-encoded as described in [URI-GEN] ๐Ÿ’œ

Who uses this? ManageSieve [RFC5804] clients and servers, obviously ๐Ÿ’… Also clients that can keep user preferences in protocols like [LDAP] or [ACAP] ๐Ÿ“

Interoperability considerations: None. Zero drama ๐ŸŒธ

Security considerations: ngl this part is kind of serious, so read it carefully ๐Ÿ˜ญ The <scriptname> part of a ManageSieve URL might potentially disclose some confidential information about the author of the script or, depending on a ManageSieve implementation, about configuration of the mail system. The latter might be used to prepare for a more complex attack on the mail system. Clients resolving ManageSieve URLs that wish to achieve data confidentiality and/or integrity SHOULD use the STARTTLS command (if supported by the server) before starting authentication, or use a SASL mechanism, such as GSSAPI, that provides a confidentiality security layer.

Contact: Alexey Melnikov <alexey.melnikov@isode.com> ๐ŸŽ€

Author/Change controller: IESG.

References: This document and RFC 5228 [SIEVE].


4. Formal Syntax โœจ

okay the grammar section, the part where the details live ๐Ÿค“ The spec uses ABNF [ABNF] and the ABNF core rules from Appendix A of that same spec. The "UTF8-2", "UTF8-3", and "UTF8-4" non-terminals come from [UTF-8].

Mostly, everything is case-insensitive. Writing tokens in upper or lower case is just for editorial clarity, so it doesn't change anything. Implementations MUST accept these strings in a case-insensitive way, no exceptions ๐Ÿซถ

Here are the basic character building blocks ๐Ÿงฑ

SAFE-CHAR             = %x01-09 / %x0B-0C / %x0E-21 / %x23-5B /
                        %x5D-7F
                        ;; any TEXT-CHAR except QUOTED-SPECIALS

QUOTED-CHAR           = SAFE-UTF8-CHAR / "\" QUOTED-SPECIALS

QUOTED-SPECIALS       = DQUOTE / "\"

SAFE-UTF8-CHAR        = SAFE-CHAR / UTF8-2 / UTF8-3 / UTF8-4
                        ;; <UTF8-2>, <UTF8-3>, and <UTF8-4>
                        ;; are defined in [UTF-8].

ATOM-CHAR             = "!" / %x23-27 / %x2A-5B / %x5D-7A / %x7C-7E
                        ;; Any CHAR except ATOM-SPECIALS

ATOM-SPECIALS         = "(" / ")" / "{" / SP / CTL / QUOTED-SPECIALS

NZDIGIT               = %x31-39
                        ;; 1-9

atom                  = 1*1024ATOM-CHAR

iana-token            = atom
                        ;; MUST be registered with IANA

auth-type             = DQUOTE auth-type-name DQUOTE

auth-type-name        = iana-token
                        ;; as defined in SASL [SASL]

Next up are the commands, and they're modal, so what you're allowed to send depends on your state ๐Ÿฆ‹

command               = (command-any / command-auth /
                         command-nonauth) CRLF
                        ;; Modal based on state

command-any           = command-capability / command-logout /
                        command-noop
                        ;; Valid in all states

command-auth          = command-getscript / command-setactive /
                        command-listscripts / command-deletescript /
                        command-putscript / command-checkscript /
                        command-havespace /
                        command-renamescript /
                        command-unauthenticate
                        ;; Valid only in Authenticated state

command-nonauth       = command-authenticate / command-starttls
                        ;; Valid only when in Non-Authenticated
                        ;; state

command-authenticate  = "AUTHENTICATE" SP auth-type [SP string]
                        *(CRLF string)

command-capability    = "CAPABILITY"

command-deletescript  = "DELETESCRIPT" SP sieve-name

command-getscript     = "GETSCRIPT" SP sieve-name

command-havespace     = "HAVESPACE" SP sieve-name SP number

command-listscripts   = "LISTSCRIPTS"

command-noop          = "NOOP" [SP string]

command-logout        = "LOGOUT"

command-putscript     = "PUTSCRIPT" SP sieve-name SP sieve-script

command-checkscript   = "CHECKSCRIPT" SP sieve-script

sieve-script          = string

command-renamescript  = "RENAMESCRIPT" SP old-sieve-name SP
                        new-sieve-name

old-sieve-name        = sieve-name

new-sieve-name        = sieve-name

command-setactive     = "SETACTIVE" SP active-sieve-name

command-starttls      = "STARTTLS"

command-unauthenticate= "UNAUTHENTICATE"

Extensions get their own tokens and data formats, and there's a rule about who's allowed to define them ๐Ÿ‘‘

extend-token          = atom
                        ;; MUST be defined by a Standards Track or
                        ;; IESG-approved experimental protocol
                        ;; extension

extension-data        = extension-item *(SP extension-item)

extension-item        = extend-token / string / number /
                        "(" [extension-data] ")"

Now the literals, the numbers, and the response stuff ๐Ÿ’–

literal-c2s           = "{" number "+}" CRLF *OCTET
                        ;; The number represents the number of
                        ;; octets.
                        ;; This type of literal can only be sent
                        ;; from the client to the server.

literal-s2c           = "{" number "}" CRLF *OCTET
                        ;; Almost identical to literal-c2s,
                        ;; but with no '+' character.
                        ;; The number represents the number of
                        ;; octets.
                        ;; This type of literal can only be sent
                        ;; from the server to the client.

number                = (NZDIGIT *DIGIT) / "0"
                        ;; A 32-bit unsigned number
                        ;; with no extra leading zeros.
                        ;; (0 <= n < 4,294,967,296)

number-str            = string
                        ;; <number> encoded as a <string>.

quoted                = DQUOTE *1024QUOTED-CHAR DQUOTE
                        ;; limited to 1024 octets between the <">s

resp-code             = "AUTH-TOO-WEAK" / "ENCRYPT-NEEDED" / "QUOTA"
                        ["/" ("MAXSCRIPTS" / "MAXSIZE")] /
                        resp-code-sasl /
                        resp-code-referral /
                        "TRANSITION-NEEDED" / "TRYLATER" /
                        "ACTIVE" / "NONEXISTENT" /
                        "ALREADYEXISTS" / "WARNINGS" /
                        "TAG" SP string /
                        resp-code-ext

resp-code-referral    = "REFERRAL" SP sieveurl

resp-code-sasl        = "SASL" SP string

resp-code-name        = iana-token
                        ;; The response code name is hierarchical,
                        ;; separated by '/'.
                        ;; The response code name MUST NOT start
                        ;; with '/'.

resp-code-ext         = resp-code-name [SP extension-data]
                        ;; unknown response codes MUST be tolerated
                        ;; by the client.

And finally, the response grammar, where the server gets to talk back ๐Ÿซถ

response              = response-authenticate /
                        response-logout /
                        response-getscript /
                        response-setactive /
                        response-listscripts /
                        response-deletescript /
                        response-putscript /
                        response-checkscript /
                        response-capability /
                        response-havespace /
                        response-starttls /
                        response-renamescript /
                        response-noop /
                        response-unauthenticate

response-authenticate = *(string CRLF)
                        ((response-ok [response-capability]) /
                         response-nobye)
                        ;; <response-capability> is REQUIRED if a
                        ;; SASL security layer was negotiated and
                        ;; MUST be omitted otherwise.

response-capability   = *(single-capability) response-oknobye

single-capability     = capability-name [SP string] CRLF

capability-name       = string
                        ;; Note that literal-s2c is allowed.
    initial-capabilities  = DQUOTE "IMPLEMENTATION" DQUOTE SP string /
                            DQUOTE "SASL" DQUOTE SP sasl-mechs /
                            DQUOTE "SIEVE" DQUOTE SP sieve-extensions /
                            DQUOTE "MAXREDIRECTS" DQUOTE SP number-str /
                            DQUOTE "NOTIFY" DQUOTE SP notify-mechs /
                            DQUOTE "STARTTLS" DQUOTE /
                            DQUOTE "LANGUAGE" DQUOTE SP language /
                            DQUOTE "VERSION" DQUOTE SP version /
                            DQUOTE "OWNER" DQUOTE SP string
                            ;; Each capability conforms to
                            ;; the syntax for single-capability.
                            ;; Also, note that the capability name
                            ;; can be returned as either literal-s2c
                            ;; or quoted, even though only "quoted"
                            ;; string is shown above.

    version = ( DQUOTE "1.0" DQUOTE ) / version-ext

    version-ext = DQUOTE ver-major "." ver-minor DQUOTE
                 ; Future versions specified in updates
                 ; to this document.  An increment to
                 ; the ver-major means a backward-incompatible
                 ; change to the protocol, e.g., "3.5" (ver-major "3")
                 ; is not backward-compatible with any "2.X" version.
                 ; Any version "Z.W" MUST be backward compatible
                 ; with any version "Z.Q", where Q < W.
                 ; For example, version "2.4" is backward compatible
                 ; with version "2.0", "2.1", "2.2", and "2.3".

    ver-major = number
    ver-minor = number

    sasl-mechs = string
                 ; Space-separated list of SASL mechanisms,
                 ; each SASL mechanism name complies with rules
                 ; specified in [SASL].
                 ; Can be empty.

    sieve-extensions = string
                 ; Space-separated list of supported SIEVE extensions.
                 ; Can be empty.

    language     = string
                 ; Contains <Language-Tag> from [RFC5646].


    notify-mechs = string
                 ; Space-separated list of URI schema parts
                 ; for supported notification [NOTIFY] methods.
                 ; MUST NOT be empty.

    response-deletescript = response-oknobye

    response-getscript    = (sieve-script CRLF response-ok) /
                            response-nobye

    response-havespace    = response-oknobye

    response-listscripts  = *(sieve-name [SP "ACTIVE"] CRLF)
                            response-oknobye
                            ;; ACTIVE may only occur with one sieve-name

    response-logout       = response-oknobye

    response-unauthenticate= response-oknobye
                             ;; "NO" response can only be returned when
                             ;; the command is issued in a wrong state
                             ;; or has a wrong number of parameters

    response-ok           = "OK" [SP "(" resp-code ")"]
                            [SP string] CRLF
                            ;; The string contains human-readable text
                            ;; encoded as UTF-8.

    response-nobye        = ("NO" / "BYE") [SP "(" resp-code ")"]
                            [SP string] CRLF
                            ;; The string contains human-readable text
                            ;; encoded as UTF-8.

    response-oknobye      = response-ok / response-nobye

    response-noop         = response-ok

    response-putscript    = response-oknobye

    response-checkscript  = response-oknobye

    response-renamescript = response-oknobye

    response-setactive    = response-oknobye

    response-starttls     = (response-ok response-capability) /
                            response-nobye

    sieve-name            = string
                            ;; See Section 1.6 for the full list of
                            ;; prohibited characters.
                            ;; Empty string is not allowed.

    active-sieve-name     = string
                            ;; See Section 1.6 for the full list of
                            ;; prohibited characters.
                            ;; This is similar to <sieve-name>, but
                            ;; empty string is allowed and has a special
                            ;; meaning.

    string                = quoted / literal-c2s / literal-s2c
                            ;; literal-c2s is only allowed when sent
                            ;; from the client to the server.
                            ;; literal-s2c is only allowed when sent
                            ;; from the server to the client.
                            ;; quoted is allowed in either direction.

5. Security Considerations ๐Ÿ”

Okay, security time, and I need you to take this seriously bestie ๐Ÿ’…. The AUTHENTICATE command uses SASL [SASL] to handle authentication and authorization services. Integrity and privacy can be provided by [SASL] and/or [TLS]. And if you use a SASL mechanism, the security considerations for that mechanism apply too.

This protocol's transactions are vulnerable to passive observers and man-in-the-middle attacks that alter the data ๐Ÿ˜ญ. That's the case unless the optional encryption and integrity services of SASL (through the AUTHENTICATE command) and/or [TLS] (through the STARTTLS command) are turned on, or an external security mechanism is used for protection. It may be useful to let both clients and servers be configured to refuse to transfer sensitive information when there's no strong encryption ๐Ÿ›ก๏ธ.

If an implementation supports SASL mechanisms that are vulnerable to passive eavesdropping attacks (such as [PLAIN]), then the implementation MUST support at least one configuration where these SASL mechanisms are not advertised or used without the presence of an external security layer such as [TLS]. No exceptions, no cap ๐Ÿšซ.

Some response codes returned on a failed AUTHENTICATE command may disclose whether or not the username is valid (for example, TRANSITION-NEEDED). So server implementations SHOULD provide the ability to disable these features, or to make them not conditional on a per-user basis, for sites that are concerned about that disclosure. For ENCRYPT-NEEDED, if it is applied to all identities then no extra information is disclosed. But if it is applied on a per-user basis, it can disclose information.

A compromised or malicious server can use the TRANSITION-NEEDED response code to trick a client that is configured to use a mechanism which does not disclose the user's password to the server (for example, Kerberos) into sending the bare password to the server ๐Ÿ’€. Clients SHOULD have the ability to disable the password transition feature. Otherwise, they should disclose that risk to the user and offer the user an option for how to proceed. Wild, I know ๐Ÿ™ˆ.

6. IANA Considerations ๐ŸŒธ

IANA has reserved TCP port number 4190 for use with the ManageSieve protocol described in this document ๐ŸŽ€.

IANA has registered the "sieve" URI scheme defined in Section 3 of this document ๐Ÿฆ‹.

IANA has registered "sieve" in the "GSSAPI/Kerberos/SASL Service Names" registry.

IANA has created a new registry for ManageSieve capabilities. The registration template for ManageSieve capabilities is specified in Section 6.1. ManageSieve protocol capabilities MUST be specified in a Standards-Track or IESG-approved Experimental RFC. The vibe is very strict, and it's iconic โœจ.

IANA has created a new registry for ManageSieve response codes. The registration template for ManageSieve response codes is specified in Section 6.3. ManageSieve protocol response codes MUST be specified in a Standards-Track or IESG-approved Experimental RFC ๐Ÿ‘‘.

6.1. ManageSieve Capability Registration Template ๐Ÿงš

Here's the template you fill in when you want to register a new capability, periodt ๐Ÿ’œ.

   To: iana@iana.org
   Subject: ManageSieve Capability Registration

   Please register the following ManageSieve capability:

   Capability name:
   Description:
   Relevant publications:
   Person & email address to contact for further information:
   Author/Change controller:

6.2. Registration of Initial ManageSieve Capabilities ๐Ÿ“

These are the first capabilities that get registered, and honestly the whole set is giving main character energy ๐ŸŒˆ.

   To: iana@iana.org
   Subject: ManageSieve Capability Registration

   Please register the following ManageSieve capabilities:

   Capability name:  IMPLEMENTATION
   Description:   Its value contains the name of the server
                  implementation and its version.
   Relevant publications:  this RFC, Section 1.7.
   Person & email address to contact for further information:
                  Alexey Melnikov <alexey.melnikov@isode.com>
   Author/Change controller:  IESG.

   Capability name:  SASL
   Description:   Its value contains a space-separated list of SASL
                  mechanisms supported by the server.
   Relevant publications:  this RFC, Sections 1.7 and 2.1.
   Person & email address to contact for further information:
                  Alexey Melnikov <alexey.melnikov@isode.com>
   Author/Change controller:  IESG.

   Capability name:  SIEVE
   Description:   Its value contains a space-separated list of supported
                  SIEVE extensions.
   Relevant publications:  this RFC, Section 1.7.  Also [SIEVE].
   Person & email address to contact for further information:
                  Alexey Melnikov <alexey.melnikov@isode.com>
   Author/Change controller:  IESG.

   Capability name:  STARTTLS
   Description:   This capability is returned if the server supports TLS
                  (STARTTLS command).
   Relevant publications:  this RFC, Sections 1.7 and 2.2.
   Person & email address to contact for further information:
                  Alexey Melnikov <alexey.melnikov@isode.com>
   Author/Change controller:  IESG.

   Capability name:  NOTIFY
   Description:   This capability is returned if the server supports the
                  'enotify' [NOTIFY] Sieve extension.
   Relevant publications:  this RFC, Section 1.7.
   Person & email address to contact for further information:
                  Alexey Melnikov <alexey.melnikov@isode.com>
   Author/Change controller:  IESG.

   Capability name:  MAXREDIRECTS
   Description:   This capability returns the limit on the number of
                  Sieve "redirect" actions a script can perform during a
                  single evaluation.  The value is a non-negative number
                  represented as a ManageSieve string.
   Relevant publications:  this RFC, Section 1.7.
   Person & email address to contact for further information:
                  Alexey Melnikov <alexey.melnikov@isode.com>
   Author/Change controller:  IESG.

   Capability name:  LANGUAGE
   Description:   The language (<Language-Tag> from [RFC5646]) currently
                  used for human-readable error messages.
   Relevant publications:  this RFC, Section 1.7.
   Person & email address to contact for further information:
                  Alexey Melnikov <alexey.melnikov@isode.com>
   Author/Change controller:  IESG.

   Capability name:  OWNER
   Description:   Its value contains the UTF-8-encoded name of the
                  currently logged-in user ("authorization identity"
                  according to RFC 4422).
   Relevant publications:  this RFC, Section 1.7.
   Person & email address to contact for further information:
                  Alexey Melnikov <alexey.melnikov@isode.com>
   Author/Change controller:  IESG.

   Capability name:  VERSION
   Description:   This capability is returned if the server is compliant
                  with RFC 5804; i.e., that it supports RENAMESCRIPT,
                  CHECKSCRIPT, and NOOP commands.
   Relevant publications:  this RFC, Sections 2.11, 2.12, and 2.13.
   Person & email address to contact for further information:
                  Alexey Melnikov <alexey.melnikov@isode.com>
   Author/Change controller:  IESG.

6.3. ManageSieve Response Code Registration Template โœจ

Okay bestie, this is the blank form IANA uses when someone wants to add a new ManageSieve response code ๐Ÿ“๐Ÿ’… It's just a template with spaces to fill in, so nothing to panic about ๐Ÿซถ

To: iana@iana.org
Subject: ManageSieve Response Code Registration

Please register the following ManageSieve response code:

   Response Code:
   Arguments (use ABNF to specify syntax, or the word NONE if none
   can be specified):
   Purpose:
   Published Specification(s):
   Person & email address to contact for further information:
   Author/Change controller:

6.4. Registration of Initial ManageSieve Response Codes ๐ŸŽ€

Now the fun part ๐Ÿฆ‹ This is the first batch of ManageSieve response codes getting registered with IANA, and every one of them is credited to [RFC5804] with Alexey Melnikov as the contact and IESG as the change controller ๐Ÿ‘‘ Let's go through them one by one ๐Ÿ’–

Okay so first up is AUTH-TOO-WEAK ๐Ÿ”’ It shows up in the NO response to an AUTHENTICATE command, and it means the site's security policy won't let you use that mechanism for that identity ๐Ÿ™ˆ

To: iana@iana.org
Subject: ManageSieve Response Code Registration

Please register the following ManageSieve response codes:

Response Code: AUTH-TOO-WEAK
Arguments (use ABNF to specify syntax, or the word NONE if none can
be specified):  NONE
Purpose:       This response code is returned in the NO response from
               an AUTHENTICATE command.  It indicates that site
               security policy forbids the use of the requested
               mechanism for the specified authentication identity.
Published Specification(s):  [RFC5804]
Person & email address to contact for further information:
               Alexey Melnikov <alexey.melnikov@isode.com>
Author/Change controller:  IESG.

Next is ENCRYPT-NEEDED ๐Ÿ” This one is also in the NO response to AUTHENTICATE, and it says site policy wants a strong encryption mechanism for that identity and mechanism combo ๐ŸŒธ

Response Code: ENCRYPT-NEEDED
Arguments (use ABNF to specify syntax, or the word NONE if none can
be specified):  NONE
Purpose:       This response code is returned in the NO response from
               an AUTHENTICATE command.  It indicates that site
               security policy requires the use of a strong
               encryption mechanism for the specified authentication
               identity and mechanism.
Published Specification(s):  [RFC5804]
Person & email address to contact for further information:
               Alexey Melnikov <alexey.melnikov@isode.com>
Author/Change controller:  IESG.

Now QUOTA ๐Ÿ“ฆ This is the main quota one, and it's kinda the parent of the next two. In a NO/BYE response it means the command would've pushed the user over the site-defined quota limits ๐Ÿ˜ญ In an OK response it can mean the user is close to their quota or already went over it, but only if the server supports soft quotas โœจ

Response Code: QUOTA
Arguments (use ABNF to specify syntax, or the word NONE if none can
be specified):  NONE
Purpose:       If this response code is returned in the NO/BYE
               response, it means that the command would have placed
               the user above the site-defined quota constraints.  If
               this response code is returned in the OK response, it
               can mean that the user is near its quota or that the
               user exceeded its quota, but the server supports soft
               quotas.
Published Specification(s):  [RFC5804]
Person & email address to contact for further information:
               Alexey Melnikov <alexey.melnikov@isode.com>
Author/Change controller:  IESG.

Then there's QUOTA/MAXSCRIPTS ๐Ÿงš This is the more specific version of QUOTA, and it's all about the number of Sieve scripts. Same deal with NO/BYE versus OK, just aimed at the script count ๐Ÿ“œ

Response Code: QUOTA/MAXSCRIPTS
Arguments (use ABNF to specify syntax, or the word NONE if none can
be specified):  NONE
Purpose:       If this response code is returned in the NO/BYE
               response, it means that the command would have placed
               the user above the site-defined limit on the number of
               Sieve scripts.  If this response code is returned in
               the OK response, it can mean that the user is near its
               quota or that the user exceeded its quota, but the
               server supports soft quotas.  This response code is a
               more specific version of the QUOTA response code.
Published Specification(s):  [RFC5804]
Person & email address to contact for further information:
               Alexey Melnikov <alexey.melnikov@isode.com>
Author/Change controller:  IESG.

QUOTA/MAXSIZE is the size-focused sibling ๐Ÿ’œ It says the command would've put the user over the site-defined maximum script size in a NO/BYE response, and the OK version works the same soft-quota way. It's also a more specific version of QUOTA ๐Ÿซง

Response Code: QUOTA/MAXSIZE
Arguments (use ABNF to specify syntax, or the word NONE if none can
be specified):  NONE
Purpose:       If this response code is returned in the NO/BYE
               response, it means that the command would have placed
               the user above the site-defined maximum script size.
               If this response code is returned in the OK response,
               it can mean that the user is near its quota or that
               the user exceeded its quota, but the server supports
               soft quotas.  This response code is a more specific
               version of the QUOTA response code.
Published Specification(s):  [RFC5804]
Person & email address to contact for further information:
               Alexey Melnikov <alexey.melnikov@isode.com>
Author/Change controller:  IESG.

Okay now REFERRAL ๐Ÿ—บ๏ธ This one is a whole vibe. It can come with a BYE result from any command, and it has a required parameter that tells you which server to go to for this user's Sieve scripts. That server is given as a Sieve URL (check out Section 3 for that) โœจ The scriptname part of the URL MUST NOT be specified, and the client should authenticate to the referred server and use it for everything else in the session ๐Ÿฆ‹

Response Code: REFERRAL
Arguments (use ABNF to specify syntax, or the word NONE if none can
be specified):  <sieveurl>
Purpose:       This response code may be returned with a BYE result
               from any command, and includes a mandatory parameter
               that indicates what server to access to manage this
               user's Sieve scripts.  The server will be specified by
               a Sieve URL (see Section 3).  The scriptname portion
               of the URL MUST NOT be specified.  The client should
               authenticate to the specified server and use it for
               all further commands in the current session.
Published Specification(s):  [RFC5804]
Person & email address to contact for further information:
               Alexey Melnikov <alexey.melnikov@isode.com>
Author/Change controller:  IESG.

Next is SASL ๐ŸŒˆ It can show up in the OK response to a successful AUTHENTICATE command, and it carries the optional final server response data, as defined by [SASL] ๐Ÿซถ

Response Code: SASL
Arguments (use ABNF to specify syntax, or the word NONE if none can
be specified):  <string>
Purpose:       This response code can occur in the OK response to a
               successful AUTHENTICATE command and includes the
               optional final server response data from the server as
               specified by [SASL].
Published Specification(s):  [RFC5804]
Person & email address to contact for further information:
               Alexey Melnikov <alexey.melnikov@isode.com>
Author/Change controller:  IESG.

TRANSITION-NEEDED ๐Ÿ”„ This one is kinda plot-twisty. It shows up in a NO response to AUTHENTICATE, and it means the username is valid but the authentication database entry needs an update before that mechanism works. The usual fix is to set up a secure channel with TLS, then authenticate once with the [PLAIN] mechanism. After that, the selected mechanism SHOULD then work for later sessions ๐Ÿ’…

Response Code: TRANSITION-NEEDED
Arguments (use ABNF to specify syntax, or the word NONE if none can
be specified):  NONE
Purpose:       This response code occurs in a NO response of an
               AUTHENTICATE command.  It indicates that the user name
               is valid, but the entry in the authentication database
               needs to be updated in order to permit authentication
               with the specified mechanism.  This is typically done
               by establishing a secure channel using TLS, followed
               by authenticating once using the [PLAIN]
               authentication mechanism.  The selected mechanism
               SHOULD then work for authentications in subsequent
               sessions.
Published Specification(s):  [RFC5804]
Person & email address to contact for further information:
               Alexey Melnikov <alexey.melnikov@isode.com>
Author/Change controller:  IESG.

TRYLATER โฐ This is for a temporary server failure. The client MAY continue using local information and try the command later. It only makes sense in a NO/BYE response ๐Ÿฅบ

Response Code: TRYLATER
Arguments (use ABNF to specify syntax, or the word NONE if none can
be specified):  NONE
Purpose:       A command failed due to a temporary server failure.
               The client MAY continue using local information and
               try the command later.  This response code only make
               sense when returned in a NO/BYE response.
Published Specification(s):  [RFC5804]
Person & email address to contact for further information:
               Alexey Melnikov <alexey.melnikov@isode.com>
Author/Change controller:  IESG.

ACTIVE ๐ŸŽฏ A command failed because it isn't allowed on the active script. The example they give is DELETESCRIPT on the active script ๐Ÿ™…โ€โ™€๏ธ It only makes sense in a NO/BYE response ๐Ÿ’€

Response Code: ACTIVE
Arguments (use ABNF to specify syntax, or the word NONE if none can
be specified):  NONE
Purpose:       A command failed because it is not allowed on the
               active script, for example, DELETESCRIPT on the active
               script.  This response code only makes sense when
               returned in a NO/BYE response.
Published Specification(s):  [RFC5804]
Person & email address to contact for further information:
               Alexey Melnikov <alexey.melnikov@isode.com>
Author/Change controller:  IESG.

NONEXISTENT ๐Ÿ‘ป This one's pretty self-explanatory: the command failed because the referenced script name doesn't exist. Also only makes sense in a NO/BYE response ๐Ÿซ 

Response Code: NONEXISTENT
Arguments (use ABNF to specify syntax, or the word NONE if none can
be specified):  NONE
Purpose:       A command failed because the referenced script name
               doesn't exist.  This response code only makes sense
               when returned in a NO/BYE response.
Published Specification(s):  [RFC5804]
Person & email address to contact for further information:
               Alexey Melnikov <alexey.melnikov@isode.com>
Author/Change controller:  IESG.

ALREADYEXISTS ๐Ÿ‘ฏ The mirror of NONEXISTENT. The command failed because the referenced script name already exists, and it's also only meaningful in a NO/BYE response ๐Ÿ’œ

Response Code: ALREADYEXISTS
Arguments (use ABNF to specify syntax, or the word NONE if none can
be specified):  NONE
Purpose:       A command failed because the referenced script name
               already exists.  This response code only makes sense
               when returned in a NO/BYE response.
Published Specification(s):  [RFC5804]
Person & email address to contact for further information:
               Alexey Melnikov <alexey.melnikov@isode.com>
Author/Change controller:  IESG.

WARNINGS โš ๏ธ This is a soft heads-up. The server MAY return it in the OK response (though it might come back with NO/BYE too). It tells the client that even though the script is syntactically valid, it might contain errors the script writer didn't mean to include ๐Ÿ™ˆ

Response Code: WARNINGS
Arguments (use ABNF to specify syntax, or the word NONE if none can
be specified):  NONE
Purpose:       This response code MAY be returned by the server in
               the OK response (but it might be returned with the NO/
               BYE response as well) and signals the client that even
               though the script is syntactically valid, it might
               contain errors not intended by the script writer.
Published Specification(s):  [RFC5804]
Person & email address to contact for further information:
               Alexey Melnikov <alexey.melnikov@isode.com>
Author/Change controller:  IESG.

And last but not least, TAG ๐Ÿท๏ธ This one's arguments are a string, and that string is whatever was specified in the command that caused this response. It's typically used for client state synchronization, so it's basically the server saying "yep, I'm talking about this exact thing" ๐Ÿงšโœจ

Response Code: TAG
Arguments (use ABNF to specify syntax, or the word NONE if none can
be specified):  string
Purpose:       This response code name is followed by a string
               specified in the command that caused this response.
               It is typically used for client state synchronization.
Published Specification(s):  [RFC5804]
Person & email address to contact for further information:
               Alexey Melnikov <alexey.melnikov@isode.com>
Author/Change controller:  IESG.

7. Internationalization Considerations โœจ

okay so the LANGUAGE capability (see Section 1.7) lets a client find out which language the server uses for the human-readable text at the end of any OK/NO/BYE response ๐ŸŒ bestie, that's the whole point of it ๐Ÿ’…

Human-readable text in OK responses usually doesn't need to be shown to the user ๐Ÿ™ˆ The exception is when it comes back with a PUTSCRIPT or CHECKSCRIPT command that also has the WARNINGS response code (Section 1.3). Then it's worth showing. Human-readable text from NO/BYE responses is meant to be shown to the user, unless the client can handle the failure of the command that caused it automatically. Clients SHOULD use response codes (Section 1.3) for automatic error handling ๐Ÿค– โœจ Response codes MAY also be used by the client to show error messages in a language the user understands, for example, if the LANGUAGE capability doesn't return a language the user can read ๐Ÿซถ

Now, the human-readable text from OK (WARNINGS) or NO/BYE responses for PUTSCRIPT/CHECKSCRIPT commands is meant for advanced users who understand the Sieve language ๐Ÿง  These users are usually sophisticated enough to handle whatever language the server is using, even if it isn't their favourite, and they'll want to see the error/warning text no matter what language the server puts it in ๐Ÿ’œ

A client that generates Sieve script automatically ๐Ÿงš for example, if the script is made without user intervention, or from a UI that shows an abstract list of conditions and actions, SHOULD NOT show warning/error messages to the user ๐Ÿ™ˆ Honestly, the user might not even know the client is using Sieve underneath, and that's totally fine. But if the client has a debugging mode, those warnings/errors SHOULD be available in it ๐Ÿ”ฅ

Heads up: this document doesn't give you a way to change the language that's currently in use ๐ŸŒธ A future extension is expected to take care of that.

8. Acknowledgements ๐ŸŽ€

Thanks to Simon Josefsson, Larry Greenfield, Allen Johnson, Chris Newman, Lyndon Nerenberg, Tim Showalter, Sarah Robeson, Walter Wong, Barry Leiba, Arnt Gulbrandsen, Stephan Bosch, Ken Murchison, Phil Pennock, Ned Freed, Jeffrey Hutzelman, Mark E. Mallett, Dilyan Palauzov, Dave Cridland, Aaron Stone, Robert Burrell Donkin, Patrick Ben Koetter, Bjoern Hoehrmann, Martin Duerst, Pasi Eronen, Magnus Westerlund, Tim Polk, and Julien Coloos for helping with this document ๐Ÿซถ A super special thank you to Phil Pennock, who wrote the text for the NOOP command AND hunted down various bugs in the document ๐Ÿ˜ญ๐Ÿ‘‘


9. References ๐Ÿ“š

9.1. Normative References

[ABNF]         Crocker, D. and P. Overell, "Augmented BNF for Syntax
               Specifications: ABNF", STD 68, RFC 5234, January 2008.

[ACAP]         Newman, C. and J. Myers, "ACAP -- Application
               Configuration Access Protocol", RFC 2244, November
               1997.

[BASE64]       Josefsson, S., "The Base16, Base32, and Base64 Data
               Encodings", RFC 4648, October 2006.

[DNS-SRV]      Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR
               for specifying the location of services (DNS SRV)",
               RFC 2782, February 2000.

[KEYWORDS]     Bradner, S., "Key words for use in RFCs to Indicate
               Requirement Levels", BCP 14, RFC 2119, March 1997.

[NET-UNICODE]  Klensin, J. and M. Padlipsky, "Unicode Format for
               Network Interchange", RFC 5198, March 2008.

[NOTIFY]       Melnikov, A., Leiba, B., Segmuller, W., and T. Martin,
               "Sieve Email Filtering: Extension for Notifications",
               RFC 5435, January 2009.

[RFC2277]      Alvestrand, H., "IETF Policy on Character Sets and
               Languages", BCP 18, RFC 2277, January 1998.

[RFC2460]      Deering, S. and R. Hinden, "Internet Protocol, Version
               6 (IPv6) Specification", RFC 2460, December 1998.

[RFC3490]      Faltstrom, P., Hoffman, P., and A. Costello,
               "Internationalizing Domain Names in Applications
               (IDNA)", RFC 3490, March 2003.

[RFC4519]      Sciberras, A., "Lightweight Directory Access Protocol
               (LDAP): Schema for User Applications", RFC 4519, June
               2006.

[RFC5646]      Phillips, A. and M. Davis, "Tags for Identifying
               Languages", BCP 47, RFC 5646, September 2009.

[RFC791]       Postel, J., "Internet Protocol", STD 5, RFC 791,
               September 1981.

[SASL]         Melnikov, A. and K. Zeilenga, "Simple Authentication
               and Security Layer (SASL)", RFC 4422, June 2006.

[SASLprep]     Zeilenga, K., "SASLprep: Stringprep Profile for User
               Names and Passwords", RFC 4013, February 2005.

[SCRAM]        Menon-Sen, A., Melnikov, A., Newman, C., and N.
               Williams, "Salted Challenge Response Authentication
               Mechanism (SCRAM) SASL and GSS-API Mechanisms", RFC
               5802, July 2010.

[SIEVE]        Guenther, P. and T. Showalter, "Sieve: An Email
               Filtering Language", RFC 5228, January 2008.

[StringPrep]   Hoffman, P. and M. Blanchet, "Preparation of
               Internationalized Strings ("stringprep")", RFC 3454,
               December 2002.

[TLS]          Dierks, T. and E. Rescorla, "The Transport Layer
               Security (TLS) Protocol Version 1.2", RFC 5246, August
               2008.

[URI-GEN]      Berners-Lee, T., Fielding, R., and L. Masinter,
               "Uniform Resource Identifier (URI): Generic Syntax",
               STD 66, RFC 3986, January 2005.

[UTF-8]        Yergeau, F., "UTF-8, a transformation format of ISO
               10646", STD 63, RFC 3629, November 2003.

[X509]         Cooper, D., Santesson, S., Farrell, S., Boeyen, S.,
               Housley, R., and W. Polk, "Internet X.509 Public Key
               Infrastructure Certificate and Certificate Revocation
               List (CRL) Profile", RFC 5280, May 2008.

[X509-SRV]     Santesson, S., "Internet X.509 Public Key
               Infrastructure Subject Alternative Name for Expression
               of Service Name", RFC 4985, August 2007.

9.2. Informative References

[DIGEST-MD5]   Leach, P. and C. Newman, "Using Digest Authentication
               as a SASL Mechanism", RFC 2831, May 2000.

[GSSAPI]       Melnikov, A., "The Kerberos V5 ("GSSAPI") Simple
               Authentication and Security Layer (SASL) Mechanism",
               RFC 4752, November 2006.

[I-HAVE]       Freed, N., "Sieve Email Filtering: Ihave Extension",
               RFC 5463, March 2009.

[IMAP]         Crispin, M., "INTERNET MESSAGE ACCESS PROTOCOL -
               VERSION 4rev1", RFC 3501, March 2003.

[LDAP]         Zeilenga, K., "Lightweight Directory Access Protocol
               (LDAP): Technical Specification Road Map", RFC 4510,
               June 2006.

[PLAIN]        Zeilenga, K., "The PLAIN Simple Authentication and
               Security Layer (SASL) Mechanism", RFC 4616, August
               2006.

Authors' Addresses ๐Ÿ’Œ

Alexey Melnikov (editor)
Isode Limited
5 Castle Business Village
36 Station Road
Hampton, Middlesex  TW12 2BX
UK

EMail: Alexey.Melnikov@isode.com


Tim Martin
BeThereBeSquare, Inc.
672 Haight st.
San Francisco, CA  94117
USA

Phone: +1 510 260-4175
EMail: timmartin@alumni.cmu.edu

That's the whole spec, bestie! ๐ŸŒˆโœจ RFC 5804 is officially rewritten, and you made it to the very end ๐Ÿฆ‹๐Ÿ’–

๐Ÿ“ฆ where this page comes from