| 
9. Formal Syntax
   The following syntax specification uses the augmented Backus-Naur
   Form (BNF) notation as specified in [RFC-822] with one exception; the
   delimiter used with the "#" construct is a single space (SPACE) and
   not one or more commas.
   In the case of alternative or optional rules in which a later rule
   overlaps an earlier rule, the rule which 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" could be
   parsed as a flag_extension.  Some, but not all, instances of this
   rule are noted below.
   Except as noted otherwise, all alphabetic characters are case-
   insensitive.  The use of upper or lower case characters to define
   token strings is for editorial clarity only.  Implementations MUST
   accept these strings in a case-insensitive fashion.
address         ::= "(" addr_name SPACE addr_adl SPACE addr_mailbox
                    SPACE addr_host ")"
addr_adl        ::= nstring
                    ;; Holds route from [RFC-822] route-addr if
                    ;; non-NIL
addr_host       ::= nstring
                    ;; NIL indicates [RFC-822] group syntax.
                    ;; Otherwise, holds [RFC-822] domain name
addr_mailbox    ::= nstring
                    ;; NIL indicates end of [RFC-822] group; if
                    ;; non-NIL and addr_host is NIL, holds
                    ;; [RFC-822] group name.
                    ;; Otherwise, holds [RFC-822] local-part
addr_name       ::= nstring
                    ;; Holds phrase from [RFC-822] mailbox if
                    ;; non-NIL
alpha           ::= "A" / "B" / "C" / "D" / "E" / "F" / "G" / "H" /
                    "I" / "J" / "K" / "L" / "M" / "N" / "O" / "P" /
                    "Q" / "R" / "S" / "T" / "U" / "V" / "W" / "X" /
                    "Y" / "Z" /
                    "a" / "b" / "c" / "d" / "e" / "f" / "g" / "h" /
                    "i" / "j" / "k" / "l" / "m" / "n" / "o" / "p" /
                    "q" / "r" / "s" / "t" / "u" / "v" / "w" / "x" /
                    "y" / "z"
                    ;; Case-sensitive
append          ::= "APPEND" SPACE mailbox [SPACE flag_list]
                    [SPACE date_time] SPACE literal
astring         ::= atom / string
atom            ::= 1*ATOM_CHAR
ATOM_CHAR       ::= 
atom_specials   ::= "(" / ")" / "{" / SPACE / CTL / list_wildcards /
                    quoted_specials
authenticate    ::= "AUTHENTICATE" SPACE auth_type *(CRLF base64)
auth_type       ::= atom
                    ;; Defined by [IMAP-AUTH]
base64          ::= *(4base64_char) [base64_terminal]
base64_char     ::= alpha / digit / "+" / "/"
base64_terminal ::= (2base64_char "==") / (3base64_char "=")
body            ::= "(" body_type_1part / body_type_mpart ")"
body_extension  ::= nstring / number / "(" 1#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 [SPACE body_fld_dsp
                    [SPACE body_fld_lang
                    [SPACE 1#body_extension]]]
                    ;; MUST NOT be returned on non-extensible
                    ;; "BODY" fetch
body_ext_mpart  ::= body_fld_param
                    [SPACE body_fld_dsp SPACE body_fld_lang
                    [SPACE 1#body_extension]]
                    ;; MUST NOT be returned on non-extensible
                    ;; "BODY" fetch
body_fields     ::= body_fld_param SPACE body_fld_id SPACE
                    body_fld_desc SPACE body_fld_enc SPACE
                    body_fld_octets
body_fld_desc   ::= nstring
body_fld_dsp    ::= "(" string SPACE body_fld_param ")" / nil
body_fld_enc    ::= (<"> ("7BIT" / "8BIT" / "BINARY" / "BASE64"/
                    "QUOTED-PRINTABLE") <">) / string
body_fld_id     ::= nstring
body_fld_lang   ::= nstring / "(" 1#string ")"
body_fld_lines  ::= number
body_fld_md5    ::= nstring
body_fld_octets ::= number
body_fld_param  ::= "(" 1#(string SPACE string) ")" / nil
body_type_1part ::= (body_type_basic / body_type_msg / body_type_text)
                    [SPACE body_ext_1part]
body_type_basic ::= media_basic SPACE body_fields
                    ;; MESSAGE subtype MUST NOT be "RFC822"
body_type_mpart ::= 1*body SPACE media_subtype
                    [SPACE body_ext_mpart]
body_type_msg   ::= media_message SPACE body_fields SPACE envelope
                    SPACE body SPACE body_fld_lines
body_type_text  ::= media_text SPACE body_fields SPACE body_fld_lines
capability      ::= "AUTH=" auth_type / atom
                    ;; New capabilities MUST begin with "X" or be
                    ;; registered with IANA as standard or
                    ;; standards-track
capability_data ::= "CAPABILITY" SPACE [1#capability SPACE] "IMAP4rev1"
                    [SPACE 1#capability]
                    ;; IMAP4rev1 servers which offer RFC 1730
                    ;; compatibility MUST list "IMAP4" as the first
                    ;; capability.
CHAR            ::= 
CHAR8           ::= 
command         ::= tag SPACE (command_any / command_auth /
                    command_nonauth / command_select) CRLF
                    ;; Modal based on state
command_any     ::= "CAPABILITY" / "LOGOUT" / "NOOP" / x_command
                    ;; Valid in all states
command_auth    ::= append / create / delete / examine / list / lsub /
                    rename / select / status / subscribe / unsubscribe
                    ;; Valid only in Authenticated or Selected state
command_nonauth ::= login / authenticate
                    ;; Valid only when in Non-Authenticated state
command_select  ::= "CHECK" / "CLOSE" / "EXPUNGE" /
                     copy / fetch / store / uid / search
                    ;; Valid only when in Selected state
continue_req    ::= "+" SPACE (resp_text / base64)
copy            ::= "COPY" SPACE set SPACE mailbox
CR              ::= 
create          ::= "CREATE" SPACE mailbox
                    ;; Use of INBOX gives a NO error
CRLF            ::= CR LF
CTL             ::= 
date            ::= date_text / <"> date_text <">
date_day        ::= 1*2digit
                    ;; Day of month
date_day_fixed  ::= (SPACE 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       ::= <"> date_day_fixed "-" date_month "-" date_year
                    SPACE time SPACE zone <">
delete          ::= "DELETE" SPACE mailbox
                    ;; Use of INBOX gives a NO error
digit           ::= "0" / digit_nz
digit_nz        ::= "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" /
                    "9"
envelope        ::= "(" env_date SPACE env_subject SPACE env_from
                    SPACE env_sender SPACE env_reply_to SPACE env_to
                    SPACE env_cc SPACE env_bcc SPACE env_in_reply_to
                    SPACE 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
examine         ::= "EXAMINE" SPACE mailbox
fetch           ::= "FETCH" SPACE set SPACE ("ALL" / "FULL" /
                    "FAST" / fetch_att / "(" 1#fetch_att ")")
fetch_att       ::= "ENVELOPE" / "FLAGS" / "INTERNALDATE" /
                    "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] /
                    "BODY" ["STRUCTURE"] / "UID" /
                    "BODY" [".PEEK"] section
                    ["<" number "." nz_number ">"]
flag            ::= "\Answered" / "\Flagged" / "\Deleted" /
                    "\Seen" / "\Draft" / flag_keyword / flag_extension
flag_extension  ::= "\" atom
                    ;; Future expansion.  Client implementations
                    ;; MUST accept flag_extension flags.  Server
                    ;; implementations MUST NOT generate
                    ;; flag_extension flags except as defined by
                    ;; future standard or standards-track
                    ;; revisions of this specification.
flag_keyword    ::= atom
flag_list       ::= "(" #flag ")"
greeting        ::= "*" SPACE (resp_cond_auth / resp_cond_bye) CRLF
header_fld_name ::= astring
header_list     ::= "(" 1#header_fld_name ")"
LF              ::= 
list            ::= "LIST" SPACE mailbox SPACE list_mailbox
list_mailbox    ::= 1*(ATOM_CHAR / list_wildcards) / string
list_wildcards  ::= "%" / "*"
literal         ::= "{" number "}" CRLF *CHAR8
                    ;; Number represents the number of CHAR8 octets
login           ::= "LOGIN" SPACE userid SPACE password
lsub            ::= "LSUB" SPACE mailbox SPACE list_mailbox
mailbox         ::= "INBOX" / astring
                    ;; INBOX is case-insensitive.  All case variants of
                    ;; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX
                    ;; not as an astring.  Refer to section 5.1 for
                    ;; further semantic details of mailbox names.
mailbox_data    ::=  "FLAGS" SPACE flag_list /
                     "LIST" SPACE mailbox_list /
                     "LSUB" SPACE mailbox_list /
                     "MAILBOX" SPACE text /
                     "SEARCH" [SPACE 1#nz_number] /
                     "STATUS" SPACE mailbox SPACE
                     "(" # QUOTED_CHAR <"> / nil) SPACE mailbox
media_basic     ::= (<"> ("APPLICATION" / "AUDIO" / "IMAGE" /
                    "MESSAGE" / "VIDEO") <">) / string)
                    SPACE media_subtype
                    ;; Defined in [MIME-IMT]
media_message   ::= <"> "MESSAGE" <"> SPACE <"> "RFC822" <">
                    ;; Defined in [MIME-IMT]
media_subtype   ::= string
                    ;; Defined in [MIME-IMT]
media_text      ::= <"> "TEXT" <"> SPACE media_subtype
                    ;; Defined in [MIME-IMT]
message_data    ::= nz_number SPACE ("EXPUNGE" /
                                    ("FETCH" SPACE msg_att))
msg_att         ::= "(" 1#("ENVELOPE" SPACE envelope /
                    "FLAGS" SPACE "(" #(flag / "\Recent") ")" /
                    "INTERNALDATE" SPACE date_time /
                    "RFC822" [".HEADER" / ".TEXT"] SPACE nstring /
                    "RFC822.SIZE" SPACE number /
                    "BODY" ["STRUCTURE"] SPACE body /
                    "BODY" section ["<" number ">"] SPACE nstring /
                    "UID" SPACE uniqueid) ")"
nil             ::= "NIL"
nstring         ::= string / nil
number          ::= 1*digit
                    ;; Unsigned 32-bit integer
                    ;; (0 <= n < 4,294,967,296)
nz_number       ::= digit_nz *digit
                    ;; Non-zero unsigned 32-bit integer
                    ;; (0 < n < 4,294,967,296)
password        ::= astring
quoted          ::= <"> *QUOTED_CHAR <">
QUOTED_CHAR     ::=  /
                    "\" quoted_specials
quoted_specials ::= <"> / "\"
rename          ::= "RENAME" SPACE mailbox SPACE mailbox
                    ;; Use of INBOX as a destination gives a NO error
response        ::= *(continue_req / response_data) response_done
response_data   ::= "*" SPACE (resp_cond_state / resp_cond_bye /
                    mailbox_data / message_data / capability_data)
                    CRLF
response_done   ::= response_tagged / response_fatal
response_fatal  ::= "*" SPACE resp_cond_bye CRLF
                    ;; Server closes connection immediately
response_tagged ::= tag SPACE resp_cond_state CRLF
resp_cond_auth  ::= ("OK" / "PREAUTH") SPACE resp_text
                    ;; Authentication condition
resp_cond_bye   ::= "BYE" SPACE resp_text
resp_cond_state ::= ("OK" / "NO" / "BAD") SPACE resp_text
                    ;; Status condition
resp_text       ::= ["[" resp_text_code "]" SPACE] (text_mime2 / text)
                    ;; text SHOULD NOT begin with "[" or "="
resp_text_code  ::= "ALERT" / "PARSE" /
                    "PERMANENTFLAGS" SPACE "(" #(flag / "\*") ")" /
                    "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
                    "UIDVALIDITY" SPACE nz_number /
                    "UNSEEN" SPACE nz_number /
                    atom [SPACE 1*]
search          ::= "SEARCH" SPACE ["CHARSET" SPACE astring SPACE]
                    1#search_key
                    ;; [CHARSET] MUST be registered with IANA
search_key      ::= "ALL" / "ANSWERED" / "BCC" SPACE astring /
                    "BEFORE" SPACE date / "BODY" SPACE astring /
                    "CC" SPACE astring / "DELETED" / "FLAGGED" /
                    "FROM" SPACE astring /
                    "KEYWORD" SPACE flag_keyword / "NEW" / "OLD" /
                    "ON" SPACE date / "RECENT" / "SEEN" /
                    "SINCE" SPACE date / "SUBJECT" SPACE astring /
                    "TEXT" SPACE astring / "TO" SPACE astring /
                    "UNANSWERED" / "UNDELETED" / "UNFLAGGED" /
                    "UNKEYWORD" SPACE flag_keyword / "UNSEEN" /
                    ;; Above this line were in [IMAP2]
                    "DRAFT" /
                    "HEADER" SPACE header_fld_name SPACE astring /
                    "LARGER" SPACE number / "NOT" SPACE search_key /
                    "OR" SPACE search_key SPACE search_key /
                    "SENTBEFORE" SPACE date / "SENTON" SPACE date /
                    "SENTSINCE" SPACE date / "SMALLER" SPACE number /
                    "UID" SPACE set / "UNDRAFT" / set /
                    "(" 1#search_key ")"
section         ::= "[" [section_text / (nz_number *["." nz_number]
                    ["." (section_text / "MIME")])] "]"
section_text    ::= "HEADER" / "HEADER.FIELDS" [".NOT"]
                    SPACE header_list / "TEXT"
select          ::= "SELECT" SPACE mailbox
sequence_num    ::= nz_number / "*"
                    ;; * is the largest number in use.  For message
                    ;; sequence numbers, it is the number of messages
                    ;; in the mailbox.  For unique identifiers, it is
                    ;; the unique identifier of the last message in
                    ;; the mailbox.
set             ::= sequence_num / (sequence_num ":" sequence_num) /
                    (set "," set)
                    ;; Identifies a set of messages.  For message
                    ;; sequence numbers, these are consecutive
                    ;; numbers from 1 to the number of messages in
                    ;; the mailbox
                    ;; Comma delimits individual numbers, colon
                    ;; delimits between two numbers inclusive.
                    ;; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13,
                    ;; 14,15 for a mailbox with 15 messages.
SPACE           ::= 
status          ::= "STATUS" SPACE mailbox SPACE "(" 1#status_att ")"
status_att      ::= "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" /
                    "UNSEEN"
store           ::= "STORE" SPACE set SPACE store_att_flags
store_att_flags ::= (["+" / "-"] "FLAGS" [".SILENT"]) SPACE
                    (flag_list / #flag)
string          ::= quoted / literal
subscribe       ::= "SUBSCRIBE" SPACE mailbox
tag             ::= 1*
text            ::= 1*TEXT_CHAR
text_mime2       ::= "=?"  "?"  "?"
                      "?="
                     ;; Syntax defined in [MIME-HDRS]
TEXT_CHAR       ::= 
time            ::= 2digit ":" 2digit ":" 2digit
                    ;; Hours minutes seconds
uid             ::= "UID" SPACE (copy / fetch / search / store)
                    ;; Unique identifiers used instead of message
                    ;; sequence numbers
uniqueid        ::= nz_number
                    ;; Strictly ascending
unsubscribe     ::= "UNSUBSCRIBE" SPACE mailbox
userid          ::= astring
x_command       ::= "X" atom 
zone            ::= ("+" / "-") 4digit
                    ;; Signed four-digit value of hhmm representing
                    ;; hours and minutes west 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".
 |