| Index: third_party/twisted_8_1/twisted/mail/pop3client.py
|
| diff --git a/third_party/twisted_8_1/twisted/mail/pop3client.py b/third_party/twisted_8_1/twisted/mail/pop3client.py
|
| deleted file mode 100644
|
| index 5b7986c99d62617baac11d141370195ea01f02a8..0000000000000000000000000000000000000000
|
| --- a/third_party/twisted_8_1/twisted/mail/pop3client.py
|
| +++ /dev/null
|
| @@ -1,704 +0,0 @@
|
| -# -*- test-case-name: twisted.mail.test.test_pop3client -*-
|
| -# Copyright (c) 2001-2004 Divmod Inc.
|
| -# See LICENSE for details.
|
| -
|
| -"""
|
| -POP3 client protocol implementation
|
| -
|
| -Don't use this module directly. Use twisted.mail.pop3 instead.
|
| -
|
| -@author: U{Jp Calderone<mailto:exarkun@twistedmatrix.com>}
|
| -"""
|
| -
|
| -import re, md5
|
| -
|
| -from twisted.python import log
|
| -from twisted.internet import defer
|
| -from twisted.protocols import basic
|
| -from twisted.protocols import policies
|
| -from twisted.internet import error
|
| -from twisted.internet import interfaces
|
| -
|
| -OK = '+OK'
|
| -ERR = '-ERR'
|
| -
|
| -class POP3ClientError(Exception):
|
| - """Base class for all exceptions raised by POP3Client.
|
| - """
|
| -
|
| -class InsecureAuthenticationDisallowed(POP3ClientError):
|
| - """Secure authentication was required but no mechanism could be found.
|
| - """
|
| -
|
| -class TLSError(POP3ClientError):
|
| - """
|
| - Secure authentication was required but either the transport does
|
| - not support TLS or no TLS context factory was supplied.
|
| - """
|
| -
|
| -class TLSNotSupportedError(POP3ClientError):
|
| - """
|
| - Secure authentication was required but the server does not support
|
| - TLS.
|
| - """
|
| -
|
| -class ServerErrorResponse(POP3ClientError):
|
| - """The server returned an error response to a request.
|
| - """
|
| - def __init__(self, reason, consumer=None):
|
| - POP3ClientError.__init__(self, reason)
|
| - self.consumer = consumer
|
| -
|
| -class LineTooLong(POP3ClientError):
|
| - """The server sent an extremely long line.
|
| - """
|
| -
|
| -class _ListSetter:
|
| - # Internal helper. POP3 responses sometimes occur in the
|
| - # form of a list of lines containing two pieces of data,
|
| - # a message index and a value of some sort. When a message
|
| - # is deleted, it is omitted from these responses. The
|
| - # setitem method of this class is meant to be called with
|
| - # these two values. In the cases where indexes are skipped,
|
| - # it takes care of padding out the missing values with None.
|
| - def __init__(self, L):
|
| - self.L = L
|
| - def setitem(self, (item, value)):
|
| - diff = item - len(self.L) + 1
|
| - if diff > 0:
|
| - self.L.extend([None] * diff)
|
| - self.L[item] = value
|
| -
|
| -
|
| -def _statXform(line):
|
| - # Parse a STAT response
|
| - numMsgs, totalSize = line.split(None, 1)
|
| - return int(numMsgs), int(totalSize)
|
| -
|
| -
|
| -def _listXform(line):
|
| - # Parse a LIST response
|
| - index, size = line.split(None, 1)
|
| - return int(index) - 1, int(size)
|
| -
|
| -
|
| -def _uidXform(line):
|
| - # Parse a UIDL response
|
| - index, uid = line.split(None, 1)
|
| - return int(index) - 1, uid
|
| -
|
| -def _codeStatusSplit(line):
|
| - # Parse an +OK or -ERR response
|
| - parts = line.split(' ', 1)
|
| - if len(parts) == 1:
|
| - return parts[0], ''
|
| - return parts
|
| -
|
| -def _dotUnquoter(line):
|
| - """
|
| - C{'.'} characters which begin a line of a message are doubled to avoid
|
| - confusing with the terminating C{'.\\r\\n'} sequence. This function
|
| - unquotes them.
|
| - """
|
| - if line.startswith('..'):
|
| - return line[1:]
|
| - return line
|
| -
|
| -class POP3Client(basic.LineOnlyReceiver, policies.TimeoutMixin):
|
| - """POP3 client protocol implementation class
|
| -
|
| - Instances of this class provide a convenient, efficient API for
|
| - retrieving and deleting messages from a POP3 server.
|
| -
|
| - @type startedTLS: C{bool}
|
| - @ivar startedTLS: Whether TLS has been negotiated successfully.
|
| -
|
| -
|
| - @type allowInsecureLogin: C{bool}
|
| - @ivar allowInsecureLogin: Indicate whether login() should be
|
| - allowed if the server offers no authentication challenge and if
|
| - our transport does not offer any protection via encryption.
|
| -
|
| - @type serverChallenge: C{str} or C{None}
|
| - @ivar serverChallenge: Challenge received from the server
|
| -
|
| - @type timeout: C{int}
|
| - @ivar timeout: Number of seconds to wait before timing out a
|
| - connection. If the number is <= 0, no timeout checking will be
|
| - performed.
|
| - """
|
| -
|
| - startedTLS = False
|
| - allowInsecureLogin = False
|
| - timeout = 0
|
| - serverChallenge = None
|
| -
|
| - # Capabilities are not allowed to change during the session
|
| - # (except when TLS is negotiated), so cache the first response and
|
| - # use that for all later lookups
|
| - _capCache = None
|
| -
|
| - # Regular expression to search for in the challenge string in the server
|
| - # greeting line.
|
| - _challengeMagicRe = re.compile('(<[^>]+>)')
|
| -
|
| - # List of pending calls.
|
| - # We are a pipelining API but don't actually
|
| - # support pipelining on the network yet.
|
| - _blockedQueue = None
|
| -
|
| - # The Deferred to which the very next result will go.
|
| - _waiting = None
|
| -
|
| - # Whether we dropped the connection because of a timeout
|
| - _timedOut = False
|
| -
|
| - # If the server sends an initial -ERR, this is the message it sent
|
| - # with it.
|
| - _greetingError = None
|
| -
|
| - def _blocked(self, f, *a):
|
| - # Internal helper. If commands are being blocked, append
|
| - # the given command and arguments to a list and return a Deferred
|
| - # that will be chained with the return value of the function
|
| - # when it eventually runs. Otherwise, set up for commands to be
|
| -
|
| - # blocked and return None.
|
| - if self._blockedQueue is not None:
|
| - d = defer.Deferred()
|
| - self._blockedQueue.append((d, f, a))
|
| - return d
|
| - self._blockedQueue = []
|
| - return None
|
| -
|
| - def _unblock(self):
|
| - # Internal helper. Indicate that a function has completed.
|
| - # If there are blocked commands, run the next one. If there
|
| - # are not, set up for the next command to not be blocked.
|
| - if self._blockedQueue == []:
|
| - self._blockedQueue = None
|
| - elif self._blockedQueue is not None:
|
| - _blockedQueue = self._blockedQueue
|
| - self._blockedQueue = None
|
| -
|
| - d, f, a = _blockedQueue.pop(0)
|
| - d2 = f(*a)
|
| - d2.chainDeferred(d)
|
| - # f is a function which uses _blocked (otherwise it wouldn't
|
| - # have gotten into the blocked queue), which means it will have
|
| - # re-set _blockedQueue to an empty list, so we can put the rest
|
| - # of the blocked queue back into it now.
|
| - self._blockedQueue.extend(_blockedQueue)
|
| -
|
| -
|
| - def sendShort(self, cmd, args):
|
| - # Internal helper. Send a command to which a short response
|
| - # is expected. Return a Deferred that fires when the response
|
| - # is received. Block all further commands from being sent until
|
| - # the response is received. Transition the state to SHORT.
|
| - d = self._blocked(self.sendShort, cmd, args)
|
| - if d is not None:
|
| - return d
|
| -
|
| - if args:
|
| - self.sendLine(cmd + ' ' + args)
|
| - else:
|
| - self.sendLine(cmd)
|
| - self.state = 'SHORT'
|
| - self._waiting = defer.Deferred()
|
| - return self._waiting
|
| -
|
| - def sendLong(self, cmd, args, consumer, xform):
|
| - # Internal helper. Send a command to which a multiline
|
| - # response is expected. Return a Deferred that fires when
|
| - # the entire response is received. Block all further commands
|
| - # from being sent until the entire response is received.
|
| - # Transition the state to LONG_INITIAL.
|
| - d = self._blocked(self.sendLong, cmd, args, consumer, xform)
|
| - if d is not None:
|
| - return d
|
| -
|
| - if args:
|
| - self.sendLine(cmd + ' ' + args)
|
| - else:
|
| - self.sendLine(cmd)
|
| - self.state = 'LONG_INITIAL'
|
| - self._xform = xform
|
| - self._consumer = consumer
|
| - self._waiting = defer.Deferred()
|
| - return self._waiting
|
| -
|
| - # Twisted protocol callback
|
| - def connectionMade(self):
|
| - if self.timeout > 0:
|
| - self.setTimeout(self.timeout)
|
| -
|
| - self.state = 'WELCOME'
|
| - self._blockedQueue = []
|
| -
|
| - def timeoutConnection(self):
|
| - self._timedOut = True
|
| - self.transport.loseConnection()
|
| -
|
| - def connectionLost(self, reason):
|
| - if self.timeout > 0:
|
| - self.setTimeout(None)
|
| -
|
| - if self._timedOut:
|
| - reason = error.TimeoutError()
|
| - elif self._greetingError:
|
| - reason = ServerErrorResponse(self._greetingError)
|
| -
|
| - d = []
|
| - if self._waiting is not None:
|
| - d.append(self._waiting)
|
| - self._waiting = None
|
| - if self._blockedQueue is not None:
|
| - d.extend([deferred for (deferred, f, a) in self._blockedQueue])
|
| - self._blockedQueue = None
|
| - for w in d:
|
| - w.errback(reason)
|
| -
|
| - def lineReceived(self, line):
|
| - if self.timeout > 0:
|
| - self.resetTimeout()
|
| -
|
| - state = self.state
|
| - self.state = None
|
| - state = getattr(self, 'state_' + state)(line) or state
|
| - if self.state is None:
|
| - self.state = state
|
| -
|
| - def lineLengthExceeded(self, buffer):
|
| - # XXX - We need to be smarter about this
|
| - if self._waiting is not None:
|
| - waiting, self._waiting = self._waiting, None
|
| - waiting.errback(LineTooLong())
|
| - self.transport.loseConnection()
|
| -
|
| - # POP3 Client state logic - don't touch this.
|
| - def state_WELCOME(self, line):
|
| - # WELCOME is the first state. The server sends one line of text
|
| - # greeting us, possibly with an APOP challenge. Transition the
|
| - # state to WAITING.
|
| - code, status = _codeStatusSplit(line)
|
| - if code != OK:
|
| - self._greetingError = status
|
| - self.transport.loseConnection()
|
| - else:
|
| - m = self._challengeMagicRe.search(status)
|
| -
|
| - if m is not None:
|
| - self.serverChallenge = m.group(1)
|
| -
|
| - self.serverGreeting(status)
|
| -
|
| - self._unblock()
|
| - return 'WAITING'
|
| -
|
| - def state_WAITING(self, line):
|
| - # The server isn't supposed to send us anything in this state.
|
| - log.msg("Illegal line from server: " + repr(line))
|
| -
|
| - def state_SHORT(self, line):
|
| - # This is the state we are in when waiting for a single
|
| - # line response. Parse it and fire the appropriate callback
|
| - # or errback. Transition the state back to WAITING.
|
| - deferred, self._waiting = self._waiting, None
|
| - self._unblock()
|
| - code, status = _codeStatusSplit(line)
|
| - if code == OK:
|
| - deferred.callback(status)
|
| - else:
|
| - deferred.errback(ServerErrorResponse(status))
|
| - return 'WAITING'
|
| -
|
| - def state_LONG_INITIAL(self, line):
|
| - # This is the state we are in when waiting for the first
|
| - # line of a long response. Parse it and transition the
|
| - # state to LONG if it is an okay response; if it is an
|
| - # error response, fire an errback, clean up the things
|
| - # waiting for a long response, and transition the state
|
| - # to WAITING.
|
| - code, status = _codeStatusSplit(line)
|
| - if code == OK:
|
| - return 'LONG'
|
| - consumer = self._consumer
|
| - deferred = self._waiting
|
| - self._consumer = self._waiting = self._xform = None
|
| - self._unblock()
|
| - deferred.errback(ServerErrorResponse(status, consumer))
|
| - return 'WAITING'
|
| -
|
| - def state_LONG(self, line):
|
| - # This is the state for each line of a long response.
|
| - # If it is the last line, finish things, fire the
|
| - # Deferred, and transition the state to WAITING.
|
| - # Otherwise, pass the line to the consumer.
|
| - if line == '.':
|
| - consumer = self._consumer
|
| - deferred = self._waiting
|
| - self._consumer = self._waiting = self._xform = None
|
| - self._unblock()
|
| - deferred.callback(consumer)
|
| - return 'WAITING'
|
| - else:
|
| - if self._xform is not None:
|
| - self._consumer(self._xform(line))
|
| - else:
|
| - self._consumer(line)
|
| - return 'LONG'
|
| -
|
| -
|
| - # Callbacks - override these
|
| - def serverGreeting(self, greeting):
|
| - """Called when the server has sent us a greeting.
|
| -
|
| - @type greeting: C{str} or C{None}
|
| - @param greeting: The status message sent with the server
|
| - greeting. For servers implementing APOP authentication, this
|
| - will be a challenge string. .
|
| - """
|
| -
|
| -
|
| - # External API - call these (most of 'em anyway)
|
| - def startTLS(self, contextFactory=None):
|
| - """
|
| - Initiates a 'STLS' request and negotiates the TLS / SSL
|
| - Handshake.
|
| -
|
| - @type contextFactory: C{ssl.ClientContextFactory} @param
|
| - contextFactory: The context factory with which to negotiate
|
| - TLS. If C{None}, try to create a new one.
|
| -
|
| - @return: A Deferred which fires when the transport has been
|
| - secured according to the given contextFactory, or which fails
|
| - if the transport cannot be secured.
|
| - """
|
| - tls = interfaces.ITLSTransport(self.transport, None)
|
| - if tls is None:
|
| - return defer.fail(TLSError(
|
| - "POP3Client transport does not implement "
|
| - "interfaces.ITLSTransport"))
|
| -
|
| - if contextFactory is None:
|
| - contextFactory = self._getContextFactory()
|
| -
|
| - if contextFactory is None:
|
| - return defer.fail(TLSError(
|
| - "POP3Client requires a TLS context to "
|
| - "initiate the STLS handshake"))
|
| -
|
| - d = self.capabilities()
|
| - d.addCallback(self._startTLS, contextFactory, tls)
|
| - return d
|
| -
|
| -
|
| - def _startTLS(self, caps, contextFactory, tls):
|
| - assert not self.startedTLS, "Client and Server are currently communicating via TLS"
|
| -
|
| - if 'STLS' not in caps:
|
| - return defer.fail(TLSNotSupportedError(
|
| - "Server does not support secure communication "
|
| - "via TLS / SSL"))
|
| -
|
| - d = self.sendShort('STLS', None)
|
| - d.addCallback(self._startedTLS, contextFactory, tls)
|
| - d.addCallback(lambda _: self.capabilities())
|
| - return d
|
| -
|
| -
|
| - def _startedTLS(self, result, context, tls):
|
| - self.transport = tls
|
| - self.transport.startTLS(context)
|
| - self._capCache = None
|
| - self.startedTLS = True
|
| - return result
|
| -
|
| -
|
| - def _getContextFactory(self):
|
| - try:
|
| - from twisted.internet import ssl
|
| - except ImportError:
|
| - return None
|
| - else:
|
| - context = ssl.ClientContextFactory()
|
| - context.method = ssl.SSL.TLSv1_METHOD
|
| - return context
|
| -
|
| -
|
| - def login(self, username, password):
|
| - """Log into the server.
|
| -
|
| - If APOP is available it will be used. Otherwise, if TLS is
|
| - available an 'STLS' session will be started and plaintext
|
| - login will proceed. Otherwise, if the instance attribute
|
| - allowInsecureLogin is set to True, insecure plaintext login
|
| - will proceed. Otherwise, InsecureAuthenticationDisallowed
|
| - will be raised (asynchronously).
|
| -
|
| - @param username: The username with which to log in.
|
| - @param password: The password with which to log in.
|
| -
|
| - @rtype: C{Deferred}
|
| - @return: A deferred which fires when login has
|
| - completed.
|
| - """
|
| - d = self.capabilities()
|
| - d.addCallback(self._login, username, password)
|
| - return d
|
| -
|
| -
|
| - def _login(self, caps, username, password):
|
| - if self.serverChallenge is not None:
|
| - return self._apop(username, password, self.serverChallenge)
|
| -
|
| - tryTLS = 'STLS' in caps
|
| -
|
| - #If our transport supports switching to TLS, we might want to try to switch to TLS.
|
| - tlsableTransport = interfaces.ITLSTransport(self.transport, None) is not None
|
| -
|
| - # If our transport is not already using TLS, we might want to try to switch to TLS.
|
| - nontlsTransport = interfaces.ISSLTransport(self.transport, None) is None
|
| -
|
| - if not self.startedTLS and tryTLS and tlsableTransport and nontlsTransport:
|
| - d = self.startTLS()
|
| -
|
| - d.addCallback(self._loginTLS, username, password)
|
| - return d
|
| -
|
| - elif self.startedTLS or not nontlsTransport or self.allowInsecureLogin:
|
| - return self._plaintext(username, password)
|
| - else:
|
| - return defer.fail(InsecureAuthenticationDisallowed())
|
| -
|
| -
|
| - def _loginTLS(self, res, username, password):
|
| - return self._plaintext(username, password)
|
| -
|
| - def _plaintext(self, username, password):
|
| - # Internal helper. Send a username/password pair, returning a Deferred
|
| - # that fires when both have succeeded or fails when the server rejects
|
| - # either.
|
| - return self.user(username).addCallback(lambda r: self.password(password))
|
| -
|
| - def _apop(self, username, password, challenge):
|
| - # Internal helper. Computes and sends an APOP response. Returns
|
| - # a Deferred that fires when the server responds to the response.
|
| - digest = md5.new(challenge + password).hexdigest()
|
| - return self.apop(username, digest)
|
| -
|
| - def apop(self, username, digest):
|
| - """Perform APOP login.
|
| -
|
| - This should be used in special circumstances only, when it is
|
| - known that the server supports APOP authentication, and APOP
|
| - authentication is absolutely required. For the common case,
|
| - use L{login} instead.
|
| -
|
| - @param username: The username with which to log in.
|
| - @param digest: The challenge response to authenticate with.
|
| - """
|
| - return self.sendShort('APOP', username + ' ' + digest)
|
| -
|
| - def user(self, username):
|
| - """Send the user command.
|
| -
|
| - This performs the first half of plaintext login. Unless this
|
| - is absolutely required, use the L{login} method instead.
|
| -
|
| - @param username: The username with which to log in.
|
| - """
|
| - return self.sendShort('USER', username)
|
| -
|
| - def password(self, password):
|
| - """Send the password command.
|
| -
|
| - This performs the second half of plaintext login. Unless this
|
| - is absolutely required, use the L{login} method instead.
|
| -
|
| - @param password: The plaintext password with which to authenticate.
|
| - """
|
| - return self.sendShort('PASS', password)
|
| -
|
| - def delete(self, index):
|
| - """Delete a message from the server.
|
| -
|
| - @type index: C{int}
|
| - @param index: The index of the message to delete.
|
| - This is 0-based.
|
| -
|
| - @rtype: C{Deferred}
|
| - @return: A deferred which fires when the delete command
|
| - is successful, or fails if the server returns an error.
|
| - """
|
| - return self.sendShort('DELE', str(index + 1))
|
| -
|
| - def _consumeOrSetItem(self, cmd, args, consumer, xform):
|
| - # Internal helper. Send a long command. If no consumer is
|
| - # provided, create a consumer that puts results into a list
|
| - # and return a Deferred that fires with that list when it
|
| - # is complete.
|
| - if consumer is None:
|
| - L = []
|
| - consumer = _ListSetter(L).setitem
|
| - return self.sendLong(cmd, args, consumer, xform).addCallback(lambda r: L)
|
| - return self.sendLong(cmd, args, consumer, xform)
|
| -
|
| - def _consumeOrAppend(self, cmd, args, consumer, xform):
|
| - # Internal helper. Send a long command. If no consumer is
|
| - # provided, create a consumer that appends results to a list
|
| - # and return a Deferred that fires with that list when it is
|
| - # complete.
|
| - if consumer is None:
|
| - L = []
|
| - consumer = L.append
|
| - return self.sendLong(cmd, args, consumer, xform).addCallback(lambda r: L)
|
| - return self.sendLong(cmd, args, consumer, xform)
|
| -
|
| - def capabilities(self, useCache=True):
|
| - """Retrieve the capabilities supported by this server.
|
| -
|
| - Not all servers support this command. If the server does not
|
| - support this, it is treated as though it returned a successful
|
| - response listing no capabilities. At some future time, this may be
|
| - changed to instead seek out information about a server's
|
| - capabilities in some other fashion (only if it proves useful to do
|
| - so, and only if there are servers still in use which do not support
|
| - CAPA but which do support POP3 extensions that are useful).
|
| -
|
| - @type useCache: C{bool}
|
| - @param useCache: If set, and if capabilities have been
|
| - retrieved previously, just return the previously retrieved
|
| - results.
|
| -
|
| - @return: A Deferred which fires with a C{dict} mapping C{str}
|
| - to C{None} or C{list}s of C{str}. For example::
|
| -
|
| - C: CAPA
|
| - S: +OK Capability list follows
|
| - S: TOP
|
| - S: USER
|
| - S: SASL CRAM-MD5 KERBEROS_V4
|
| - S: RESP-CODES
|
| - S: LOGIN-DELAY 900
|
| - S: PIPELINING
|
| - S: EXPIRE 60
|
| - S: UIDL
|
| - S: IMPLEMENTATION Shlemazle-Plotz-v302
|
| - S: .
|
| -
|
| - will be lead to a result of::
|
| -
|
| - | {'TOP': None,
|
| - | 'USER': None,
|
| - | 'SASL': ['CRAM-MD5', 'KERBEROS_V4'],
|
| - | 'RESP-CODES': None,
|
| - | 'LOGIN-DELAY': ['900'],
|
| - | 'PIPELINING': None,
|
| - | 'EXPIRE': ['60'],
|
| - | 'UIDL': None,
|
| - | 'IMPLEMENTATION': ['Shlemazle-Plotz-v302']}
|
| - """
|
| - if useCache and self._capCache is not None:
|
| - return defer.succeed(self._capCache)
|
| -
|
| - cache = {}
|
| - def consume(line):
|
| - tmp = line.split()
|
| - if len(tmp) == 1:
|
| - cache[tmp[0]] = None
|
| - elif len(tmp) > 1:
|
| - cache[tmp[0]] = tmp[1:]
|
| -
|
| - def capaNotSupported(err):
|
| - err.trap(ServerErrorResponse)
|
| - return None
|
| -
|
| - def gotCapabilities(result):
|
| - self._capCache = cache
|
| - return cache
|
| -
|
| - d = self._consumeOrAppend('CAPA', None, consume, None)
|
| - d.addErrback(capaNotSupported).addCallback(gotCapabilities)
|
| - return d
|
| -
|
| -
|
| - def noop(self):
|
| - """Do nothing, with the help of the server.
|
| -
|
| - No operation is performed. The returned Deferred fires when
|
| - the server responds.
|
| - """
|
| - return self.sendShort("NOOP", None)
|
| -
|
| -
|
| - def reset(self):
|
| - """Remove the deleted flag from any messages which have it.
|
| -
|
| - The returned Deferred fires when the server responds.
|
| - """
|
| - return self.sendShort("RSET", None)
|
| -
|
| -
|
| - def retrieve(self, index, consumer=None, lines=None):
|
| - """Retrieve a message from the server.
|
| -
|
| - If L{consumer} is not None, it will be called with
|
| - each line of the message as it is received. Otherwise,
|
| - the returned Deferred will be fired with a list of all
|
| - the lines when the message has been completely received.
|
| - """
|
| - idx = str(index + 1)
|
| - if lines is None:
|
| - return self._consumeOrAppend('RETR', idx, consumer, _dotUnquoter)
|
| -
|
| - return self._consumeOrAppend('TOP', '%s %d' % (idx, lines), consumer, _dotUnquoter)
|
| -
|
| -
|
| - def stat(self):
|
| - """Get information about the size of this mailbox.
|
| -
|
| - The returned Deferred will be fired with a tuple containing
|
| - the number or messages in the mailbox and the size (in bytes)
|
| - of the mailbox.
|
| - """
|
| - return self.sendShort('STAT', None).addCallback(_statXform)
|
| -
|
| -
|
| - def listSize(self, consumer=None):
|
| - """Retrieve a list of the size of all messages on the server.
|
| -
|
| - If L{consumer} is not None, it will be called with two-tuples
|
| - of message index number and message size as they are received.
|
| - Otherwise, a Deferred which will fire with a list of B{only}
|
| - message sizes will be returned. For messages which have been
|
| - deleted, None will be used in place of the message size.
|
| - """
|
| - return self._consumeOrSetItem('LIST', None, consumer, _listXform)
|
| -
|
| -
|
| - def listUID(self, consumer=None):
|
| - """Retrieve a list of the UIDs of all messages on the server.
|
| -
|
| - If L{consumer} is not None, it will be called with two-tuples
|
| - of message index number and message UID as they are received.
|
| - Otherwise, a Deferred which will fire with of list of B{only}
|
| - message UIDs will be returned. For messages which have been
|
| - deleted, None will be used in place of the message UID.
|
| - """
|
| - return self._consumeOrSetItem('UIDL', None, consumer, _uidXform)
|
| -
|
| -
|
| - def quit(self):
|
| - """Disconnect from the server.
|
| - """
|
| - return self.sendShort('QUIT', None)
|
| -
|
| -__all__ = [
|
| - # Exceptions
|
| - 'InsecureAuthenticationDisallowed', 'LineTooLong', 'POP3ClientError',
|
| - 'ServerErrorResponse', 'TLSError', 'TLSNotSupportedError',
|
| -
|
| - # Protocol classes
|
| - 'POP3Client']
|
|
|