Twisted IMAP support
Here three examples deriving from the script contained in the official
documentation, which can connect to an IMAP mailbox and retrieve the
messages subjects:
How does a command gets sent?
Let’s take the example of the status method
a Command object is instantiated with:
- the STATUS string as the command,
- the command arguments,
- the continuation function and its arguments,
- the expected response (is unused at this time)
sendCommand
- takes this Command instance as an argument,
- stores a deferred in the cmd,
- if there is a reply expected for a running command: queue the
command and returns the command deferred,
- else :
- make a tag number which identifies the request,
- stores the command in the tags member dictionary
- send the request and returns the deferred
the __cbStatus callback which parses the reply string into a dictionary
and returns the dictionary is attached to the deferred
How does a network reply gets processed?
lineReceived is meant to distinguish between the lines and the
literal strings. The case of literal strings is of minor importance
in our context: in case of a line, it is split into:
- the tag which can be either *, + or an IMAP tag
according to the RFC 3501,
- and the rest which comprises of the response name and arguments.
The tag and rest are passed to:
the dispatchCommand which selects a handler for the data based on
the client state: the state of the Twisted client can be either
UNAUTH, AUTH (the IMAP state selected and logout are
comprised into the AUTH Twisted state).
The response_AUTH handler, which correspond to our context, hands
the the tag and data to:
the _defaultHandler has several cases:
if the response is untagged
- if the client is not waiting for an answer the _extraInfo
method is evaluated with the tag and rest as arguments.
- if the client is waiting, the waiting member attribute
contains the tag number. Using the tags dictionary, which
stores the tag as keys and the Command object instance as
value, it is possible to reach to the command name, the
received line buffer, the continuation function, the deferred
and its callback. Because the response is untagged, either it
is :
- a continuation (+), in which case the continuation
function is called
- a data (*), in which case the data is appended to the
buffer. The buffer is used the tagged response arrives.
if the response is tagged, it is a final response, the finish
method, of the command object instance corresponding to the tag,
is executed.
the finish method of the command object parses the buffer of lines
and executes the callback with the received lines.
These steps are not adapted to the processing of notifications as:
- there is no callback stored for the message from the server
accepting notifications, the + idling continuation data requests
- the data is buffered until the reception final tag response which
triggers the callback of the command while a user callback should be
executed for each notification,
How can this API be used
(and yes it is a shame errors are completely ingored)
The pattern for this task is :
- A client factory deriving from tw.in.pr.ClientFactory, configured
with the server name, port, user, account and mailbox
- A protocol deriving from tw.pr.imap4.IMAP4Client which connect to
the mailbox on serverGreetings and calls the factory deferred
- A higher level function attached to the factory deferred expecting
a connection to the inbox and fetching the latest emails titles
The chronological steps are:
- declare the client factory, the protocol, and in the main: the
higher level function which receives the list of email in the inbox
and prints them
- instanciate a factory with the account information
- attach the higher level function to the deferred factory
- attach the factory to the reactor with a TCPConnect and the
mailserver informations
- run the reactor
- the TCP connection is opened triggering the buildprotocol on the
factory, returning a protocol instance on which connectionMade is
called which says “hi” to the server
- the server replies with its greetings and capabilities, triggering
the protocol serverGreetings callback:
- login
- select the correct mailbox
- download the message subjects
- call the factory deferred with the result
- the function prints the title and stops the reactor
02 51 68 50 63
5, rue des pins
Fromentine