Go to the latest version of this document.

# ``twisted`.`mail`.`imap4``

module documentation
(source)

An IMAP4 protocol implementation

Author

Jp Calderone

To do:

      Suspend idle timeout while server is processing
      Use an async message parser instead of buffering in memory
      Figure out a way to not queue multi-message client requests (Flow? A simple callback?)
      Clarify some API docs (Query, etc)
      Make APPEND recognize (again) non-existent mailboxes before accepting the literal

Class | `Command` | Undocumented
Class | `DontQuoteMe` | Undocumented
Class | `FileProducer` | No class docstring; 0/5 instance variable, 0/1 constant, 2/6 methods documented
Class | `IMAP4Client` | IMAP4 client protocol implementation
Class | `IMAP4Server` | Protocol implementation for an IMAP4rev1 server.
Class | `LiteralFile` | No class docstring; 0/3 instance variable, 0/1 class variable, 1/3 method documented
Class | `LiteralString` | No class docstring; 0/3 instance variable, 1/3 method documented
Class | `MemoryAccount` | Undocumented
Class | `MemoryAccountWithoutNamespaces` | Undocumented
Class | `MessageProducer` | No class docstring; 0/5 instance variable, 0/1 class variable, 0/1 constant, 1/3 method documented
Class | `MessageSet` | A set of message identifiers usable by both `IMAP4Client` and `IMAP4Server` via `IMailboxIMAP.store` and `IMailboxIMAP.fetch`.
Class | `StreamReader` | Undocumented
Class | `StreamWriter` | Undocumented
Class | `WriteBuffer` | Buffer up a bunch of writes before sending them all to a transport at once.
Exception | `IllegalClientResponse` | Undocumented
Exception | `IllegalIdentifierError` | Undocumented
Exception | `IllegalMailboxEncoding` | Undocumented
Exception | `IllegalOperation` | Undocumented
Exception | `IllegalQueryError` | Undocumented
Exception | `IllegalServerResponse` | Undocumented
Exception | `IMAP4Exception` | Undocumented
Exception | `MailboxCollision` | Undocumented
Exception | `MailboxException` | Undocumented
Exception | `MismatchedNesting` | Undocumented
Exception | `MismatchedQuoting` | Undocumented
Exception | `NegativeResponse` | Undocumented
Exception | `NoSuchMailbox` | Undocumented
Exception | `NoSupportedAuthentication` | Undocumented
Exception | `ReadOnlyMailbox` | Undocumented
Exception | `UnhandledResponse` | Undocumented
Function | `collapseNestedLists` | Turn a nested list structure into an s-exp-like string.
Function | `collapseStrings` | Turns a list of length-one strings and lists into a list of longer strings and lists. For example,
Function | `decoder` | Decode the given `str` using the IMAP4 specific variation of UTF-7.
Function | `encoder` | Encode the given `unicode` string using the IMAP4 specific variation of UTF-7.
Function | `getBodyStructure` | RFC 3501, 7.4.2, BODYSTRUCTURE:
Function | `getEnvelope` | Undocumented
Function | `getLineCount` | Undocumented
Function | `imap4_utf_7` | Undocumented
Function | `iterateInReactor` | Consume an interator at most a single iteration per reactor iteration.
Function | `modified_base64` | Undocumented
Function | `modified_unbase64` | Undocumented
Function | `Not` | The negation of a query
Function | `Or` | The disjunction of two or more queries
Function | `parseAddr` | Undocumented
Function | `parseIdList` | Parse a message set search key into a `MessageSet`.
Function | `parseNestedParens` | Parse an s-exp-like string into a more useful data structure.
Function | `parseTime` | Undocumented
Function | `Query` | Create a query string
Function | `splitOn` | Undocumented
Function | `splitQuoted` | Split a string into whitespace delimited tokens
Function | `statusRequestHelper` | Undocumented
Function | `subparts` | Undocumented
Function | `unquote` | Undocumented
Function | `wildcardToRegexp` | Undocumented
Constant | `TIMEOUT_ERROR` | Undocumented
Variable | `memory_cast` | Undocumented
Class | `_FetchParser` | Undocumented
Class | `_MessageStructure` | `_MessageStructure` is a helper base class for message structure classes representing the structure of particular kinds of messages, as defined by their MIME type.
Class | `_MultipartMessageStructure` | `_MultipartMessageStructure` represents the message structure of a multipart/* message.
Class | `_RFC822MessageStructure` | `_RFC822MessageStructure` represents the message structure of a message/rfc822 message.
Class | `_SinglepartMessageStructure` | `_SinglepartMessageStructure` represents the message structure of a non-multipart/* message.
Class | `_TextMessageStructure` | `_TextMessageStructure` represents the message structure of a text/* message.
Function | `_formatHeaders` | Undocumented
Function | `_getContentType` | Return a two-tuple of the main and subtype of the given message.
Function | `_getMessageStructure` | Construct an appropriate type of message structure object for the given message object.
Function | `_literal` | Undocumented
Function | `_needsLiteral` | Undocumented
Function | `_needsQuote` | Undocumented
Function | `_parseMbox` | Undocumented
Function | `_prepareMailboxName` | Undocumented
Function | `_quote` | Undocumented
Function | `_swap` | Swap `this` with `that` if `this` is `ifIs`.
Function | `_swapAllPairs` | Swap each element in each pair in `of` with `that` it is `ifIs`.
Constant | `_ATOM_SPECIALS` | Undocumented
Constant | `_CTL` | Undocumented
Constant | `_MONTH_NAMES` | Undocumented
Constant | `_NO_QUOTES` | Undocumented
Constant | `_SIMPLE_BOOL` | Undocumented
Constant | `_SP` | Undocumented
Variable | `_atomChars` | Undocumented
Variable | `_codecInfo` | Undocumented
Variable | `_nativeNonAtomChars` | Undocumented
Variable | `_nonAtomChars` | Undocumented
Variable | `_nonAtomRE` | Undocumented
Variable | `_statusRequestDict` | Undocumented

def collapseNestedLists(items): (source)

Turn a nested list structure into an s-exp-like string.

Strings in `items` will be sent as literals if they contain CR or LF, otherwise they will be quoted. References to None in `items` will be translated to the atom NIL. Objects with a 'read' attribute will have it called on them with no arguments and the returned string will be inserted into the output as a literal. Integers will be converted to strings and inserted into the output unquoted. Instances of `DontQuoteMe` will be converted to strings and inserted into the output unquoted.

This function used to be much nicer, and only quote things that really needed to be quoted (and `DontQuoteMe` did not exist), however, many broken IMAP4 clients were unable to deal with this level of sophistication, forcing the current behavior to be adopted for practical reasons.

Parameters
items:Any iterable | Undocumented

Returns
`str` | Undocumented

def collapseStrings(results): (source)

Turns a list of length-one strings and lists into a list of longer strings and lists. For example,

['a', 'b', ['c', 'd']] is returned as ['ab', ['cd']]

Parameters
results:`list` of `bytes` and `list` | The list to be collapsed

Returns
`list` of `bytes` and `list` | A new list which is the collapsed form of `results`

def decoder(s, errors=None): (source)

Decode the given `str` using the IMAP4 specific variation of UTF-7.

Parameters
s:`str` | The bytes to decode.
errors | Policy for handling decoding errors. Currently ignored.

Returns
a `tuple` of a `unicode` string giving the text which was decoded and an `int` giving the number of bytes consumed from the input.

def encoder(s, errors=None): (source)

Encode the given `unicode` string using the IMAP4 specific variation of UTF-7.

Parameters
s:`unicode` | The text to encode.
errors | Policy for handling encoding errors. Currently ignored.

Returns
`tuple` of a `str` giving the encoded bytes and an `int` giving the number of code units consumed from the input.

def getBodyStructure(msg, extended=False): (source)

RFC 3501, 7.4.2, BODYSTRUCTURE:

      A parenthesized list that describes the [MIME-IMB] body structure of a
      message.  This is computed by the server by parsing the [MIME-IMB] header
      fields, defaulting various fields as necessary.

        For example, a simple text message of 48 lines and 2279 octets can have
        a body structure of: ("TEXT" "PLAIN" ("CHARSET" "US-ASCII") NIL NIL
        "7BIT" 2279 48)

This is represented as:

        ["TEXT", "PLAIN", ["CHARSET", "US-ASCII"], None, None, "7BIT", 2279, 48]

These basic fields are documented in the RFC as:

1. body type

   A string giving the content media type name as defined in [MIME-IMB].

2. body subtype

   A string giving the content subtype name as defined in [MIME-IMB].

3. body parameter parenthesized list

   A parenthesized list of attribute/value pairs [e.g., ("foo" "bar" "baz" "rag") where "bar" is the value of "foo" and "rag" is the value of "baz"] as defined in [MIME-IMB].

4. body id

   A string giving the content id as defined in [MIME-IMB].

5. body description

   A string giving the content description as defined in [MIME-IMB].

6. body encoding

   A string giving the content transfer encoding as defined in [MIME-IMB].

7. body size

   A number giving the size of the body in octets. Note that this size is the size in its transfer encoding and not the resulting size after any decoding.

Put another way, the body structure is a list of seven elements. The semantics of the elements of this list are:

1. Byte string giving the major MIME type
2. Byte string giving the minor MIME type
3. A list giving the Content-Type parameters of the message
4. A byte string giving the content identifier for the message part, or None if it has no content identifier.
5. A byte string giving the content description for the message part, or None if it has no content description.
6. A byte string giving the Content-Encoding of the message body
7. An integer giving the number of octets in the message body

The RFC goes on:

        Multiple parts are indicated by parenthesis nesting.  Instead of a body
        type as the first element of the parenthesized list, there is a sequence
        of one or more nested body structures.  The second element of the
        parenthesized list is the multipart subtype (mixed, digest, parallel,
        alternative, etc.).

        For example, a two part message consisting of a text and a
        BASE64-encoded text attachment can have a body structure of: (("TEXT"
        "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT" 1152 23)("TEXT" "PLAIN"
        ("CHARSET" "US-ASCII" "NAME" "cc.diff")
        "<960723163407.20117h@cac.washington.edu>" "Compiler diff" "BASE64" 4554
        73) "MIXED")

This is represented as:

        [["TEXT", "PLAIN", ["CHARSET", "US-ASCII"], None, None, "7BIT", 1152,
          23],
         ["TEXT", "PLAIN", ["CHARSET", "US-ASCII", "NAME", "cc.diff"],
          "<960723163407.20117h@cac.washington.edu>", "Compiler diff",
          "BASE64", 4554, 73],
         "MIXED"]

In other words, a list of N + 1 elements, where N is the number of parts in the message. The first N elements are structures as defined by the previous section. The last element is the minor MIME subtype of the multipart message.

Additionally, the RFC describes extension data:

        Extension data follows the multipart subtype.  Extension data is never
        returned with the BODY fetch, but can be returned with a BODYSTRUCTURE
        fetch.  Extension data, if present, MUST be in the defined order.

The `extended` flag controls whether extension data might be returned with the normal data.

def getEnvelope(msg): (source)

Undocumented

def getLineCount(msg): (source)

Undocumented

def imap4_utf_7(name): (source)

Undocumented

def iterateInReactor(i): (source)

Consume an interator at most a single iteration per reactor iteration.

If the iterator produces a Deferred, the next iteration will not occur until the Deferred fires, otherwise the next iteration will be taken in the next reactor iteration.

Returns
`Deferred` | A deferred which fires (with None) when the iterator is exhausted or whose errback is called if there is an exception.

def modified_base64(s): (source)

Undocumented

def modified_unbase64(s): (source)

Undocumented

def Not(query): (source)

The negation of a query

def Or(*args): (source)

The disjunction of two or more queries

def parseAddr(addr): (source)

Undocumented

def parseIdList(s, lastMessageId=None): (source)

Parse a message set search key into a `MessageSet`.

Parameters
s:`bytes` | A string description of an id list, for example "1:3, 4:*"
lastMessageId:`int` | The last message sequence id or UID, depending on whether we are parsing the list in UID or sequence id context. The caller should pass in the correct value.

Returns
`MessageSet` | A `MessageSet` that contains the ids defined in the list

def parseNestedParens(s, handleLiteral=1): (source)

Parse an s-exp-like string into a more useful data structure.

Parameters
s:`bytes` | The s-exp-like string to parse
handleLiteral | Undocumented

Returns
`list` of `bytes` and `list` | A list containing the tokens present in the input.

Raises
`MismatchedNesting` | Raised if the number or placement of opening or closing parenthesis is invalid.

def parseTime(s): (source)

Undocumented

def Query(sorted=0, **kwarg): (source)

Create a query string

Among the accepted keywords are:

        all         : If set to a true value, search all messages in the
                      current mailbox

        answered    : If set to a true value, search messages flagged with
                      \Answered

        bcc         : A substring to search the BCC header field for

        before      : Search messages with an internal date before this
                      value.  The given date should be a string in the format
                      of 'DD-Mon-YYYY'.  For example, '03-Mar-2003'.

        body        : A substring to search the body of the messages for

        cc          : A substring to search the CC header field for

        deleted     : If set to a true value, search messages flagged with
                      \Deleted

        draft       : If set to a true value, search messages flagged with
                      \Draft

        flagged     : If set to a true value, search messages flagged with
                      \Flagged

        from        : A substring to search the From header field for

        header      : A two-tuple of a header name and substring to search
                      for in that header

        keyword     : Search for messages with the given keyword set

        larger      : Search for messages larger than this number of octets

        messages    : Search only the given message sequence set.

        new         : If set to a true value, search messages flagged with
                      \Recent but not \Seen

        old         : If set to a true value, search messages not flagged with
                      \Recent

        on          : Search messages with an internal date which is on this
                      date.  The given date should be a string in the format
                      of 'DD-Mon-YYYY'.  For example, '03-Mar-2003'.

        recent      : If set to a true value, search for messages flagged with
                      \Recent

        seen        : If set to a true value, search for messages flagged with
                      \Seen

        sentbefore  : Search for messages with an RFC822 'Date' header before
                      this date.  The given date should be a string in the format
                      of 'DD-Mon-YYYY'.  For example, '03-Mar-2003'.

        senton      : Search for messages with an RFC822 'Date' header which is
                      on this date  The given date should be a string in the format
                      of 'DD-Mon-YYYY'.  For example, '03-Mar-2003'.

        sentsince   : Search for messages with an RFC822 'Date' header which is
                      after this date.  The given date should be a string in the format
                      of 'DD-Mon-YYYY'.  For example, '03-Mar-2003'.

        since       : Search for messages with an internal date that is after
                      this date..  The given date should be a string in the format
                      of 'DD-Mon-YYYY'.  For example, '03-Mar-2003'.

        smaller     : Search for messages smaller than this number of octets

        subject     : A substring to search the 'subject' header for

        text        : A substring to search the entire message for

        to          : A substring to search the 'to' header for

        uid         : Search only the messages in the given message set

        unanswered  : If set to a true value, search for messages not
                      flagged with \Answered

        undeleted   : If set to a true value, search for messages not
                      flagged with \Deleted

        undraft     : If set to a true value, search for messages not
                      flagged with \Draft

        unflagged   : If set to a true value, search for messages not
                      flagged with \Flagged

        unkeyword   : Search for messages without the given keyword set

        unseen      : If set to a true value, search for messages not
                      flagged with \Seen

Parameters
sorted:`bool` | If true, the output will be sorted, alphabetically. The standard does not require it, but it makes testing this function easier. The default is zero, and this should be acceptable for any application.
**kwarg | Undocumented

Returns
`str` | The formatted query string

def splitOn(sequence, predicate, transformers): (source)

Undocumented

def splitQuoted(s): (source)

Split a string into whitespace delimited tokens

Tokens that would otherwise be separated but are surrounded by " remain as a single token. Any token that is not quoted and is equal to "NIL" is tokenized as `None`.

Parameters
s:`bytes` | The string to be split

Returns
`list` of `bytes` | A list of the resulting tokens

Raises
`MismatchedQuoting` | Raised if an odd number of quotes are present

def statusRequestHelper(mbox, names): (source)

Undocumented

def subparts(m): (source)

Undocumented

def unquote(s): (source)

Undocumented

def wildcardToRegexp(wildcard, delim=None): (source)

Undocumented

TIMEOUT_ERROR = (source)

Undocumented

Value

    error.TimeoutError()

memory_cast = (source)

Undocumented

def _formatHeaders(headers): (source)

Undocumented

def _getContentType(msg): (source)

Return a two-tuple of the main and subtype of the given message.

def _getMessageStructure(message): (source)

Construct an appropriate type of message structure object for the given message object.

Parameters
message | A `IMessagePart` provider

Returns
A `_MessageStructure` instance of the most specific type available for the given message, determined by inspecting the MIME type of the message.

def _literal(s: `bytes`) -> `bytes`: (source)

Undocumented

def _needsLiteral(s): (source)

Undocumented

def _needsQuote(s): (source)

Undocumented

def _parseMbox(name): (source)

Undocumented

def _prepareMailboxName(name): (source)

Undocumented

def _quote(s): (source)

Undocumented

def _swap(this, that, ifIs): (source)

Swap `this` with `that` if `this` is `ifIs`.

Parameters
this | The object that may be replaced.
that | The object that may replace `this`.
ifIs | An object whose identity will be compared to `this`.

def _swapAllPairs(of, that, ifIs): (source)

Swap each element in each pair in `of` with `that` it is `ifIs`.

Parameters
of:`list` of 2-`tuple`s | A list of 2-`tuple`s, whose members may be the object `that`
that | Undocumented
ifIs | An object whose identity will be compared to members of each pair in `of`

Returns
A `list` of 2-`tuple`s with all occurences of `ifIs` replaced with `that`

_ATOM_SPECIALS: `bytes` = (source)

Undocumented

Value

    b'(){ %*"'

_CTL = (source)

Undocumented

Value

    bytes(chain(range(33), range(128, 256)))

_MONTH_NAMES = (source)

Undocumented

Value

    dict(zip(range(1, 13), 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split()↵
    ))

_NO_QUOTES: `tuple[str, ...]` = (source)

Undocumented

Value

    ('LARGER', 'SMALLER', 'UID')

_SIMPLE_BOOL: `tuple[str, ...]` = (source)

Undocumented

Value

    ('ALL',
     'ANSWERED',
     'DELETED',
     'DRAFT',
     'FLAGGED',
     'NEW',
     'OLD',
    ...

_SP: `bytes` = (source)

Undocumented

Value

    b' '

_atomChars = (source)

Undocumented

_codecInfo = (source)

Undocumented

_nativeNonAtomChars = (source)

Undocumented

_nonAtomChars = (source)

Undocumented

_nonAtomRE = (source)

Undocumented

_statusRequestDict: `dict[str, str]` = (source)

Undocumented