Section 9. Formal Syntax

The following syntax specification uses the Augmented Backus-Naur
   Form (ABNF) notation as specified in [ABNF].
   In the case of alternative or optional rules in which a later rule
   overlaps an earlier rule, the rule that is listed earlier MUST take
   priority.  For example, "\Seen" when parsed as a flag is the \Seen
   flag name and not a flag-extension, even though "\Seen" can be parsed
   as a flag-extension.  Some, but not all, instances of this rule are
   noted below.
     Note: [ABNF] rules MUST be followed strictly; in particular:
   1.  Unless otherwise noted, all alphabetic characters are case
       insensitive.  The use of uppercase or lowercase characters to
       define token strings is for editorial clarity only.
       Implementations MUST accept these strings in a case-insensitive
       fashion.
   2.  In all cases, SP refers to exactly one space.  It is NOT
       permitted to substitute TAB, insert additional spaces, or
       otherwise treat SP as being equivalent to linear whitespace
       (LWSP).
   3.  The ASCII NUL character, %x00, MUST NOT be used anywhere, with
       the exception of the OCTET production.
   SP              = <Defined in RFC 5234>
   CTL             = <Defined in RFC 5234>
   CRLF            = <Defined in RFC 5234>
   ALPHA           = <Defined in RFC 5234>
   DIGIT           = <Defined in RFC 5234>
   DQUOTE          = <Defined in RFC 5234>
   OCTET           = <Defined in RFC 5234>
   address         = "(" addr-name SP addr-adl SP addr-mailbox SP
                     addr-host ")"
   addr-adl        = nstring
                       ; Holds route from [RFC5322] obs-route if
                       ; non-NIL
   addr-host       = nstring
                       ; NIL indicates [RFC5322] group syntax.
                       ; Otherwise, holds [RFC5322] domain name
   addr-mailbox    = nstring
                       ; NIL indicates end of [RFC5322] group; if
                       ; non-NIL and addr-host is NIL, holds
                       ; [RFC5322] group name.
                       ; Otherwise, holds [RFC5322] local-part
                       ; after removing [RFC5322] quoting
   addr-name       = nstring
                       ; If non-NIL, holds phrase from [RFC5322]
                       ; mailbox after removing [RFC5322] quoting
   append          = "APPEND" SP mailbox [SP flag-list] [SP date-time]
                     SP literal
   append-uid      = uniqueid
   astring         = 1*ASTRING-CHAR / string
   ASTRING-CHAR   = ATOM-CHAR / resp-specials
   atom            = 1*ATOM-CHAR
   ATOM-CHAR       = <any CHAR except atom-specials>
   atom-specials   = "(" / ")" / "{" / SP / CTL / list-wildcards /
                     quoted-specials / resp-specials
   authenticate    = "AUTHENTICATE" SP auth-type [SP initial-resp]
                     *(CRLF base64)
   auth-type       = atom
                       ; Authentication mechanism name, as defined by
                       ; [SASL], Section 7.1
   base64          = *(4base64-char) [base64-terminal]
   base64-char     = ALPHA / DIGIT / "+" / "/"
                       ; Case sensitive
   base64-terminal = (2base64-char "==") / (3base64-char "=")
   body            = "(" (body-type-1part / body-type-mpart) ")"
   body-extension  = nstring / number / number64 /
                      "(" body-extension *(SP body-extension) ")"
                       ; Future expansion.  Client implementations
                       ; MUST accept body-extension fields.  Server
                       ; implementations MUST NOT generate
                       ; body-extension fields except as defined by
                       ; future Standard or Standards Track
                       ; revisions of this specification.
   body-ext-1part  = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang
                     [SP body-fld-loc *(SP body-extension)]]]
                       ; MUST NOT be returned on non-extensible
                       ; "BODY" fetch
   body-ext-mpart  = body-fld-param [SP body-fld-dsp [SP body-fld-lang
                     [SP body-fld-loc *(SP body-extension)]]]
                       ; MUST NOT be returned on non-extensible
                       ; "BODY" fetch
   body-fields     = body-fld-param SP body-fld-id SP body-fld-desc SP
                     body-fld-enc SP body-fld-octets
   body-fld-desc   = nstring
   body-fld-dsp    = "(" string SP body-fld-param ")" / nil
   body-fld-enc    = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/
                     "QUOTED-PRINTABLE") DQUOTE) / string
                     ; Content-Transfer-Encoding header field value.
                     ; Defaults to "7BIT" (as per RFC 2045)
                     ; if not present in the body part.
   body-fld-id     = nstring
   body-fld-lang   = nstring / "(" string *(SP string) ")"
   body-fld-loc    = nstring
   body-fld-lines  = number64
   body-fld-md5    = nstring
   body-fld-octets = number
   body-fld-param  = "(" string SP string *(SP string SP string) ")" /
                     nil
   body-type-1part = (body-type-basic / body-type-msg / body-type-text)
                     [SP body-ext-1part]
   body-type-basic = media-basic SP body-fields
                       ; MESSAGE subtype MUST NOT be "RFC822" or
                       ; "GLOBAL"
   body-type-mpart = 1*body SP media-subtype
                     [SP body-ext-mpart]
                       ; MULTIPART body part
   body-type-msg   = media-message SP body-fields SP envelope
                     SP body SP body-fld-lines
   body-type-text  = media-text SP body-fields SP body-fld-lines
   capability      = ("AUTH=" auth-type) / atom
                       ; New capabilities SHOULD be
                       ; registered with IANA using the
                       ; RFC Required policy, i.e., in
                       ; a Standards Track, an Experimental,
                       ; or an Informational RFC.
   capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev2"
                     *(SP capability)
                       ; See Section 6.1.1 for information about
                       ; required security-related capabilities.
                       ; Servers that offer RFC 1730 compatibility MUST
                       ; list "IMAP4" as the first capability.
                       ; Servers that offer RFC 3501 compatibility MUST
                       ; list "IMAP4rev1" as one of the capabilities.
   CHAR            = <defined in [ABNF]>
   CHAR8           = %x01-ff
                       ; any OCTET except NUL, %x00
   charset         = atom / quoted
   childinfo-extended-item =  "CHILDINFO" SP "("
               list-select-base-opt-quoted
               *(SP list-select-base-opt-quoted) ")"
               ; Extended data item (mbox-list-extended-item)
               ; returned when the RECURSIVEMATCH
               ; selection option is specified.
               ; Note 1: the CHILDINFO extended data item tag can be
               ; returned with or without surrounding quotes, as per
               ; mbox-list-extended-item-tag production.
               ; Note 2: The selection options are always returned
               ; quoted, unlike their specification in
               ; the extended LIST command.
   child-mbox-flag =  "\HasChildren" / "\HasNoChildren"
               ; attributes for the CHILDREN return option, at most
               ; one possible per LIST response
   command         = tag SP (command-any / command-auth /
                     command-nonauth / command-select) CRLF
                       ; Modal based on state
   command-any     = "CAPABILITY" / "LOGOUT" / "NOOP"
                       ; Valid in all states
   command-auth    = append / create / delete / enable / examine /
                     list / namespace-command / rename /
                     select / status / subscribe / unsubscribe /
                     idle
                       ; Valid only in Authenticated or Selected state
   command-nonauth = login / authenticate / "STARTTLS"
                       ; Valid only when in Not Authenticated state
   command-select  = "CLOSE" / "UNSELECT" / "EXPUNGE" / copy /
                      move / fetch / store / search / uid
                       ; Valid only when in Selected state
   continue-req    = "+" SP (resp-text / base64) CRLF
   copy            = "COPY" SP sequence-set SP mailbox
   create          = "CREATE" SP mailbox
                       ; Use of INBOX gives a NO error
   date            = date-text / DQUOTE date-text DQUOTE
   date-day        = 1*2DIGIT
                       ; Day of month
   date-day-fixed  = (SP DIGIT) / 2DIGIT
                       ; Fixed-format version of date-day
   date-month      = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" /
                     "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
   date-text       = date-day "-" date-month "-" date-year
   date-year       = 4DIGIT
   date-time       = DQUOTE date-day-fixed "-" date-month "-" date-year
                     SP time SP zone DQUOTE
   delete          = "DELETE" SP mailbox
                       ; Use of INBOX gives a NO error
   digit-nz        = %x31-39
                       ; 1-9
   eitem-standard-tag =  atom
               ; a tag for LIST extended data item defined in a Standard
               ; Track or Experimental RFC.
   eitem-vendor-tag =  vendor-token "-" atom
               ; a vendor-specific tag for LIST extended data item
   enable          = "ENABLE" 1*(SP capability)
   enable-data     = "ENABLED" *(SP capability)
   envelope        = "(" env-date SP env-subject SP env-from SP
                     env-sender SP env-reply-to SP env-to SP env-cc SP
                     env-bcc SP env-in-reply-to SP env-message-id ")"
   env-bcc         = "(" 1*address ")" / nil
   env-cc          = "(" 1*address ")" / nil
   env-date        = nstring
   env-from        = "(" 1*address ")" / nil
   env-in-reply-to = nstring
   env-message-id  = nstring
   env-reply-to    = "(" 1*address ")" / nil
   env-sender      = "(" 1*address ")" / nil
   env-subject     = nstring
   env-to          = "(" 1*address ")" / nil
   esearch-response  = "ESEARCH" [search-correlator] [SP "UID"]
                       *(SP search-return-data)
                     ; ESEARCH response replaces SEARCH response
                     ; from IMAP4rev1.
   examine         = "EXAMINE" SP mailbox
   fetch           = "FETCH" SP sequence-set SP (
                     "ALL" / "FULL" / "FAST" /
                     fetch-att / "(" fetch-att *(SP fetch-att) ")")
   fetch-att       = "ENVELOPE" / "FLAGS" / "INTERNALDATE" /
                     "RFC822.SIZE" /
                     "BODY" ["STRUCTURE"] / "UID" /
                     "BODY" section [partial] /
                     "BODY.PEEK" section [partial] /
                     "BINARY" [".PEEK"] section-binary [partial] /
                     "BINARY.SIZE" section-binary
   flag            = "\Answered" / "\Flagged" / "\Deleted" /
                     "\Seen" / "\Draft" / flag-keyword / flag-extension
                       ; Does not include "\Recent"
   flag-extension  = "\" atom
                       ; Future expansion.  Client implementations
                       ; MUST accept flag-extension flags.  Server
                       ; implementations MUST NOT generate
                       ; flag-extension flags except as defined by
                       ; a future Standard or Standards Track
                       ; revisions of this specification.
                       ; "\Recent" was defined in RFC 3501
                       ; and is now deprecated.
   flag-fetch      = flag / obsolete-flag-recent
   flag-keyword    = "$MDNSent" / "$Forwarded" / "$Junk" /
                     "$NotJunk" / "$Phishing" / atom
   flag-list       = "(" [flag *(SP flag)] ")"
   flag-perm       = flag / "\*"
   greeting        = "*" SP (resp-cond-auth / resp-cond-bye) CRLF
   header-fld-name = astring
   header-list     = "(" header-fld-name *(SP header-fld-name) ")"
   idle            = "IDLE" CRLF "DONE"
   initial-resp    =  (base64 / "=")
                      ; "initial response" defined in
                      ; Section 4 of [SASL]
   list            = "LIST" [SP list-select-opts] SP
                     mailbox SP mbox-or-pat
                     [SP list-return-opts]
   list-mailbox    = 1*list-char / string
   list-char       = ATOM-CHAR / list-wildcards / resp-specials
   list-return-opt   =  return-option
                        ; Note that return-option is the ABNF
                        ; non-terminal used by RFC 5258
   list-return-opts =  "RETURN" SP
               "(" [list-return-opt *(SP list-return-opt)] ")"
               ; list return options, e.g., CHILDREN
   list-select-base-opt =  "SUBSCRIBED" / option-extension
               ; options that can be used by themselves
   list-select-base-opt-quoted =  DQUOTE list-select-base-opt DQUOTE
   list-select-independent-opt =  "REMOTE" / option-extension
               ; options that do not syntactically interact with
               ; other options
   list-select-mod-opt =  "RECURSIVEMATCH" / option-extension
               ; options that require a list-select-base-opt
               ; to also be present
   list-select-opt =  list-select-base-opt / list-select-independent-opt
                      / list-select-mod-opt
   list-select-opts =  "(" [
                      (*(list-select-opt SP) list-select-base-opt
                      *(SP list-select-opt))
                     / (list-select-independent-opt
                      *(SP list-select-independent-opt))
                        ] ")"
               ; Any number of options may be in any order.
               ; If a list-select-mod-opt appears, then a
               ; list-select-base-opt must also appear.
               ; This allows these:
               ; ()
               ; (REMOTE)
               ; (SUBSCRIBED)
               ; (SUBSCRIBED REMOTE)
               ; (SUBSCRIBED RECURSIVEMATCH)
               ; (SUBSCRIBED REMOTE RECURSIVEMATCH)
               ; But does NOT allow these:
               ; (RECURSIVEMATCH)
               ; (REMOTE RECURSIVEMATCH)
   list-wildcards  = "%" / "*"
   literal         = "{" number64 ["+"] "}" CRLF *CHAR8
                       ; <number64> represents the number of CHAR8s.
                       ; A non-synchronizing literal is distinguished
                       ; from a synchronizing literal by the presence of
                       ; "+" before the closing "}".
                       ; Non-synchronizing literals are not allowed when
                       ; sent from server to the client.
   literal8        =  "~{" number64 "}" CRLF *OCTET
                       ; <number64> represents the number of OCTETs
                       ; in the response string.
   login           = "LOGIN" SP userid SP password
   mailbox         = "INBOX" / astring
                       ; INBOX is case insensitive.  All case variants
                       ; of INBOX (e.g., "iNbOx") MUST be interpreted as
                       ; INBOX, not as an astring.  An astring that
                       ; consists of the case-insensitive sequence
                       ; "I" "N" "B" "O" "X" is considered
                       ; to be an INBOX and not an astring.
                       ; Refer to Section 5.1 for further
                       ; semantic details of mailbox names.
   mailbox-data    =  "FLAGS" SP flag-list / "LIST" SP mailbox-list /
                      esearch-response /
                      "STATUS" SP mailbox SP "(" [status-att-list] ")" /
                      number SP "EXISTS" / namespace-response /
                      obsolete-search-response /
                      obsolete-recent-response
                       ; obsolete-search-response and
                       ; obsolete-recent-response can only be returned
                       ; by servers that support both IMAPrev1
                       ; and IMAPrev2.
   mailbox-list    = "(" [mbx-list-flags] ")" SP
                      (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox
                      [SP mbox-list-extended]
               ; This is the list information pointed to by the ABNF
               ; item "mailbox-data", which is defined above
   mbox-list-extended =  "(" [mbox-list-extended-item
                         *(SP mbox-list-extended-item)] ")"
   mbox-list-extended-item = mbox-list-extended-item-tag SP
                              tagged-ext-val
   mbox-list-extended-item-tag = astring
                  ; The content MUST conform to either
                  ; "eitem-vendor-tag" or "eitem-standard-tag"
                  ; ABNF productions.
   mbox-or-pat =  list-mailbox / patterns
   mbx-list-flags  = *(mbx-list-oflag SP) mbx-list-sflag
                     *(SP mbx-list-oflag) /
                     mbx-list-oflag *(SP mbx-list-oflag)
   mbx-list-oflag  = "\Noinferiors" / child-mbox-flag /
                     "\Subscribed" / "\Remote" / flag-extension
                  ; Other flags; multiple from this list are
                  ; possible per LIST response, but each flag
                  ; can only appear once per LIST response
   mbx-list-sflag  = "\NonExistent" / "\Noselect" / "\Marked" /
                     "\Unmarked"
                  ; Selectability flags; only one per LIST response
   media-basic     = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" /
                     "FONT" / "MESSAGE" / "MODEL" / "VIDEO" ) DQUOTE)
                     / string)
                     SP media-subtype
                       ; FONT defined in [RFC8081].
                       ; MODEL defined in [RFC2077].
                       ; Other top-level media types
                       ; are defined in [MIME-IMT].
   media-message   = DQUOTE "MESSAGE" DQUOTE SP
                     DQUOTE ("RFC822" / "GLOBAL") DQUOTE
                       ; Defined in [MIME-IMT]
   media-subtype   = string
                       ; Defined in [MIME-IMT]
   media-text      = DQUOTE "TEXT" DQUOTE SP media-subtype
                       ; Defined in [MIME-IMT]
   message-data    = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att))
   move            = "MOVE" SP sequence-set SP mailbox
   msg-att         = "(" (msg-att-dynamic / msg-att-static)
                      *(SP (msg-att-dynamic / msg-att-static)) ")"
   msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")"
                       ; MAY change for a message
   msg-att-static  = "ENVELOPE" SP envelope /
                     "INTERNALDATE" SP date-time /
                     "RFC822.SIZE" SP number64 /
                     "BODY" ["STRUCTURE"] SP body /
                     "BODY" section ["<" number ">"] SP nstring /
                     "BINARY" section-binary SP (nstring / literal8) /
                     "BINARY.SIZE" section-binary SP number /
                     "UID" SP uniqueid
                       ; MUST NOT change for a message
   name-component  = 1*UTF8-CHAR
                       ; MUST NOT contain ".", "/", "%", or "*"
   namespace         = nil / "(" 1*namespace-descr ")"
   namespace-command = "NAMESPACE"
   namespace-descr   = "(" string SP
                          (DQUOTE QUOTED-CHAR DQUOTE / nil)
                           [namespace-response-extensions] ")"
   namespace-response-extensions = *namespace-response-extension
   namespace-response-extension = SP string SP
                     "(" string *(SP string) ")"
   namespace-response = "NAMESPACE" SP namespace
                         SP namespace SP namespace
                    ; The first Namespace is the Personal Namespace(s).
                    ; The second Namespace is the Other Users'
                    ; Namespace(s).
                    ; The third Namespace is the Shared Namespace(s).
   nil             = "NIL"
   nstring         = string / nil
   number          = 1*DIGIT
                       ; Unsigned 32-bit integer
                       ; (0 <= n < 4,294,967,296)
   number64        = 1*DIGIT
                       ; Unsigned 63-bit integer
                       ; (0 <= n <= 9,223,372,036,854,775,807)
   nz-number       = digit-nz *DIGIT
                       ; Non-zero unsigned 32-bit integer
                       ; (0 < n < 4,294,967,296)
   nz-number64     = digit-nz *DIGIT
                       ; Unsigned 63-bit integer
                       ; (0 < n <= 9,223,372,036,854,775,807)
   obsolete-flag-recent = "\Recent"
   obsolete-recent-response = number SP "RECENT"
   obsolete-search-response = "SEARCH" *(SP nz-number)
   oldname-extended-item =  "OLDNAME" SP "(" mailbox ")"
                       ; Extended data item (mbox-list-extended-item)
                       ; returned in a LIST response when a mailbox is
                       ; renamed or deleted. Also returned when
                       ; the server canonicalized the provided mailbox
                       ; name.
                       ; Note 1: the OLDNAME tag can be returned
                       ; with or without surrounding quotes, as per
                       ; mbox-list-extended-item-tag production.
   option-extension = (option-standard-tag / option-vendor-tag)
                      [SP option-value]
   option-standard-tag =  atom
                  ; an option defined in a Standards Track or
                  ; Experimental RFC
   option-val-comp =  astring /
                      option-val-comp *(SP option-val-comp) /
                      "(" option-val-comp ")"
   option-value =  "(" option-val-comp ")"
   option-vendor-tag =  vendor-token "-" atom
                  ; a vendor-specific option, non-standard
   partial-range    = number64 ["." nz-number64]
                       ; Copied from RFC 5092 (IMAP URL)
                       ; and updated to support 64-bit sizes.
   partial         = "<" number64 "." nz-number64 ">"
                       ; Partial FETCH request. 0-based offset of
                       ; the first octet, followed by the number of
                       ; octets in the fragment.
   password        = astring
   patterns        = "(" list-mailbox ")"
                     ; [RFC5258] supports multiple patterns,
                     ; but this document only requires one
                     ; to be supported.
                     ; If the server is also implementing
                     ; [RFC5258], the "patterns" syntax from
                     ; that document must be followed.
   quoted          = DQUOTE *QUOTED-CHAR DQUOTE
   QUOTED-CHAR     = <any TEXT-CHAR except quoted-specials> /
                     "\" quoted-specials / UTF8-2 / UTF8-3 / UTF8-4
   quoted-specials = DQUOTE / "\"
   rename          = "RENAME" SP mailbox SP mailbox
                       ; Use of INBOX as a destination gives a NO error
   response        = *(continue-req / response-data) response-done
   response-data   = "*" SP (resp-cond-state / resp-cond-bye /
                     mailbox-data / message-data / capability-data /
                     enable-data) CRLF
   response-done   = response-tagged / response-fatal
   response-fatal  = "*" SP resp-cond-bye CRLF
                       ; Server closes connection immediately
   response-tagged = tag SP resp-cond-state CRLF
   resp-code-apnd  = "APPENDUID" SP nz-number SP append-uid
   resp-code-copy  = "COPYUID" SP nz-number SP uid-set SP uid-set
   resp-cond-auth  = ("OK" / "PREAUTH") SP resp-text
                       ; Authentication condition
   resp-cond-bye   = "BYE" SP resp-text
   resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text
                       ; Status condition
   resp-specials   = "]"
   resp-text       = ["[" resp-text-code "]" SP] [text]
   resp-text-code  = "ALERT" /
                     "BADCHARSET" [SP "(" charset *(SP charset) ")" ] /
                     capability-data / "PARSE" /
                     "PERMANENTFLAGS" SP
                         "(" [flag-perm *(SP flag-perm)] ")" /
                     "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
                     "UIDNEXT" SP nz-number /
                     "UIDVALIDITY" SP nz-number /
                     resp-code-apnd / resp-code-copy / "UIDNOTSTICKY" /
                     "UNAVAILABLE" / "AUTHENTICATIONFAILED" /
                     "AUTHORIZATIONFAILED" / "EXPIRED" /
                     "PRIVACYREQUIRED" / "CONTACTADMIN" / "NOPERM" /
                     "INUSE" / "EXPUNGEISSUED" / "CORRUPTION" /
                     "SERVERBUG" / "CLIENTBUG" / "CANNOT" /
                     "LIMIT" / "OVERQUOTA" / "ALREADYEXISTS" /
                     "NONEXISTENT" / "NOTSAVED" / "HASCHILDREN" /
                     "CLOSED" /
                     "UNKNOWN-CTE" /
                     atom [SP 1*<any TEXT-CHAR except "]">]
   return-option   = "SUBSCRIBED" / "CHILDREN" / status-option /
                      option-extension
   search          = "SEARCH" [search-return-opts]
                     SP search-program
   search-correlator  = SP "(" "TAG" SP tag-string ")"
   search-key      = "ALL" / "ANSWERED" / "BCC" SP astring /
                     "BEFORE" SP date / "BODY" SP astring /
                     "CC" SP astring / "DELETED" / "FLAGGED" /
                     "FROM" SP astring / "KEYWORD" SP flag-keyword /
                     "ON" SP date / "SEEN" /
                     "SINCE" SP date / "SUBJECT" SP astring /
                     "TEXT" SP astring / "TO" SP astring /
                     "UNANSWERED" / "UNDELETED" / "UNFLAGGED" /
                     "UNKEYWORD" SP flag-keyword / "UNSEEN" /
                       ; Above this line were in [IMAP2]
                     "DRAFT" / "HEADER" SP header-fld-name SP astring /
                     "LARGER" SP number64 / "NOT" SP search-key /
                     "OR" SP search-key SP search-key /
                     "SENTBEFORE" SP date / "SENTON" SP date /
                     "SENTSINCE" SP date / "SMALLER" SP number64 /
                     "UID" SP sequence-set / "UNDRAFT" / sequence-set /
                     "(" search-key *(SP search-key) ")"
   search-modifier-name = tagged-ext-label
   search-mod-params = tagged-ext-val
                     ; This non-terminal shows recommended syntax
                     ; for future extensions.
   search-program     = ["CHARSET" SP charset SP]
                       search-key *(SP search-key)
                       ; CHARSET argument to SEARCH MUST be
                       ; registered with IANA.
   search-ret-data-ext = search-modifier-name SP search-return-value
                       ; Note that not every SEARCH return option
                       ; is required to have the corresponding
                       ; ESEARCH return data.
   search-return-data = "MIN" SP nz-number /
                       "MAX" SP nz-number /
                       "ALL" SP sequence-set /
                       "COUNT" SP number /
                       search-ret-data-ext
                       ; All return data items conform to
                       ; search-ret-data-ext syntax.
                       ; Note that "$" marker is not allowed
                       ; after the ALL return data item.
   search-return-opts = SP "RETURN" SP "(" [search-return-opt
                       *(SP search-return-opt)] ")"
   search-return-opt  = "MIN" / "MAX" / "ALL" / "COUNT" /
                        "SAVE" /
                        search-ret-opt-ext
                       ; conforms to generic search-ret-opt-ext
                       ; syntax
   search-ret-opt-ext = search-modifier-name [SP search-mod-params]
   search-return-value = tagged-ext-val
                       ; Data for the returned search option.
                       ; A single "nz-number"/"number"/"number64" value
                       ; can be returned as an atom (i.e., without
                       ; quoting).  A sequence-set can be returned
                       ; as an atom as well.
   section         = "[" [section-spec] "]"
   section-binary  = "[" [section-part] "]"
   section-msgtext = "HEADER" /
                     "HEADER.FIELDS" [".NOT"] SP header-list /
                     "TEXT"
                       ; top-level or MESSAGE/RFC822 or
                       ; MESSAGE/GLOBAL part
   section-part    = nz-number *("." nz-number)
                       ; body part reference.
                       ; Allows for accessing nested body parts.
   section-spec    = section-msgtext / (section-part ["." section-text])
   section-text    = section-msgtext / "MIME"
                       ; text other than actual body part (headers,
                       ; etc.)
   select          = "SELECT" SP mailbox
   seq-number      = nz-number / "*"
                       ; message sequence number (COPY, FETCH, STORE
                       ; commands) or unique identifier (UID COPY,
                       ; UID FETCH, UID STORE commands).
                       ; * represents the largest number in use.  In
                       ; the case of message sequence numbers, it is
                       ; the number of messages in a non-empty mailbox.
                       ; In the case of unique identifiers, it is the
                       ; unique identifier of the last message in the
                       ; mailbox or, if the mailbox is empty, the
                       ; mailbox's current UIDNEXT value.
                       ; The server should respond with a tagged BAD
                       ; response to a command that uses a message
                       ; sequence number greater than the number of
                       ; messages in the selected mailbox.  This
                       ; includes "*" if the selected mailbox is empty.
   seq-range       = seq-number ":" seq-number
                       ; two seq-number values and all values between
                       ; these two regardless of order.
                       ; Example: 2:4 and 4:2 are equivalent and
                       ; indicate values 2, 3, and 4.
                       ; Example: a unique identifier sequence range of
                       ; 3291:* includes the UID of the last message in
                       ; the mailbox, even if that value is less than
                       ; 3291.
   sequence-set    = (seq-number / seq-range) ["," sequence-set]
                       ; set of seq-number values, regardless of order.
                       ; Servers MAY coalesce overlaps and/or execute
                       ; the sequence in any order.
                       ; Example: a message sequence number set of
                       ; 2,4:7,9,12:* for a mailbox with 15 messages is
                       ; equivalent to 2,4,5,6,7,9,12,13,14,15
                       ; Example: a message sequence number set of
                       ; *:4,5:7 for a mailbox with 10 messages is
                       ; equivalent to 10,9,8,7,6,5,4,5,6,7 and MAY
                       ; be reordered and overlap coalesced to be
                       ; 4,5,6,7,8,9,10.
   sequence-set    =/ seq-last-command
                       ; Allow for "result of the last command"
                       ; indicator.
   seq-last-command   = "$"
   status          = "STATUS" SP mailbox SP
                     "(" status-att *(SP status-att) ")"
   status-att      = "MESSAGES" / "UIDNEXT" / "UIDVALIDITY" /
                     "UNSEEN" / "DELETED" / "SIZE"
   status-att-val  = ("MESSAGES" SP number) /
                     ("UIDNEXT" SP nz-number) /
                     ("UIDVALIDITY" SP nz-number) /
                     ("UNSEEN" SP number) /
                     ("DELETED" SP number) /
                     ("SIZE" SP number64)
                       ; Extensions to the STATUS responses
                       ; should extend this production.
                       ; Extensions should use the generic
                       ; syntax defined by tagged-ext.
   status-att-list =  status-att-val *(SP status-att-val)
   status-option = "STATUS" SP "(" status-att *(SP status-att) ")"
                       ; This ABNF production complies with
                       ; <option-extension> syntax.
   store           = "STORE" SP sequence-set SP store-att-flags
   store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP
                     (flag-list / (flag *(SP flag)))
   string          = quoted / literal
   subscribe       = "SUBSCRIBE" SP mailbox
   tag             = 1*<any ASTRING-CHAR except "+">
   tag-string      = astring
                     ; <tag> represented as <astring>
   tagged-ext-label    = tagged-label-fchar *tagged-label-char
                         ; Is a valid RFC 3501 "atom".
   tagged-label-fchar  = ALPHA / "-" / "_" / "."
   tagged-label-char   = tagged-label-fchar / DIGIT / ":"
   tagged-ext-comp     = astring /
                         tagged-ext-comp *(SP tagged-ext-comp) /
                         "(" tagged-ext-comp ")"
                         ; Extensions that follow this general
                         ; syntax should use nstring instead of
                         ; astring when appropriate in the context
                         ; of the extension.
                         ; Note that a message set or a "number"
                         ; can always be represented as an "atom".
                         ; A URL should be represented as
                         ; a "quoted" string.
   tagged-ext-simple   = sequence-set / number / number64
   tagged-ext-val      = tagged-ext-simple /
                         "(" [tagged-ext-comp] ")"
   text            = 1*(TEXT-CHAR / UTF8-2 / UTF8-3 / UTF8-4)
                       ; Non-ASCII text can only be returned
                       ; after ENABLE IMAP4rev2 command
   TEXT-CHAR       = <any CHAR except CR and LF>
   time            = 2DIGIT ":" 2DIGIT ":" 2DIGIT
                       ; Hours minutes seconds
   uid             = "UID" SP
                     (copy / move / fetch / search / store /
                      uid-expunge)
                       ; Unique identifiers used instead of message
                       ; sequence numbers
   uid-expunge     = "EXPUNGE" SP sequence-set
                       ; Unique identifiers used instead of message
                       ; sequence numbers
   uid-set         = (uniqueid / uid-range) *("," uid-set)
   uid-range       = (uniqueid ":" uniqueid)
                       ; two uniqueid values and all values
                       ; between these two regardless of order.
                       ; Example: 2:4 and 4:2 are equivalent.
   uniqueid        = nz-number
                       ; Strictly ascending
   unsubscribe     = "UNSUBSCRIBE" SP mailbox
   userid          = astring
   UTF8-CHAR       = <Defined in Section 4 of RFC 3629>
   UTF8-2          = <Defined in Section 4 of RFC 3629>
   UTF8-3          = <Defined in Section 4 of RFC 3629>
   UTF8-4          = <Defined in Section 4 of RFC 3629>
   vendor-token    = "vendor." name-component
                       ; Definition copied from RFC 2244.
                       ; MUST be registered with IANA
   zone            = ("+" / "-") 4DIGIT
                       ; Signed four-digit value of hhmm representing
                       ; hours and minutes east of Greenwich (that is,
                       ; the amount that the given time differs from
                       ; Universal Time).  Subtracting the timezone
                       ; from the given time will give the UT form.
                       ; The Universal Time zone is "+0000".