<?xml version='1.0' encoding='utf-8'?> encoding='UTF-8'?>

<!-- draft submitted in xml v3 -->

<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" category="std" docName="draft-ietf-jmap-sieve-22" number="9661" obsoletes="" updates="" submissionType="IETF" consensus="true" xml:lang="en" tocInclude="true" symRefs="true" sortRefs="true" version="3">

  <!-- xml2rfc v2v3 conversion 3.10.0 -->

  <front>
    <title abbrev="JMAP Sieve">JMAP Sieve">The JSON Meta Application Protocol (JMAP) for Sieve Scripts</title>
    <seriesInfo name="Internet-Draft" value="draft-ietf-jmap-sieve-22"/> name="RFC" value="9661"/>
    <author initials="K." surname="Murchison" fullname="Kenneth Murchison">
      <organization abbrev="Fastmail">Fastmail US LLC</organization>
      <address>
        <postal>
          <street>1429 Walnut Street - Street, Suite 1201</street>
          <city>Philadelphia</city>
          <region>PA</region>
          <code>19102</code>
          <country>USA</country>
          <country>United States of America</country>
        </postal>
        <email>murch@fastmailteam.com</email>
      </address>
    </author>
    <date/>
    <date month="September" year="2024"/>

    <area>ART</area>
    <!-- <workgroup>Independent Submission</workgroup>-->
    <workgroup>JMAP</workgroup>
    <workgroup>jmap</workgroup>

    <keyword>JMAP</keyword>
    <keyword>JSON</keyword>
    <keyword>Sieve</keyword>
    <abstract>
      <t>This document specifies a data model for managing Sieve
      scripts on a server using the JSON Meta Application Protocol
      (JMAP).
      Clients can use this protocol to efficiently search, access,
      organize, and validate Sieve scripts.
      </t>
    </abstract>
<!--
    <note title="Open Issues">
      <ul spacing="normal">
        <li>
        </li>
      </ul>
    </note>
-->
  </front>

  <middle>
    <section numbered="true" toc="default">
      <name>Introduction</name>
      <t><xref target="RFC8620">JMAP</xref>
      (JSON target="RFC8620">The JSON Meta Application Protocol) Protocol (JMAP)</xref>
      is a generic protocol for
      synchronizing data, such as mail, calendars calendars, or contacts, between
      a client and a server.

      It is optimized for mobile and web environments, and it aims to
      provide a consistent interface to different data types.
      </t>

      <t>This specification defines a data model for managing
      <xref target="RFC5228">Sieve</xref> scripts target="RFC5228">Sieve scripts</xref> on
      a server using JMAP.

      The data model is designed to allow a server to provide
      consistent access to the same scripts via
      <xref target="RFC5804">ManageSieve</xref> as well as JMAP.
      </t>

      <section numbered="true" toc="default">
        <name>Notational Conventions</name>
        <t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL",
        "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT
        RECOMMENDED", "MAY", "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>",
        "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>",
        "<bcp14>SHALL NOT</bcp14>", "<bcp14>SHOULD</bcp14>",
        "<bcp14>SHOULD NOT</bcp14>",
        "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
        "<bcp14>MAY</bcp14>", and "OPTIONAL" "<bcp14>OPTIONAL</bcp14>" in this document
        are to be interpreted as described in BCP 14 BCP&nbsp;14
        <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only
        when, they appear in all capitals, as shown here.
        </t> here.</t>
        <t>Type signatures, examples, and property descriptions in
        this document follow the conventions established in
        <xref target="RFC8620" section="1.1"/>.
        This document also uses data types and terminology established
        in Sections
        <xref Sections&nbsp;<xref target="RFC8620" section="1.2"
              sectionFormat="bare"/>-<xref
              sectionFormat="bare"/> through <xref target="RFC8620"
              section="1.6" sectionFormat="bare"/> of
        <xref target="RFC8620"/>.</t>

        <t>The term SieveScript "SieveScript" (with this specific capitalization) is
        used to refer to the data type defined in this document <xref target="object"/>
        and instances of those this data types. type used throughout this document.
        Servers MUST <bcp14>MUST</bcp14> support all properties specified for the
        data type defined in this document.</t>

        <t>For brevity, JMAP API examples
        (see <xref target="RFC8620" section="3"/>)
        examples
        only show the "methodCalls" property of the Request
        object, "Request"
        object and the "methodResponses" property of the Response "Response"
        object.
        All other examples are shown using the
        <xref target="RFC9112">HTTP 1.1</xref> protocol.</t> target="RFC9112">HTTP/1.1 protocol</xref>.</t>
      </section>

      <section numbered="true" toc="default">
        <name>Addition to the Capabilities Object</name>
        <t>The capabilities "capabilities" object is returned as part of the JMAP
        Session object;
        see <xref target="RFC8620" section="2" sectionFormat="comma"/>.
        This document defines one additional capability URI.
        </t>

        <section anchor="capa" numbered="true" toc="default">
          <name>urn:ietf:params:jmap:sieve</name>
          <t>The urn:ietf:params:jmap:sieve URI represents support for
          the SieveScript data type and associated API methods.
          The value of this property in the JMAP Session
          capabilities
          "capabilities" property is an object that MUST <bcp14>MUST</bcp14> contain
          the following information on server capabilities:
          </t>

          <ul

          <dl spacing="normal">
            <li>
              <t><strong>implementation</strong>:
              <dt><strong>implementation</strong>:</dt><dd><t>
                <tt>String</tt>
              </t>
              <t>
                The name and version of the Sieve implementation.
              </t>
              <t/>
            </li>
          </ul>
            </dd>
          </dl>

          <t>The value of this property in an account's
          accountCapabilities
          "accountCapabilities" property is an object that MUST <bcp14>MUST</bcp14> contain
          the following information on per-account server capabilities:
          </t>

          <ul

          <dl spacing="normal">
            <li>
              <t><strong>maxSizeScriptName</strong>:
                <tt>UnsignedInt</tt>
              <dt><strong>maxSizeScriptName</strong>:</dt>
                <dd><t><tt>UnsignedInt</tt>
              </t>
              <t>
                The maximum length, in octets, allowed for the
                name of a SieveScript.
                For compatibility with ManageSieve, this MUST <bcp14>MUST</bcp14> be at
                least 512 (up to 128 Unicode characters).
              </t>
              <t/>
            </li>
            <li>
              <t><strong>maxSizeScript</strong>:
                <tt>UnsignedInt|null</tt>
              </t></dd>

              <dt><strong>maxSizeScript</strong>:</dt><dd>
                <t><tt>UnsignedInt|null</tt>
              </t>
              <t>
                The maximum size (in octets) of a Sieve script the
                server is willing to store for the user,
                or <tt>null</tt> for no limit.
              </t>
              <t/>
            </li>
            <li>
              <t><strong>maxNumberScripts</strong>:
                <tt>UnsignedInt|null</tt>
            </dd>
              <dt><strong>maxNumberScripts</strong>:</dt>
                <dd><t><tt>UnsignedInt|null</tt>
              </t>
              <t>
                The maximum number of Sieve scripts the server is
                willing to store for the user,
                or <tt>null</tt> for no limit.
              </t>
              <t/>
            </li>
            <li>
              <t><strong>maxNumberRedirects</strong>:
                <tt>UnsignedInt|null</tt>
            </dd>
              <dt><strong>maxNumberRedirects</strong>:</dt>
                <dd><t><tt>UnsignedInt|null</tt>
              </t>
              <t>
                The maximum number of Sieve "redirect" actions a
                script can perform during a single evaluation evaluation,
                or <tt>null</tt> for no limit.
                Note that this is different from the total number of
                "redirect" actions a script can contain.
              </t>
              <t/>
            </li>
            <li>
              <t><strong>sieveExtensions</strong>:
                <tt>String[]</tt>
            </dd>

              <dt><strong>sieveExtensions</strong>:</dt>
                <dd><t><tt>String[]</tt>
              </t>
              <t>
                A list of case-sensitive Sieve capability strings (as
                listed in the Sieve "require" action; see
                <xref target="RFC5228" section="3.2" sectionFormat="comma"/>)
                indicating the extensions supported by the Sieve engine.
              </t>
              <t/>
            </li>
            <li>
              <t><strong>notificationMethods</strong>:
                <tt>String[]|null</tt>
              </t></dd>
              <dt><strong>notificationMethods</strong>:</dt>
                <dd><t><tt>String[]|null</tt>
              </t>
              <t>
                A list of
                <xref target="RFC3986">URI schema scheme parts</xref>
                for notification methods supported by the Sieve
                <xref target="RFC5435">"enotify"</xref>
                extension, target="RFC5435">"enotify" extension</xref>,
                or <tt>null</tt> if the extension
                is not supported by the Sieve engine.
              </t>
              <t/>
            </li>
            <li>
              <t><strong>externalLists</strong>:
                <tt>String[]|null</tt>
            </dd>
              <dt><strong>externalLists</strong>:</dt>
                <dd><t><tt>String[]|null</tt>
              </t>
              <t>
                A list of
                <xref target="RFC3986">URI schema scheme parts</xref>
                for externally stored list types supported by the
                Sieve <xref target="RFC6134">"extlists"</xref>
                extension, target="RFC6134">"extlists" extension</xref>,
                or <tt>null</tt> if the extension
                is not supported by the Sieve engine.
              </t>
            </li>
          </ul>
            </dd>
	  </dl>
        </section>

        <section anchor="session" numbered="true" toc="default">
          <name>Example</name>
          <t keepWithNext="true">
            A
            This example JMAP Session object showing shows a user that has access to their
            own Sieve scripts with support for a few Sieve extensions:
          </t>
          <artwork
<sourcecode name="" type="" align="left" alt=""><![CDATA[ type="json"><![CDATA[
{
  "capabilities": {
    "urn:ietf:params:jmap:core": {
      ...
    },
    "urn:ietf:params:jmap:mail": {},
    "urn:ietf:params:jmap:quota": {},
    "urn:ietf:params:jmap:blob": {},
    "urn:ietf:params:jmap:sieve": {
      "implementation": "ACME Email Filtering"
    },
    "urn:ietf:params:jmap:vacationresponse": {},
    ...
  },
  "accounts": {
    "ken": {
      "name": "ken@example.com",
      "isPersonal": true,
      "isReadOnly": false,
      "accountCapabilities": {
        "urn:ietf:params:jmap:core": {},
        "urn:ietf:params:jmap:quota": {},
        "urn:ietf:params:jmap:mail": {
          ...
        },
        "urn:ietf:params:jmap:blob": {
          "supportedTypeNames": [
            "Email"
            "SieveScript",
            ...
          ],
          ...
        },
        "urn:ietf:params:jmap:sieve": {
          "maxSizeScriptName": 512,
          "maxSizeScript": 65536,
          "maxNumberScripts": 5,
          "maxNumberRedirects": null,
          "sieveExtensions": [
            "fileinto",
            "imap4flags",
            "enotify",
            ...
          ],
          "notificationMethods": [
            "mailto"
          ],
          "externalLists": null,
        },
        "urn:ietf:params:jmap:vacationresponse": {},
        ...
      },
      ...
    }
  },
  "primaryAccounts": {
    "urn:ietf:params:jmap:mail": "ken",
    "urn:ietf:params:jmap:sieve": "ken",
    "urn:ietf:params:jmap:vacationresponse": "ken",
    ...
  },
  "username": "ken@example.com",
  "apiUrl": "/jmap/",
  "downloadUrl":
    "/jmap/download/{accountId}/{blobId}/{name}?accept={type}",
  "uploadUrl": "/jmap/upload/{accountId}/",
  ...
}
]]></artwork>
]]></sourcecode>
        </section>
      </section>
    </section>

    <section anchor="object" numbered="true" toc="default">
      <name>Sieve Scripts</name>
      <t>A <strong>SieveScript</strong> "SieveScript" object represents
      a single <xref target="RFC5228">Sieve</xref> script target="RFC5228">Sieve script</xref> for
      filtering email messages at the time of final delivery.
      </t>

      <section anchor="props" numbered="true" toc="default">
        <name>Sieve Script Properties</name>
        <t>A <strong>SieveScript</strong> "SieveScript" object has the
        following properties:

        </t>
        <ul
        <dl spacing="normal">
          <li>
            <t><strong>id</strong>:
            <tt>Id</tt>
            <dt><strong>id</strong>:</dt>
            <dd><t><tt>Id</tt>
            (immutable; server-set)
            </t>
            <t>
              The id of the script.
            </t>
            <t/>
          </li>
          <li>
            <t><strong>name</strong>:
            <tt>String|null</tt>
          </dd>
            <dt><strong>name</strong>:</dt>
            <dd><t><tt>String|null</tt>
            (optional; default is server-dependent) server dependent)
            </t>
            <t>
              User-visible name for the SieveScript.
              If non-null, this MUST <bcp14>MUST</bcp14> be a
              <xref target="RFC5198">Net-Unicode</xref>
              string target="RFC5198">Net-Unicode string</xref>
              of at least 1 character in length, subject to the
              maximum size given in the capability "capability" object.
            </t>
            <t>
              For compatibility with ManageSieve, servers MUST <bcp14>MUST</bcp14> reject
              names that contain any of the following Unicode characters:
              U+0000 - U+001F, U+007F - U+009F,
              U+0000-U+001F, U+007F-U+009F, U+2028, or U+2029.
            </t>
            <t>
              Servers MAY <bcp14>MAY</bcp14> reject names that violate server policy
              (e.g., names containing a slash (/)).
            </t>
            <t>
              The name MUST <bcp14>MUST</bcp14> be unique among all SieveScripts within an
              account.
            </t>
            <t/>
          </li>
          <li>
            <t><strong>blobId</strong>:
            <tt>Id</tt>
          </dd>
            <dt><strong>blobId</strong>:</dt>
            <dd><t><tt>Id</tt>
            </t>
            <t>
              The id of the blob containing the raw octets of the script.
            </t>
            <t/>
          </li>
          <li>
            <t><strong>isActive</strong>:
            <tt>Boolean</tt>
          </dd>
            <dt><strong>isActive</strong>:</dt>
            <dd><t><tt>Boolean</tt>
            (server-set; default: false)
            </t>
            <t>
              Indicator that the SieveScript is actively filtering
              incoming messages.
            </t>
            <t>
              A user may have at most one active script.
              The <xref target="set">SieveScript/set</xref> method target="set">SieveScript/set method</xref> is
              used for changing the active script or disabling Sieve
              processing.
            </t>
            <t/>
          </li>
        </ul>
          </dd>
        </dl>
      </section>

      <section anchor="content" numbered="true" toc="default">
        <name>Sieve Script Content</name>
        <t>A script MUST <bcp14>MUST</bcp14> be <xref target="RFC3629">UTF-8</xref>
          content target="RFC3629">UTF-8 content</xref>
          of at least 1 character in length, subject to the
          syntax of <xref target="RFC5228">Sieve</xref>.
          A script MUST NOT <bcp14>MUST NOT</bcp14> contain any "require" statement(s)
          mentioning Sieve capability strings not present in the
          <xref target="capa">capability</xref> object. target="capa">"capability" object</xref>.
          Note that if the Sieve <xref target="RFC5463">"ihave"</xref> target="RFC5463">"ihave" capability string </xref>
          is present in the capability "capability" object,
          the script MAY <bcp14>MAY</bcp14> mention unrecognized/unsupported extensions
          in the "ihave" test.
        </t>

        <t>Script content is treated as a binary blob and
          uploaded/downloaded via the mechanisms provided in
          <xref target="RFC8620"/> Sections
          <xref
          Sections&nbsp;<xref target="RFC8620" section="6.1"
                sectionFormat="bare"/>/<xref
                sectionFormat="bare"/> and <xref target="RFC8620"
                section="6.2" sectionFormat="bare"/>
          respectively of <xref target="RFC8620"/>,
          respectively, and/or via the JMAP Blob management methods provided in
          <xref target="RFC9404"/> Sections
          <xref
          Sections&nbsp;<xref target="RFC9404" section="4.1"
                sectionFormat="bare"/>/<xref
                sectionFormat="bare"/> and <xref target="RFC9404"
                section="4.2" sectionFormat="bare"/> of <xref target="RFC9404"/>,
          respectively.
        </t>

        <t>Downloading script content via the JMAP downloadUrl or the
          Blob/get method provides equivalent functionality equivalent to that of the
          GETSCRIPT command defined in <xref target="RFC5804"/>.
        </t>
      </section>

      <section anchor="get" numbered="true" toc="default">
        <name>SieveScript/get</name>
        <t>This is a standard "/get" method as described in
        <xref target="RFC8620" section="5.1" sectionFormat="comma"/>.
        The <em>ids</em> "ids" argument may be
        <tt>null</tt> to fetch all scripts at once.
        </t>
        <t>This method provides equivalent functionality equivalent to that of the
        LISTSCRIPTS command defined in <xref target="RFC5804"/>.
        </t>

        <section numbered="true" toc="default">
          <name>Examples</name>
          <t keepWithNext="true">
            List all scripts:
          </t>
          <artwork
<sourcecode name="" type="" align="left" alt=""><![CDATA[ type="json"><![CDATA[
[
  ["SieveScript/get", {
    "accountId": "ken"
  }, "0"]
]

[
  [
    "SieveScript/get",
    {
      "state": "1634915373.240633104-120",
      "list": [
        {
          "id": "2d647053-dded-418d-917a-63eda3ac8f7b",
          "name": "test1",
          "isActive": true,
          "blobId": "S7"
        }
      ],
      "notFound": [],
      "accountId": "ken"
    },
    "0"
  ]
]
]]></artwork>
]]></sourcecode>

          <t keepWithNext="true">
            Download the script content via
            the JMAP downloadUrl as advertised in the example in <xref target="session"/>:
          </t>
          <artwork
<sourcecode name="" type="" align="left" alt=""><![CDATA[ type="http-message"><![CDATA[
GET /jmap/download/ken/S7/test1.siv?accept=application/sieve HTTP/1.1
Host: jmap.example.com
Authorization: Basic a2VuOnBhc3N3b3Jk

HTTP/1.1 200 OK
Date: Fri, 22 Oct 2021 15:27:38 GMT
Content-Type: application/sieve; charset=utf-8
Content-Disposition: attachment; filename="test1.siv"
Content-Length: 49

require ["fileinto"];
fileinto "INBOX.target";
]]></artwork>
]]></sourcecode>

          <t keepWithNext="true">
            Fetch script properties
            and content in a single JMAP API request using the
            <xref target="RFC9404"> JMAP Blob management extension</xref>:
          </t>
          <artwork

<sourcecode name="" type="" align="left" alt=""><![CDATA[ type="json"><![CDATA[
[
  ["SieveScript/get", {
    "accountId": "ken",
    "ids": [ "2d647053-dded-418d-917a-63eda3ac8f7b" ]
  }, "0"],
  ["Blob/get", {
    "accountId": "ken",
    "#ids": {
      "resultOf": "0",
      "name": "SieveScript/get",
      "path": "/list/*/blobId"
    }
  }, "1"]
]

[
  [
    "SieveScript/get",
    {
      "state": "1634915373.240633104-120",
      "list": [
        {
          "id": "2d647053-dded-418d-917a-63eda3ac8f7b",
          "name": "test1",
          "isActive": true,
          "blobId": "S7"
        }
      ],
      "notFound": [],
      "accountId": "ken"
    },
    "0"
  ],
  [
    "Blob/get",
    {
      "list": [
        {
          "id": "S7",
          "data:asText":
     "require [\"fileinto\"];\\r\\nfileinto \"INBOX.target\";\\r\\n",
          "size": 49
        }
      ],
      "notFound": [],
      "accountId": "ken"
    },
    "1"
  ]
]
]]></artwork>
]]></sourcecode>
        </section>
      </section>
      <!-- /get -->

      <section anchor="set" numbered="true" toc="default">
        <name>SieveScript/set</name>
        <t>This is a standard "/set" method as described in
        <xref target="RFC8620" section="5.3" sectionFormat="comma"/> sectionFormat="comma"/>,
        but with the following additional optional request arguments:

        </t>
        <ul
        <dl spacing="normal">
          <li>
            <t><strong>onSuccessActivateScript</strong>:
            <tt>Id</tt>
            <dt><strong>onSuccessActivateScript</strong>:</dt>
            <dd><t><tt>Id</tt>
            </t>
            <t>
            The id of the SieveScript to activate if and
            only if all of the creations, modifications, and
            destructions (if any) succeed.
            (For references to SieveScript creations, this is
            equivalent to a creation-reference, so the id will be the
            creation id prefixed with a "#".)
            The currently active SieveScript (if any) will be deactivated
            before activating the specified SieveScript.
            </t>

            <t>
            If omitted, or if the id is either invalid or nonexistent, it MUST <bcp14>MUST</bcp14> be
            ignored
            ignored, and the currently active SieveScript (if any) will
            remain as such.
            </t>

            <t>
            The id of any activated SieveScript MUST <bcp14>MUST</bcp14> be reported in
            either the "created" or "updated" argument in the response
            as appropriate, including a value of "true" for  the "isActive"
            property.
            The id of any deactivated SieveScript MUST <bcp14>MUST</bcp14> be reported in
            the "updated" argument in the response, including a value of
            "false" for the "isActive" property.
            </t>
            <t/>
          </li>

          <li>
            <t><strong>onSuccessDeactivateScript</strong>:
            <tt>Boolean</tt>
          </dd>

            <dt><strong>onSuccessDeactivateScript</strong>:</dt>
            <dd><t><tt>Boolean</tt>
            </t>
            <t>
            If <tt>true</tt>, "true", the currently active
            SieveScript (if any) will be deactivated if and only if
            all of the creations, modifications, and destructions (if
            any) succeed.
            If <tt>false</tt> "false" or omitted, the currently active SieveScript (if
            any) will remain as such.
            </t>
            <t>

            The id of any deactivated SieveScript MUST <bcp14>MUST</bcp14> be reported in
            the "updated" argument in the response, including a value of
            "false" for the "isActive" property.
            </t>
            <t/>
          </li>
        </ul>
          </dd>
        </dl>

        <t>If both the <strong>onSuccessActivateScript</strong> "onSuccessActivateScript" and
        <strong>onSuccessDeactivateScript</strong>
        "onSuccessDeactivateScript" arguments are
        present in the request, then
        <strong>onSuccessDeactivateScript</strong> MUST
        "onSuccessDeactivateScript" <bcp14>MUST</bcp14> be processed first.
        If neither argument is present in the request, the currently
        active SieveScript (if any) will remain as such.
        </t>

        <t>This method provides equivalent functionality equivalent to that of the
        PUTSCRIPT, DELETESCRIPT, RENAMESCRIPT, and SETACTIVE commands defined
        in <xref target="RFC5804"/>.
        </t>

        <t>Script content must first be uploaded as per
        <xref target="content"/> prior to referencing it in a
        SieveScript/set call.</t>

        <t>If the SieveScript can not cannot be created or updated because it
        would result in two SieveScripts with the same name, the
        server MUST <bcp14>MUST</bcp14> reject the request with an "alreadyExists"
        SetError.
        An "existingId" property of type "Id" MUST <bcp14>MUST</bcp14> be included on the
        SetError object with the id of the existing SieveScript.</t>

        <t>If the SieveScript can not cannot be created or updated because
        its size exceeds the "maxSizeScript" limit, the server MUST <bcp14>MUST</bcp14>
        reject the request with a "tooLarge" SetError.</t>

        <t>If the SieveScript can not cannot be created because it would
        exceed the "maxNumberScripts" limit or would exceed a
        server-imposed storage limit, the server MUST <bcp14>MUST</bcp14>
        reject the request with an "overQuota" SetError.</t>

        <t>The active SieveScript MUST NOT <bcp14>MUST NOT</bcp14> be destroyed
        unless it is first deactivated in a separate SieveScript/set
        method call.</t>
        <t>The following extra SetError types are defined:
        </t>

        <t>For "create" and "update":
        </t>
        <ul
        <dl spacing="normal">
          <li>
            <t><strong>invalidSieve</strong>:
            </t>
            <t>

            <dt><strong>invalidSieve</strong>:</dt>
            <dd><t>
              The SieveScript content violates the
              <xref target="RFC5228">Sieve</xref>
              grammar target="RFC5228">Sieve grammar</xref>,
              and/or one
              or more extensions mentioned in the script's "require"
              statement(s) are not supported by the Sieve interpreter.
              The <em>description</em> "description" property on
              the SetError object SHOULD <bcp14>SHOULD</bcp14> contain a specific error
              message giving at least the line number of the first error.
            </t>
            <t/>
          </li>
        </ul> error.</t>
            </dd>
          </dl>
        <t>For "destroy":
        </t>
        <ul
        <dl spacing="normal">
          <li>
            <t><strong>sieveIsActive</strong>:
            </t>
            <t>
            <dt><strong>sieveIsActive</strong>:</dt>
            <dd><t>
              The SieveScript is active.
            </t>
            <t/>
          </li>
        </ul>
          </dd>
        </dl>
        <section numbered="true" toc="default">
          <name>Examples</name>
          <t keepWithNext="true">
                Upload a script
                requiring the Imap4Flags Extension
                <xref target="RFC5232"/>
                Extension
                using the JMAP uploadUrl as advertised in the example in
                <xref target="session"/>:
          </t>
          <artwork
<sourcecode name="" type="" align="left" alt=""><![CDATA[ type="http-message"><![CDATA[
POST /jmap/upload/ken/ HTTP/1.1
Host: jmap.example.com
Authorization: Basic a2VuOnBhc3N3b3Jk
Content-Type: application/sieve
Content-Length: 98

require "imapflags";

if address :is ["To", "Cc"] "jmap@ietf.org" {
  setflag "\\Flagged";
}

HTTP/1.1 201 Created
Date: Thu, 10 Dec 2020 17:14:31 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 171

{
  "accountId": "ken",
  "blobId": "Gabcc83e44a6e19991c4568d0b94e1767c83dd123",
  "type": "application/sieve"
  "size": 98
}
]]></artwork>
]]></sourcecode>
          <t keepWithNext="true">
                Create and activate
                a script using the uploaded blob.
                Note that the response shows that an existing active
                script has been deactivated in lieu of the newly
                created script being activated.
          </t>
          <artwork
<sourcecode name="" type="" align="left" alt=""><![CDATA[ type="json"><![CDATA[
[
  ["SieveScript/set", {
    "accountId": "ken",
    "create": {
      "A": {
        "name": null,
        "blobId": "Gabcc83e44a6e19991c4568d0b94e1767c83dd123"
      }
    },
    "onSuccessActivateScript": "#A"
  }, "0"]
]

[
  [
    "SieveScript/set",
    {
      "oldState": "1603741717.50737918-4096",
      "newState": "1603741751.227268529-4096",
      "created": {
        "A": {
          "id": "dd1b164f-8cdc-448c-9f54",
          "name": "ken-20201210T171432-0",
          "blobId": "Sdd1b164f-8cdc-448c-9f54",
          "isActive": true
        }
      },
      "updated": {
        "8abd6f4a-bcb4d-87650-3fcd": {
          "isActive": false
        }
      },
      "destroyed": null,
      "notCreated": null,
      "notUpdated": null,
      "notDestroyed": null,
      "accountId": "ken"
    },
    "0"
  ]
]
]]></artwork>
]]></sourcecode>
          <t keepWithNext="true">
            Update the script content using
            the <xref target="RFC9404"> JMAP Blob management extension</xref>:
          </t>
          <artwork
<sourcecode name="" type="" align="left" alt=""><![CDATA[ type="json"><![CDATA[
{
[
  ["Blob/upload", {
    "accountId": "ken",
    "create": {
      "B": {
        "data": [ {
          "data:asText":
            "redirect \"ken@example.com\"\r\n;"
         } ],
        "type": "application/sieve"
      }
    }
  }, "1"],
  ["SieveScript/set", {
    "accountId": "ken",
    "update": { "dd1b164f-8cdc-448c-9f54": {
      "blobId": "#B"
      }
    }
  }, "2"]
]

[
  [
    "Blob/upload",
    {
      "oldState": null,
      "newState": "1603741700.309607123-0128",
      "created": {
        "B": {
          "id": "G969c83e44a6e10871c4568d0b94e1767c83ddeae",
          "blobId": "G969c83e44a6e10871c4568d0b94e1767c83ddeae",
          "type": "application/sieve",
          "size": 29
        }
      },
      "notCreated": null,
      "accountId": "ken"
    },
    "1"
  ],
  [
    "SieveScript/set",
    {
      "oldState": "1603741751.227268529-4096",
      "newState": "1603742603.309607868-4096",
      "created": null,
      "updated": {
        "dd1b164f-8cdc-448c-9f54": null
      },
      "destroyed": null,
      "notCreated": null,
      "notUpdated": null,
      "notDestroyed": null,
      "accountId": "ken"
    },
    "2"
  ]
]
]]></artwork>
]]></sourcecode>
          <t keepWithNext="true">
            Update the script name name, and deactivate it:
          </t>
          <artwork
<sourcecode name="" type="" align="left" alt=""><![CDATA[ type="json"><![CDATA[
[
  ["SieveScript/set", {
    "accountId": "ken",
    "update": { "dd1b164f-8cdc-448c-9f54": {
      "name": "myscript"
      }
    },
    "onSuccessDeactivateScript": true
  }, "3"]
]

[
  [
    "SieveScript/set",
    {
      "oldState": "1603742603.309607868-4096",
      "newState": "1603742967.852315428-4096",
      "created": null,
      "updated": {
        "dd1b164f-8cdc-448c-9f54": {
          "isActive": false
        }
      },
      "destroyed": null,
      "notCreated": null,
      "notUpdated": null,
      "notDestroyed": null,
      "accountId": "ken"
    },
    "3"
  ]
]
]]></artwork>
]]></sourcecode>
          <t keepWithNext="true">
            Reactivate the script:
          </t>
          <artwork
<sourcecode name="" type="" align="left" alt=""><![CDATA[ type="json"><![CDATA[
[
  ["SieveScript/set", {
    "accountId": "ken",
    "onSuccessActivateScript": "dd1b164f-8cdc-448c-9f54"
  }, "4"]
]

[
  [
    "SieveScript/set",
    {
      "oldState": "1603742967.852315428-4096",
      "newState": "1603744460.316617118-4096",
      "created": null,
      "updated": {
        "dd1b164f-8cdc-448c-9f54": {
          "isActive": true
        }
      },
      "destroyed": null,
      "notCreated": null,
      "notUpdated": null,
      "notDestroyed": null,
      "accountId": "ken"
    },
    "4"
  ]
]
]]></artwork>
]]></sourcecode>
          <t keepWithNext="true">
            Deactivate and destroy the active script:
          </t>
          <artwork
<sourcecode name="" type="" align="left" alt=""><![CDATA[ type="json"><![CDATA[
[
  ["SieveScript/set", {
    "accountId": "ken",
    "onSuccessDeactivateScript": true
  }, "5"],
  ["SieveScript/set", {
    "accountId": "ken",
    "destroy": [ "dd1b164f-8cdc-448c-9f54" ]
  }, "6"]
]

[
  [
    "SieveScript/set",
    {
      "oldState": "1603744460.316617118-4096",
      "newState": "1603744637.575375572-4096",
      "created": null,
      "updated": {
        "dd1b164f-8cdc-448c-9f54": {
          "isActive": false
        }
      },
      "destroyed": null,
      "notCreated": null,
      "notUpdated": null,
      "notDestroyed": null,
      "accountId": "ken"
    },
    "5"
  ],
  [
    "SieveScript/set",
    {
      "oldState": "1603744637.575375572-4096",
      "newState": "1603744637.854390875-4096",
      "created": null,
      "updated": null,
      "destroyed": [
        "dd1b164f-8cdc-448c-9f54"
      ],
      "notCreated": null,
      "notUpdated": null,
      "notDestroyed": null,
      "accountId": "ken"
    },
    "6"
  ]
]
]]></artwork>
]]></sourcecode>
        </section>
      </section>
      <!-- /set -->

      <section numbered="true" toc="default">
        <name>SieveScript/query</name>
        <t>This is a standard "/query" method as described in
        <xref target="RFC8620" section="5.5" sectionFormat="comma"/>.

        A <em>FilterCondition</em> "FilterCondition" object has the
        following properties, either of which may be omitted:

        </t>
        <ul
        <dl spacing="normal">
          <li>
            <t><strong>name</strong>:
            <tt>String</tt>

            <dt><strong>name</strong>:</dt>
            <dd><t><tt>String</tt>
            </t>
            <t>
            The SieveScript "name" property contains the given string.
            </t>
            <t/>
          </li>
          <li>
            <t><strong>isActive</strong>:
            <tt>Boolean</tt>
          </dd>

            <dt><strong>isActive</strong>:</dt>
            <dd><t><tt>Boolean</tt>
            </t>
            <t>
            The "isActive" property of the SieveScript must be
            identical to the value given to match the condition.
            </t>
            <t/>
          </li>
          <!--
          <t>
            <spanx style="strong">isIncluded</spanx>:
            <spanx style="verb">Boolean</spanx>
            <vspace blankLines="1"/>
            If true, the SieveScript must be included
            (see <xref target="RFC6609" />) by the content of another
            SieveScript to match the condition.
            Otherwise, the SieveScript must not be included by the
            content of another SieveScript to match the condition.
            <vspace blankLines="1"/>
          </t>
-->
        </ul>
          </dd>
        </dl>
        <t>The following SieveScript properties MUST <bcp14>MUST</bcp14> be supported for
        sorting:

        </t>
        <ul spacing="normal">
          <li>
            <t><strong>name</strong>
            </t>
            <t/>
          </li>
          <li>
            <strong>isActive</strong>
          </li>
        </ul>
      </section>
      <section numbered="true" toc="default">
        <name>SieveScript/validate</name>
        <t>This method is used by the client to verify Sieve script
        validity without storing the script on the server.
        </t>
        <t>The method takes the following arguments:

        </t>
        <ul
        <dl spacing="normal">
          <li>
            <t><strong>accountId</strong>:
              <tt>Id</tt>
            <dt><strong>accountId</strong>:</dt>
              <dd><t><tt>Id</tt>
            </t>
            <t>
              The id of the account to use.
            </t>
            <t/>
          </li>
          <li>
            <t><strong>blobId</strong>:
              <tt>Id</tt>
          </dd>
            <dt><strong>blobId</strong>:</dt>
              <dd><t><tt>Id</tt>
            </t>
            <t>
              The id of the blob containing the raw octets of the
              script to validate,
              subject to the same requirements in
              <xref target="object"/>. target="content"/>.
            </t>
            <t/>
          </li>
        </ul>
          </dd>
        </dl>
        <t>The response has the following arguments:

        </t>
        <ul
        <dl spacing="normal">
          <li>
            <t><strong>accountId</strong>:
              <tt>Id</tt>
            <dt><strong>accountId</strong>:</dt>
              <dd><t><tt>Id</tt>
            </t>
            <t>
              The id of the account used for this call.
            </t>
            <t/>
          </li>
          <li>
            <t><strong>error</strong>:
              <tt>SetError|null</tt>
          </dd>

            <dt><strong>error</strong>:</dt>
              <dd><t><tt>SetError|null</tt>
            </t>
            <t>
              An "invalidSieve" SetError object if the script content
              is invalid (see <xref target="set"/>),
              or <tt>null</tt> if the
              script content is valid.
            </t>
            <t/>
          </li>
        </ul>
          </dd>
        </dl>

        <t>This method provides equivalent functionality equivalent to that of the
        CHECKSCRIPT command defined in <xref target="RFC5804"/>.</t>

        <t>Script content must first be uploaded as per
        <xref target="content"/> prior to referencing it in a
        SieveScript/validate call.</t>
      </section>
      <!-- /validate -->
    </section>

    <section anchor="quotas" numbered="true" toc="default">
      <name>Quotas</name>
      <t>Servers SHOULD <bcp14>SHOULD</bcp14> impose quotas on Sieve scripts to prevent
      malicious users from exceeding available storage.
      Administration of such quotas is outside of the scope of this
      specification, however
      specification; however, <xref target="RFC9425"/> defines a data
      model for users to obtain quota details over JMAP.</t>

      <t>The mechanism for handling SieveScript requests that would place
      a user over a quota setting is discussed in <xref target="set"/>.
      </t>
    </section>

    <section anchor="vacation" numbered="true" toc="default">
      <name>Compatibility with JMAP Vacation Response</name>
      <t><xref target="RFC8621" section="8"/> defines a
      VacationResponse
      "VacationResponse" object to represent an autoresponder to
      incoming email messages.
      Servers that implement the VacationResponse as a Sieve script
      that resides amongst among other user scripts are subject to the
      following requirements:

      </t>
      <ul spacing="normal">
        <li>MUST
        <li><bcp14>MUST</bcp14> allow the VacationResponse Sieve script to be fetched
        by the <xref target="get">SieveScript/get</xref>
        method. target="get">SieveScript/get method</xref>.
        </li>
        <li>MUST
        <li><bcp14>MUST</bcp14> allow the VacationResponse Sieve script to be
        [de]activated
        activated or deactivated via the "onSuccessActivateScript" argument to
        the <xref target="set">SieveScript/set</xref> method. target="set">SieveScript/set method</xref>.
        </li>
        <li>MUST NOT
        <li><bcp14>MUST NOT</bcp14> allow the VacationResponse Sieve script to be
        destroyed or have its content updated by the
        <xref target="set">SieveScript/set</xref> method. target="set">SieveScript/set method</xref>.
        Any such request MUST <bcp14>MUST</bcp14> be rejected with a "forbidden" SetError.
        A "description" property MAY <bcp14>MAY</bcp14> be present with an explanation
        that the script can only be modified by a VacationResponse/set
        method.
        </li>
      </ul>
    </section>
    <section anchor="security" numbered="true" toc="default">
      <name>Security Considerations</name>
      <t>All security considerations of discussed in
      <xref target="RFC8620">JMAP</xref>
      and <xref target="RFC5228">Sieve</xref>
      apply to this specification.</t>

      <t>Additionally, implementations MUST <bcp14>MUST</bcp14> treat Sieve script content
      as untrusted data.  As such, script parsers MUST <bcp14>MUST</bcp14> fail gracefully
      in the face of syntactically invalid or malicious content and
      MUST
      <bcp14>MUST</bcp14> be prepared to deal with resource exhaustion (E.g., (e.g.,
      allocation of enormous strings, lists, or command blocks).
      </t>
    </section>

    <section numbered="true" toc="default">
      <name>IANA Considerations</name>

      <section numbered="true" toc="default">
        <name>JMAP Capability Registration for "sieve"</name>
        <t>IANA will register the has registered "sieve" JMAP Capability in the "JMAP Capabilities" registry as follows:
        </t>
        <t>Capability Name:
        <tt>urn:ietf:params:jmap:sieve</tt>
        </t>
        <t>Specification document: this document
        </t>
        <t>Intended use: common
        </t>
        <t>Change Controller: IETF
        </t>
        <t>Security and privacy considerations: this document,
        <dl spacing="normal">
        <dt>Capability Name:</dt><dd><tt>urn:ietf:params:jmap:sieve</tt></dd>
        <dt>Reference:</dt><dd>RFC 9661</dd>
        <dt>Intended Use:</dt><dd>common</dd>
        <dt>Change Controller:</dt><dd>IETF</dd>
        <dt>Security and Privacy Considerations:</dt><dd>RFC 9661,
        <xref target="security"/>
        </t> target="security"/></dd>
	</dl>
      </section>

      <section numbered="true" toc="default">
        <name>JMAP Data Type  Registration for "SieveScript"</name>
        <t>IANA will register the has registered "SieveScript" JMAP in the "JMAP Data Type Types" registry as follows:
        </t>
        <t>Type Name: <tt>SieveScript</tt>
        </t>
        <t>Can
        <dl spacing="normal">
        <dt>Type Name:</dt><dd><tt>SieveScript</tt></dd>
        <dt>Can Reference Blobs: yes
        </t>
        <t>Can Blobs:</dt><dd>Yes</dd>
        <dt>Can Use for State Change: yes
        </t>
        <t>Capability:
        <tt>urn:ietf:params:jmap:sieve</tt>
        </t>
        <t>Specification document: this document
        </t> Change:</dt><dd>Yes</dd>
        <dt>Capability:</dt><dd><tt>urn:ietf:params:jmap:sieve</tt></dd>
        <dt>Reference:</dt><dd>RFC 9661</dd>
	</dl>
      </section>

      <section numbered="true" toc="default">
        <name>JMAP Error Codes Registry</name>
        <t>
          The
          IANA has registered the following sub-sections register two new error codes in the
          JMAP
          "JMAP Error Codes Codes" registry, as defined in
          <xref target="RFC8620"/>.
        </t>

        <section numbered="true" toc="default">
          <name>invalidSieve</name>
          <t>JMAP
          <dl spacing="normal">
          <dt>JMAP Error Code: invalidSieve </t>
          <t>Intended use: common </t>
          <t>Change controller: IETF </t>
          <t>Reference: This document, Code:</dt><dd>invalidSieve</dd>
          <dt>Intended Use:</dt><dd>common</dd>
          <dt>Change Controller:</dt><dd>IETF</dd>
          <dt>Reference:</dt><dd>RFC 9661, <xref target="set"/> </t>
          <t>Description: The target="set"/></dd>
          <dt>Description:</dt><dd>The SieveScript violates the
          <xref target="RFC5228">Sieve grammar</xref> grammar</xref>, and/or one
          or more extensions mentioned in the script's "require"
          statement(s) are not supported by the Sieve interpreter.</t> interpreter.</dd>
	  </dl>
        </section>

        <section numbered="true" toc="default">
          <name>sieveIsActive</name>
          <t>JMAP
          <dl spacing="normal">
          <dt>JMAP Error Code: sieveIsActive </t>
          <t>Intended use: common </t>
          <t>Change controller: IETF </t>
          <t>Reference: This document, Code:</dt><dd>sieveIsActive</dd>
          <dt>Intended Use:</dt><dd>common</dd>
          <dt>Change Controller:</dt><dd>IETF</dd>
          <dt>Reference:</dt><dd>RFC 9661, <xref target="set"/> </t>
          <t>Description: The target="set"/></dd>
          <dt>Description:</dt><dd>The client tried to destroy the active
          SieveScript.</t>
          SieveScript.</dd>
	  </dl>
        </section>
      </section>
    </section>
  </middle>

  <back>
    <references>
      <name>References</name>
      <references>
        <name>Normative References</name>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8620.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8621.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5228.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.3986.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5435.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6134.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.3629.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5198.xml"/>
      </references>
      <references>
        <name>Informative References</name>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5232.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5463.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5804.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9112.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9404.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9425.xml"/>
      </references>
    </references>
    <section numbered="true" numbered="false" toc="default">
      <name>Acknowledgments</name>
      <t>The concepts in this document are based largely on those in
      <xref target="RFC5804"/>.
      The author would like to thank the authors of that document for
      providing both inspiration and some borrowed text for this
      document.</t>
      <t>The author would also like to thank the following
      individuals for contributing their ideas and support for
      writing this specification: Joris Baum, Mauro <contact fullname="Joris Baum"/>, <contact fullname="Mauro De Gennaro,
      Bron Gondwana, Neil Jenkins, Alexey Melnikov, and Ricardo Signes.</t>
    </section>
  </middle>

  <back>
    <references>
      <name>References</name>
      <references>
        <name>Normative References</name>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8620.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8621.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.5228.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.3986.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.5435.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.6134.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.3629.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.5198.xml"/>
      </references>
      <references>
        <name>Informative References</name>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.5232.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.5463.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.5804.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.9112.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.9404.xml"/>
        <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.9425.xml"/>
      </references>
    </references>
    <section numbered="true" toc="default">
      <name>Change History
      (To be removed by RFC Editor before publication)</name>
      <t>Changes since ietf-21:
      </t>
      <ul spacing="normal">
        <li>Rearranged and tweaked some /validate text.</li>
      </ul>
      <t>Changes since ietf-20:
      </t>
      <ul spacing="normal">
        <li>Listed Unicode characters prohibited in script names.</li>
        <li>Cleaned up the language of the optional /set arguments.</li>
        <li>Added security considerations about parsing Sieve script
        content.</li>
        <li>Miscellaneous editorial changes.</li>
      </ul>
      <t>Changes since ietf-19:
      </t>
      <ul spacing="normal">
        <li>Tweaked the example captions.</li>
      </ul>
      <t>Changes since ietf-18:
      </t>
      <ul spacing="normal">
        <li>Edited JMAP API examples for brevity to match other JMAP
        specs, and added explanatory text to 1.1.</li>
        <li>Updated &lt;xref&gt; elements to to use "section" and
        "sectionFormat" attributes.</li>
      </ul>
      <t>Changes since ietf-17:
      </t>
      <ul spacing="normal">
        <li>Several editorial changes resulting from IESG review
        comments.</li>
        <li>Added a section discussuing quotas.</li>
      </ul>
      <t>Changes since ietf-16:
      </t>
      <ul spacing="normal">
        <li>Renamed the "invalidScript" and "scriptIsActive" SetErrors
        to "invalidSieve" and "sieveIsActive" respectively.</li>
      </ul>
      <t>Changes since ietf-15:
      </t>
      <ul spacing="normal">
        <li>Added registration for SieveScript JMAP Data Type.</li>
        <li>Miscellaneous editorial changes.</li>
      </ul>
      <t>Changes since ietf-14:
      </t>
      <ul spacing="normal">
        <li>Updated reference for JMAP Blobs.</li>
      </ul>
      <t>Changes since ietf-13:
      </t>
      <ul spacing="normal">
        <li>Added implementation argument to capabilities.</li>
        <li>Miscellaneous editorial changes.</li>
      </ul>
      <t>Changes since ietf-12:
      </t>
      <ul spacing="normal">
        <li>Added onSuccessDeactivateScipt argument to /set
        method.</li>
        <li>Clarified that the "isActive" property must be included in the
        created/uodated/destroyed arguments in a response of the
        active script is changed and/or deactivated.</li>
        <li>Miscellaneous editorial changes.</li>
      </ul>
      <t>Changes since ietf-11:
      </t>
      <ul spacing="normal">
        <li>Fixed examples to be proper JSON and JMAP.</li>
      </ul>
      <t>Changes since ietf-10:
      </t>
      <ul spacing="normal">
        <li>Fixed SieveScript/set response deactivating script example.</li>
        <li>Fixed line line nit in Blob/get request.</li>
        <li>Removed unused references.</li>
      </ul>
      <t>Changes since ietf-09:
      </t>
      <ul spacing="normal">
        <li>Fixed Blob/upload request in example.</li>
      </ul>
      <t>Changes since ietf-08:
      </t>
      <ul spacing="normal">
        <li>Fixed Blob/upload response in example.</li>
        <li>Removed SieveScript/test method (to be written as an
        extension document).</li>
      </ul>
      <t>Changes since ietf-07:
      </t>
      <ul spacing="normal">
        <li>Updated example to use Blob/upload rather than Blob/set.</li>
      </ul>
      <t>Changes since ietf-06:
      </t>
      <ul spacing="normal">
        <li>None (refreshed to avoid expiration).</li>
      </ul>
      <t>Changes since ietf-05:
      </t>
      <ul spacing="normal">
        <li>Converted source from xml2rfc v2 to v3.</li>
        <li>Added examples for SieveScript/get.</li>
        <li>Miscellaneous editorial changes.</li>
      </ul>
      <t>Changes since ietf-04:
      </t>
      <ul spacing="normal">
        <li>SieveScript/test: Switched from using a JSON array for each
        completed action and its args to a JSON object.</li>
        <li>Switched to referencing draft-ietf-jmap-blob.</li>
        <li>Miscellaneous editorial changes.</li>
      </ul>
      <t>Changes since ietf-03:
      </t>
      <ul spacing="normal">
        <li>SieveScript/test: Moved positional arguments into their own
        array (because the specfications don't use a consistent method for
        defining the action syntax or naming of positional arguments).</li>
      </ul>
      <t>Changes since ietf-02:
      </t>
      <ul spacing="normal">
        <li>Removed open issues.</li>
        <li>Reverted back to using only blob ids for script content.</li>
        <li>Added "rateLimit" and "requestTooLarge" to the list of
        possible error codes for /set method.</li>
        <li>Added Compatibility with JMAP Vacation Response
        section.</li>
        <li>Added RFC5228 to Security Considerations.</li>
        <li>Miscellaneous editorial changes.</li>
      </ul>
      <t>Changes since ietf-01:
      </t>
      <ul spacing="normal">
        <li>Removed normative references to ManageSieve (RFC 5804).</li>
        <li>Added the 'maxSizeScriptName' capability.</li>
        <li>Made the 'name' property in the SieveScript object
        optional.</li>
        <li>Added requirements for the 'name' property in the
        SieveScript object.</li>
        <li>Removed the 'blobId' property from the SieveScript
        object.</li>
        <li>Removed the 'replaceOnCreate' argument from the /set
        method.</li>
        <li>Removed the 'blobId' argument from the /validate method.</li>
        <li>Removed the 'scriptBlobId' argument from, and added the
        'scriptContent' argument to, the /test method.</li>
        <li>Editorial fixes from Neil Jenkins and Ricardo Signes.</li>
        <li>Other miscellaneous text reorganization and editorial fixes.</li>
      </ul>
      <t>Changes since ietf-00:
      </t>
      <ul spacing="normal">
        <li>Specified that changes made by onSuccessActivateScript MUST
        be reported in the /set response as created and/or updated as
        appropriate.</li>
        <li>Reworked and specified more of the /test response based on
        implementation experience.</li>
      </ul>
      <t>Changes since murchison-01:
      </t>
      <ul spacing="normal">
        <li>Explicitly stated that Sieve capability strings are
        case-sensitive.</li>
        <li>errorDescription is now String|null.</li>
        <li>Added /query method.</li>
        <li>Added /test method.</li>
      </ul>
      <t>Changes since murchison-00:
      </t>
      <ul spacing="normal">
        <li>Added IANA registration for "scriptIsActive" JMAP error code.</li>
        <li>Added open issue about /set{create} with an existing script name.</li>
      </ul> Gennaro"/>,
      <contact fullname="Bron Gondwana"/>, <contact fullname="Neil Jenkins"/>, <contact fullname="Alexey Melnikov"/>, and <contact fullname="Ricardo Signes"/>.</t>
    </section>
  </back>
</rfc>