<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rfc SYSTEM "rfc2629.dtd">

<rfc ipr="trust200902" category="std" docName="draft-ietf-jmap-sieve-01">
  <?rfc toc="yes"?>
  <?rfc symrefs="yes"?>
  <?rfc sortrefs="yes"?>
  <?rfc compact="yes"?>
  <?rfc subcompact="no"?>
  <?rfc private=""?>
  <?rfc topblock="yes"?>
  <?rfc comments="no"?>

  <front>
    <title abbrev="JMAP Sieve">JMAP for Sieve Scripts</title>

    <author initials="K." surname="Murchison" fullname="Kenneth Murchison">
      <organization abbrev="Fastmail">Fastmail US LLC</organization>
      <address>
        <postal>
          <street>1429 Walnut Street - Suite 1201</street>
          <city>Philadelphia</city> <region>PA</region>
          <code>19102</code> <country>USA</country>
        </postal>
        <email>murch@fastmailteam.com</email>
      </address>
    </author>

    <date />

    <area>ART</area>
    <!-- <workgroup>Independent Submission</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 JMAP.
      </t>
    </abstract>

    <note title="Open Issues">
      <t>
        <list style="symbols">
          <t>Do we need/want both "content" and "blobId" in the
          SieveScript object?  It may be simpler to have just one way
          of specifying content and "blobId" is more versatile and
          doesn't require JSON-encoding of the content.
          Furthermore, use of the forthcoming(?) Blob/set method would
          avoid the extra roundtrip of having to upload the blob
          first.</t>
<!--
          <t>Should changes made by onSuccessActivateScript be
          reported in the response to the client-initiated request, or
          via a second implicit SIeveScript/set response?</t>
-->
          <t>The strawman for SieveScript/test only uses blobIds.
          Will this have to change once the issue regarding
          content/blobId in SieveScript is resolved?</t>

          <t>Should ":fcc" and associated arguments (e.g., ":flags",
          ":create":, etc) reported in the /test response be in their
          own "fcc" sub-object rather than listed inline with the rest
          of the arguments for the action?</t>
        </list>
      </t>
    </note>

  </front>

  <middle>

    <section title="Introduction">
      <t>JMAP (<xref target="RFC8620"/> – JSON Meta Application
      Protocol) is a generic protocol for synchronizing data, such as
      mail, calendars or contacts, between a client and a server.
      It is optimized for mobile and web environments, and aims to
      provide a consistent interface to different data types.
      </t>

      <t>This specification defines a data model for managing Sieve
      <xref target="RFC5228"/> scripts on a server using JMAP.
      The data model is designed to allow a server to provide
      consistent access to the same scripts via ManageSieve
      <xref target="RFC5804"/> as well as JMAP, however the
      functionality offered over the two protocols may differ.
      </t>

      <section title="Notational Conventions">
        <t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL",
        "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT
        RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
        interpreted as described in BCP 14 <xref target="RFC2119"/>
        <xref target="RFC8174"/> when, and only when, they appear in
        all capitals, as shown here.
        </t>

        <t>Type signatures, examples, and property descriptions in
        this document follow the conventions established in Section
        1.1 of <xref target="RFC8620"/>.  Data types defined in the
        core specification are also used in this document. 
        </t>
      </section>

      <section title="Terminology">
        <t>The same terminology is used in this document as in the
        core JMAP specification, see <xref target="RFC8620"/>, Section
        1.6.
        </t>

        <t>The term SieveScript (with this specific capitalization) is
        used to refer to the data type defined in this document and
        instances of those data types. 
        </t>
      </section>

      <section title="Addition to the Capabilities Object">
        <t>The capabilities object is returned as part of the JMAP
        Session object; see <xref target="RFC8620"/>, Section 2. This
        document defines one additional capability URI.
        </t>

        <section title="urn:ietf:params:jmap:sieve" anchor="capa">
          <t>This represents support for the SieveScript data type and
          associated API methods.
          The value of this property in the JMAP Session
          capabilities property is an empty object.
          </t>

          <t>The value of this property in an account’s
          accountCapabilities property is an object that MUST contain
          the following information on server capabilities:

            <list style="symbols">
              <t>
                <spanx style="strong">supportsTest</spanx>:
                <spanx style="verb">Boolean</spanx>
                <vspace blankLines="1"/>
                If true, the server supports the
                <xref target="test">SieveScript/test</xref> method.
                <vspace blankLines="1"/>
              </t>

              <t>
                <spanx style="strong">maxNumberRedirects</spanx>:
                <spanx style="verb">UnsignedInt|null</spanx>
                <vspace blankLines="1"/>
                The maximum number of Sieve "redirect" actions a
                script can perform during a single evaluation
                (see <xref target="RFC5804"/>, Section 1.7),
                or <spanx style="verb">null</spanx> for no limit.
                <vspace blankLines="1"/>
              </t>

              <t>
                <spanx style="strong">maxNumberScripts</spanx>:
                <spanx style="verb">UnsignedInt|null</spanx>
                <vspace blankLines="1"/>
                The maximum number of Sieve scripts the server is
                willing to store for the user,
                or <spanx style="verb">null</spanx> for no limit.
                <vspace blankLines="1"/>
              </t>

              <t>
                <spanx style="strong">maxSizeScript</spanx>:
                <spanx style="verb">UnsignedInt|null</spanx>
                <vspace blankLines="1"/>
                The maximum size (in octets) of a Sieve script the
                server is willing to store for the user,
                or <spanx style="verb">null</spanx> for no limit.
                <vspace blankLines="1"/>
              </t>

              <t>
                <spanx style="strong">sieveExtensions</spanx>:
                <spanx style="verb">String[]</spanx>
                <vspace blankLines="1"/>
                A list of case-sensitive Sieve capability strings (as
                listed in Sieve "require" action <xref
                target="RFC5228"/>, Section 3.2) indicating the
                extensions supported by the Sieve engine.
                <vspace blankLines="1"/>
              </t>

              <t>
                <spanx style="strong">notificationMethods</spanx>:
                <spanx style="verb">String[]|null</spanx>
                <vspace blankLines="1"/>
                A list of URI schema parts <xref target="RFC3986"/>
                for notification methods supported by the Sieve
                "enotify" extension <xref target="RFC5435"/>,
                or <spanx style="verb">null</spanx> if the extension
                is not supported by the Sieve engine.
                <vspace blankLines="1"/>
              </t>

              <t>
                <spanx style="strong">externalLists</spanx>:
                <spanx style="verb">String[]|null</spanx>
                <vspace blankLines="1"/>
                A list of URI schema parts <xref target="RFC3986"/>
                for externally stored list types supported by the
                Sieve "extlists" extension <xref target="RFC6134"/>,
                or <spanx style="verb">null</spanx> if the extension
                is not supported by the Sieve engine.
              </t>
            </list>
          </t>
        </section>

      </section>
    </section>

    <section title="Sieve Scripts" anchor="object">
      <t>A <spanx style="strong">SieveScript</spanx> object represents
      a single <xref target='RFC5228'>Sieve</xref> script.
      A user may have multiple SieveScripts on the server, yet only one
      script may be used for filtering of incoming messages.  This is the
      active script.  Users may have zero or one active script.
      The <xref target='set'>SieveScript/set</xref> method described
      below is used for changing the active script or disabling Sieve
      processing.
      </t>

      <t>A <spanx style="strong">SieveScript</spanx> object has the
      following properties:

        <list style="symbols">
          <t>
            <spanx style="strong">id</spanx>:
            <spanx style="verb">Id</spanx>
            (immutable; server-set)
            <vspace blankLines="1"/>
            The id of the script.
            <vspace blankLines="1"/>
          </t>
          <t>
            <spanx style="strong">name</spanx>:
            <spanx style="verb">String</spanx>
            <vspace blankLines="1"/>
            The unique user-visible name for the script, subject to the
            requirements in <xref target="RFC5804"/>, Section 1.6.
            <vspace blankLines="1"/>
          </t>
          <t>
            <spanx style="strong">content</spanx>:
            <spanx style="verb">String</spanx>
            <vspace blankLines="1"/>
            The raw octets of the <xref target='RFC5228'>script</xref>.
            <vspace blankLines="1"/>
            Note that both Sieve and JSON require encoding of special
            characters which MUST be done in the following order:
            <list style="numbers">
              <t>
                Escape any double quote (&quot;) or backslash (\)
                characters appearing inside of quoted strings in the
                Sieve code per Section 2.4.2 of <xref target='RFC5228'/>.
                E.g., A string containing the value \foo becomes
                &quot;\\foo&quot;.
              </t>
              <t>
                Escape any double quote (&quot;), backslash (\), tab,
                carriage return, or line feed characters appearing in the
                resultant Sieve code per Section 7 of <xref target='RFC8259'/>.
                E.g., The example string in step 1 becomes
                \&quot;\\\\foo\&quot;.
              </t>
            </list>
          </t>
          <t>
            <spanx style="strong">blobId</spanx>:
            <spanx style="verb">Id</spanx>
            (immutable)
            <vspace blankLines="1"/>
            The id of the blob containing the raw octets of the
            <xref target='RFC5228'>script</xref>.
            <vspace blankLines="1"/>
          </t>
          <t>
            <spanx style="strong">isActive</spanx>:
            <spanx style="verb">Boolean</spanx>
            (server-set; default: false)
            <vspace blankLines="1"/>
            Is this the user's active script?
            <vspace blankLines="1"/>
          </t>
        </list>

        <figure>
	  <preamble>
            Example (using the Imap4Flags <xref target="RFC5232"/> Extension):
          </preamble>
<artwork><![CDATA[
{
  "id": "Sabc",
  "blobId": "Bxyz",
  "name": "example.siv",
  "content":
     "require [ \"imap4flags\" ];\r\nkeep :flags \"\\\\flagged\";",
  "isActive": false
}
]]></artwork>
        </figure>
      </t>

      <section title="SieveScript/get" anchor="get">
        <t>This is a standard "/get" method as described in
        <xref target="RFC8620"/>, Section 5.1.
        The <spanx style="emph">ids</spanx> argument may be
        <spanx style="verb">null</spanx> to fetch all at once. 
        </t>

        <t>This method provides similar functionality to the GETSCRIPT
        and LISTSCRIPTS commands in <xref target="RFC5804"/>.
        </t>
      </section>

      <section title="SieveScript/set" anchor="set">
        <t>This is a standard "/set" method as described in
        <xref target="RFC8620"/>, Section 5.3 but with the following
        additional request arguments, either of which may be omitted:

        <list style="symbols">
          <t>
            <spanx style="strong">replaceOnCreate</spanx>:
            <spanx style="verb">Boolean</spanx>
            (default: false)
            <vspace blankLines="1"/>
            If false, any attempt to create a SieveScript having the
            same "name" property as an existing SieveScript MUST be
            rejected with a "scriptNameExists" SetError.
            If true, the existing SieveScript will be destroyed and
            the new SieveScript created as a single atomic action.
            The id of the replaced SieveScript MUST be reported in the
            "destroyed" argument in the response.
            <vspace blankLines="1"/>
          </t>
          <t>
            <spanx style="strong">onSuccessActivateScript</spanx>:
            <spanx style="verb">Id|null</spanx>
            <vspace blankLines="1"/>
            The id of the SieveScript to activate if the
            create/update/destroy succeeds.
            (For references to SieveScript creations, this is
            equivalent to a creation-reference, so the id will be the
            creation id prefixed with a "#".)
            If <spanx style="verb">null</spanx>, the currently active
            script (if any) will be deactivated.
            If this argument is not present in the request, the
            currently active script (if any) will remain as such.
            The id of the activated acript MUST be reported in the
            "created" or "updated" argument in the response as
            appropriate.
            The id of the deactivated script, if any, MUST be reported
            in the "updated" argument in the response unless the
            script was also destroyed.
            <vspace blankLines="1"/>
          </t>
        </list>
        </t>

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

        <t>When creating or updating a script, a client MUST include
        either a <spanx style="emph">content</spanx> or a
        <spanx style="emph">blobId</spanx> property.  A request that
        includes neither or both properties MUST be rejected with an
        "invalidProperties" SetError.
        The server MUST check the script content for syntactic
        validity, which includes checking that all Sieve extensions
        mentioned in Sieve script "require" statement(s) are
        supported by the Sieve interpreter.
        (Note that if the Sieve interpreter supports the Sieve
        "ihave" extension <xref target="RFC5463"/>, any
        unrecognized/unsupported extension mentioned in the "ihave"
        test MUST NOT cause the syntactic validation failure.)
        A script of zero length SHOULD be considered invalid.
        If the script content is invalid the request MUST be rejected
        with a "invalidScript" SetError.</t>
<!--
        <t>After all create/update/destroy items in the "SieveScript/set"
        invocation have been processed, a single implicit
        "SieveScript/set" call MUST be made to perform any changes
        requested in these "onSuccessActivateScript" argument.
        The response to this MUST be returned after the initial
        "SieveScript/set" response.
-->
        <t>Note that simply activating or deactivating a script
        without changing any script content is accomplished via a
        request containing an "onSuccessActivateScript" argument and
        <spanx style="verb">null</spanx> "create", "update", and
        "delete" arguments.</t>

        <t>The following extra SetError types are defined:
        </t>
        <t>For "create":
          <list style="symbols">
            <t>
              <spanx style="strong">scriptNameExists</spanx>:
              <vspace blankLines="1"/>
              A SieveScript already exists with the given
              <spanx style="strong">name</spanx> property,
              and the "replaceOnCreate" argument was false.
              An <spanx style="emph">existingId</spanx> property of
              type <spanx style="emph">Id</spanx> MUST be included on
              the SetError object with the id of the existing
              SieveScript. 
              <vspace blankLines="1"/>
            </t>
            <t>
              <spanx style="strong">tooManyScripts</spanx>:
              <vspace blankLines="1"/>
              Creating the SieveScript would exceed the
              <spanx style="strong">maxNumberScripts</spanx> limit
              (see <xref target="capa"/>).
              <vspace blankLines="1"/>
            </t>
          </list>
        </t>

        <t>For "create" and "update":
          <list style="symbols">
            <t>
              <spanx style="strong">invalidScript</spanx>:
              <vspace blankLines="1"/>
              The SieveScript violates the
              <xref 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 <spanx style="emph">description</spanx> property on
              the SetError object SHOULD contain a specific error
              message giving the line number of the first error.
              <vspace blankLines="1"/>
            </t>
          </list>
        </t>

        <t>For "destroy":
          <list style="symbols">
            <t>
              <spanx style="strong">scriptIsActive</spanx>:
              <vspace blankLines="1"/>
              The SieveScript is active and the
              "onSuccessActivateScript" argument was not present.
              <vspace blankLines="1"/>
            </t>
          </list>
        </t>
      </section>

      <section title="SieveScript/query">
        <t>This is a standard "/query" method as described in
        <xref target="RFC8620"/>, Section 5.5.

        A <spanx style="emph">FilterCondition</spanx> object has the
        following properties, any of which may be omitted:

        <list style='symbols'>
          <t>
            <spanx style="strong">name</spanx>:
            <spanx style="verb">String</spanx>
            <vspace blankLines="1"/>
            The SieveScript "name" property contains the given string.
            <vspace blankLines="1"/>
          </t>
          <t>
            <spanx style="strong">isActive</spanx>:
            <spanx style="verb">Boolean</spanx>
            <vspace blankLines="1"/>
            The "isActive" property of the SieveScript must be
            identical to the value given to match the condition.
            <vspace blankLines="1"/>
          </t>
        </list>
        </t>

        <t>The following SieveScript properties MUST be supported for
        sorting:

        <list style='symbols'>
          <t>
            <spanx style="verb">name</spanx>
          </t>
          <t>
            <spanx style="verb">isActive</spanx>
          </t>
        </list>
        </t>
      </section>

      <section title="SieveScript/validate">
        <t>This method is used by the client to verify Sieve script
        validity without storing the script on the server.
        </t>

        <t>The method provides similar functionality to the
        CHECKSCRIPT command in <xref target="RFC5804"/>.
        </t>
          
        <t>The <spanx style="strong">SieveScript/validate</spanx> method
        takes the following arguments: 

          <list style="symbols">
            <t>
              <spanx style="strong">accountId</spanx>:
              <spanx style="verb">Id</spanx>
              <vspace blankLines="1"/>
              The id of the account to use.
              <vspace blankLines="1"/>
            </t>
            <t>
              <spanx style="strong">content</spanx>:
              <spanx style="verb">String</spanx>
              <vspace blankLines="1"/>
              The raw octets of the <xref target='RFC5228'>script</xref>.
              <vspace blankLines="1"/>
            </t>
            <t>
              <spanx style="strong">blobId</spanx>:
              <spanx style="verb">Id</spanx>
              (immutable)
              <vspace blankLines="1"/>
              The id of the blob containing the raw octets of the
              <xref target='RFC5228'>script</xref>.
              <vspace blankLines="1"/>
            </t>
          </list>
        </t>

        <t>A client MUST include
        either a <spanx style="emph">content</spanx> or a
        <spanx style="emph">blobId</spanx> property.  A request that
        includes neither or both properties MUST be rejected with an
        "invalidProperties" SetError.
        The <spanx style="emph">content</spanx> property, if used,
        MUST be encoded following the same procedure as for the
        <spanx style="emph">content</spanx> property in the
        <xref target="object">SieveScript</xref> object.
        The server MUST check the script content for syntactic
        validity, which includes checking that all Sieve extensions
        mentioned in Sieve script "require" statement(s) are
        supported by the Sieve interpreter.
        (Note that if the Sieve interpreter supports the Sieve
        "ihave" extension <xref target="RFC5463"/>, any
        unrecognized/unsupported extension mentioned in the "ihave"
        test MUST NOT cause the syntactic validation failure.)</t>

        <t>The response has the following arguments: 

          <list style="symbols">
            <t>
              <spanx style="strong">accountId</spanx>:
              <spanx style="verb">Id</spanx>
              <vspace blankLines="1"/>
              The id of the account used for this call.
              <vspace blankLines="1"/>
            </t>
            <t>
              <spanx style="strong">error</spanx>:
              <spanx style="verb">SetError|null</spanx>
              <vspace blankLines="1"/>
              A SetError object if the request or the script content
              invalid, or <spanx style="verb">null</spanx> if the
              script content is valid.
              <vspace blankLines="1"/>
            </t>
          </list>
        </t>
      </section>

      <section title="SieveScript/test" anchor="test">
        <t>This method is used by the client to ask the Sieve
        interpreter to evaluate a Sieve script against a set of emails
        and report what actions would be performed for each.
        </t>

        <t>The <spanx style="strong">SieveScript/test</spanx> method
        takes the following arguments: 

          <list style="symbols">
            <t>
              <spanx style="strong">accountId</spanx>:
              <spanx style="verb">Id</spanx>
              <vspace blankLines="1"/>
              The id of the account to use.
              <vspace blankLines="1"/>
            </t>
            <t>
              <spanx style="strong">scriptBlobId</spanx>:
              <spanx style="verb">Id</spanx>
              <vspace blankLines="1"/>
              The id of the blob containing the SieveScript to test against.
              <vspace blankLines="1"/>
            </t>
            <t>
              <spanx style="strong">emailBlobIds</spanx>:
              <spanx style="verb">Id[]</spanx>
              <vspace blankLines="1"/>
              The ids of the blobs containing the <xref
              target="RFC8621">Emails</xref> to test against.
              <vspace blankLines="1"/>
            </t>
            <t>
              <spanx style="strong">envelope</spanx>:
              <spanx style="verb">Envelope|null</spanx>
              <vspace blankLines="1"/>
              Information that the Sieve interpreter should assume was
              present in the SMTP transaction that delivered the
              email when evaluating "envelope" tests.
              If <spanx style="verb">null</spanx>, all "envelope"
              tests MUST eveluate to false.
              See Section 7 of <xref target="RFC8621">Email</xref> for
              the contents of the Envelope object.
              <vspace blankLines="1"/>
            </t>
            <t>
              <spanx style="strong">lastVacationResponse</spanx>:
              <spanx style="verb">Date|null</spanx>
              <vspace blankLines="1"/>

              The date-time at which the Sieve interpreter should
              assume that it last auto-replied to the sender of the
              email, or <spanx style="verb">null</spanx> if the Sieve
              interpreter should assume that it has not auto-replied
              to the sender.
              <vspace blankLines="1"/>
            </t>
          </list>
        </t>

        <t>The response has the following arguments: 

          <list style="symbols">
            <t>
              <spanx style="strong">accountId</spanx>:
              <spanx style="verb">Id</spanx>
              <vspace blankLines="1"/>
              The id of the account used for this call.
              <vspace blankLines="1"/>
            </t>
            <t>
              <spanx style="strong">completed</spanx>:
              <spanx style="verb">Id[Action[]]|null</spanx>
              <vspace blankLines="1"/>
              A map of the blob id to a set of
              <spanx style="emph">Action</spanx> types for each Email
              successfully processed by the script, or
              <spanx style="verb">null</spanx> if none.

              The <spanx style="emph">Action</spanx> data type is a
              tuple, represented as a JSON array containing two elements:
              <vspace blankLines="1"/>
              
              <list style="numbers">
                <t>
                  A <spanx style="verb">String</spanx>
                  <spanx style="strong">name</spanx> of the Sieve
                  action (e.g., "keep").
                  <vspace blankLines="1"/>
                </t>
                <t>
                  A <spanx style="verb">String[*]</spanx> object
                  containing named <spanx style="strong">arguments</spanx>
                  for that action (e.g., ":flags" or "mailbox").
                  <vspace blankLines="1"/>
                </t>
              </list>
            </t>
            <t>
              <spanx style="strong">notCompleted</spanx>:
              <spanx style="verb">Id[SetError]|null</spanx>
              <vspace blankLines="1"/>
              A map of the blob id to a SetError object for each Email
              that was not successfully processed by the script, or
              <spanx style="verb">null</spanx> if none.
              A "serverFail" SetError (see Section 3.6.2 of
              <xref target="RFC8620"/>) MUST be used to indicate a
              Sieve interpreter run-time error.
              <vspace blankLines="1"/>
            </t>
          </list>
        </t>

        <t>The following additional errors may be returned instead of
        the "SieveScript/test" response:

          <list style="symbols">
            <t>
              "blobNotFound": The script referenced by the blob id could
              not be found.
            </t>

            <t>
              "invalidScript": The referenced script is invalid
              (see <xref target="set"/>).
            </t>

            <t>
              "serverFail": The referenced script failed preparation to
              be executed for some other reason.
            </t>
          </list>
          <vspace blankLines="1"/>
        </t>

        <t>
          The name to use for each argument is a direct mapping of the
          argument names as given in the specification of each action.
          Tagged and optional arguments MUST use the name of the tag,
          minus the leading ":".
          Positional arguments MUST use the name of the
          argument inside of the angle brackets ("&lt;" and "&gt;") in
          the "Usage" line in the specification for the action.
        </t>

        <t>
          The JSON data type to use for each argument value is a
          direct mapping from its Sieve data type, per the following
          table:
        </t>

        <texttable>
          <ttcol align='center'>Sieve Type</ttcol>
          <ttcol align='center'>JSON Type</ttcol>
          <c>Number</c>
          <c>Number</c>
          <c>String</c>
          <c>String</c>
          <c>String List</c>
          <c>String[]</c>
          <c>no value</c>
          <c>Boolean (true)</c>
        </texttable>

        <t>
          Recommendations for constructing the list of arguments are
          as follows:

          <list style="symbols">
            <t>Tagged arguments SHOULD procede positional arguments.</t>

            <t>Optional arguments in which the value is supplied by
            the Sieve interpreter SHOULD be included (e.g., ":from" and
            ":subject" arguments to the
            <xref target="RFC5230">"vacation"</xref> action).</t>

            <t>Optional arguments in which the value is supplied by
            a Sieve variable SHOULD be included (e.g., "keep" or
            "fileinto" actions without an explicit ":flags" argument,
            but <xref target="RFC5232">"imap4flags"</xref> have been
            set on the internal variable).</t>

            <t>Optional arguments in which the value is the specfied
            default MAY be omitted.</t>

            <t>Tagged arguments that are only used to determine
            whether the action will be executed and have no impact on
            the result of the action MAY be omitted (e.g., ":days" and
            ":addresses" arguments to the vacation action).</t>
          </list>
        </t>

        <section title="Example">
<!--
          <t>
            The following is an example of a raw Sieve script and
            email and testing that script against the email.
            The example assumes that the script and email have already
            been uploaded and assigned blob ids of "B123" and "B456"
            respectively.
          </t>
-->
          <t>
            <figure>
	      <preamble>
                Assume that the following script has been uploaded and
                assigned blob id "B123".
              </preamble>
              <artwork><![CDATA[
require [ "imapflags", "editheader", "vacation", "fcc" ];
setflag "$SieveFiltered";
addheader :last "X-Sieve-Filtered" "yes";
vacation :days 3 :fcc "INBOX.Sent" :flags "\\Answered" text:
Gone fishing.
.
;
]]></artwork>
            </figure>
          </t>

          <t>
            <figure>
	      <preamble>
                Assume that the following email has been uploaded and
                assigned blob id "B456".
              </preamble>
              <artwork><![CDATA[
From: "Some Example Sender" <example@example.net>
To: test@example.com
Subject: test email
Date: Wed, 23 Sep 2020 12:11:11 -0500
MIME-Version: 1.0
Content-Type: text/plain; charset="UTF-8"

This is a test email.
]]></artwork>
            </figure>
          </t>

          <t>
            <figure>
	      <preamble>
                The following request executes the script against the
                email and provides envelope information for use by the
                "vacation" action.
              </preamble>
              <artwork><![CDATA[
{
  "using": [
    "urn:ietf:params:jmap:core",
    "urn:ietf:params:jmap:sieve",
    "urn:ietf:params:jmap:mail"
  ],
  "methodCalls": [
    [
      "SieveScript/test",
      {
        "scriptBlobId": "B123",
        "emailBlobIds": [
          "B456"
        ],
        "envelope": {
          "mailFrom": {
            "email": "example@example.net",
            "parameters": null
          },
          "rcptTo": [
            {
              "email": "test@example.com",
              "parameters": null
            }
          ]
        },
        "lastVacationResponse": null
      },
      "R1"
    ]
  ]
}
]]></artwork>
            </figure>
          </t>

          <t>
            <figure>
	      <preamble>
                The following response lists the actions that would be
                performed by the script.
              </preamble>
              <artwork><![CDATA[
{
  "methodResponses": [
    [
      "SieveScript/test",
      {
        "accountId": "test",
        "completed": {
          "B456": [
            [
              "addheader",
              {
                "last": true,
                "field-name": "X-Sieve-Filtered",
                "value": "yes"
              }
            ],
            [
              "vacation",
              {
                "fcc": "INBOX.Sent",
                "flags": [
                  "\\answered"
                ],
                "subject": "Auto: test email",
                "from": "test@example.com",
                "reason": "Gone fishing."
              }
            ],
            [
              "keep",
              {
                "flags": [
                  "$SieveFiltered"
                ]
              }
            ]
          ]
        },
        "notCompleted": null
      },
      "R1"
    ]
  ],
  "sessionState": "0"
}
]]></artwork>
            </figure>
          </t>
        </section> <!-- /test example -->

      </section> <!-- /test -->

    </section>


    <section title="Security Considerations" anchor="security">
      <t>All security considerations of <xref target="RFC8620">JMAP</xref>
      apply to this specification.
      </t>
    </section>

    <section title="IANA Considerations">

      <section title="JMAP Capability Registration for &quot;sieve&quot;">
        <t>IANA will register the "sieve" JMAP Capability as follows:
        </t>
        <t>Capability Name:
        <spanx style="verb">urn:ietf:params:jmap:sieve</spanx>
        </t>
        <t>Specification document: this document
        </t>
        <t>Intended use: common
        </t>
        <t>Change Controller: IETF
        </t>
        <t>Security and privacy considerations: this document,
        <xref target="security" />
        </t>
      </section>

      <section title="JMAP Error Codes Registry">
        <t>
          The following sub-section register several new error codes in the
          JMAP Error Codes registry, as defined in <xref target="RFC8620"/>.
        </t>

        <section title="scriptNameExists">
          <t>JMAP Error Code: scriptNameExists </t>
          <t>Intended use: common </t>
          <t>Change controller: IETF </t>
          <t>Reference: This document, <xref target="set"/> </t>
          <t>Description: The client tried to create a SieveScript
          with the same "name" property as an existing SieveScript and
          the "replaceOnCreate" argument was false.
          present.</t>
        </section>

        <section title="tooManyScripts">
          <t>JMAP Error Code: tooManyScripts </t>
          <t>Intended use: common </t>
          <t>Change controller: IETF </t>
          <t>Reference: This document, <xref target="set"/> </t>
          <t>Description: Creating the SieveScript would exceed the
          "maxNumberScripts" limit.</t>
        </section>

        <section title="invalidScript">
          <t>JMAP Error Code: invalidScript </t>
          <t>Intended use: common </t>
          <t>Change controller: IETF </t>
          <t>Reference: This document, <xref target="set"/> </t>
          <t>Description: The SieveScript violates the
          <xref 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.</t>
        </section>

        <section title="scriptIsActive">
          <t>JMAP Error Code: scriptIsActive </t>
          <t>Intended use: common </t>
          <t>Change controller: IETF </t>
          <t>Reference: This document, <xref target="set"/> </t>
          <t>Description: The client tried to destroy the active
          SieveScript, but the "OnSuccessActivateScript" argument was
          not present.</t>
        </section>
      </section>

    </section>

    <section title='Acknowledgments'>
      <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: Bron Gondwana, Alexey Melnikov, and
      Ricardo Signes.</t>
    </section>

  </middle>

  <back>
    <references title="Normative References">
      <?rfc include="http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"?>
      <?rfc include="http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"?>
      <?rfc include="http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8620.xml"?>
      <?rfc include="http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8621.xml"?>
      <?rfc include="http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.5228.xml"?>
      <?rfc include="http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.3986.xml"?>
      <?rfc include="http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.5435.xml"?>
      <?rfc include="http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.6134.xml"?>
      <?rfc include="http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.5804.xml"?>
      <?rfc include="http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8259.xml"?>
    </references>

    <references title="Informative References">
      <?rfc include="http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.5230.xml"?>
      <?rfc include="http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.5232.xml"?>
      <?rfc include="http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.5463.xml"?>
    </references>

    <section title="Change History (To be removed by RFC Editor before
                    publication)">
      <t>Changes since ietf-00:
      <list style='symbols'>
        <t>Specified that changes made by onSuccessActivateScript MUST
        be reported in the /set response as created and/or updated as
        appropriate.</t>
        <t>Reworked and specified more of the /test response based on
        implementation experience.</t>
      </list>
      </t>

      <t>Changes since murchison-01:
      <list style='symbols'>
        <t>Explicitly stated that Sieve capability strings are
        case-sensitive.</t>
        <t>errorDescription is now String|null.</t>
        <t>Added /query method.</t>
        <t>Added /test method.</t>
      </list>
      </t>

      <t>Changes since murchison-00:
      <list style='symbols'>
        <t>Added IANA registration for "scriptIsActive" JMAP error code.</t>

        <t>Added open issue about /set{create} with an existing script name.</t>
      </list>
      </t>
    </section>

  </back>
</rfc>
