Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1435)

Unified Diff: third_party/twisted_8_1/twisted/mail/pop3.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/twisted_8_1/twisted/mail/pb.py ('k') | third_party/twisted_8_1/twisted/mail/pop3client.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/twisted_8_1/twisted/mail/pop3.py
diff --git a/third_party/twisted_8_1/twisted/mail/pop3.py b/third_party/twisted_8_1/twisted/mail/pop3.py
deleted file mode 100644
index 5c3dd1373bce3a4e3f62017a179b9f6cb2481717..0000000000000000000000000000000000000000
--- a/third_party/twisted_8_1/twisted/mail/pop3.py
+++ /dev/null
@@ -1,1072 +0,0 @@
-# -*- test-case-name: twisted.mail.test.test_pop3 -*-
-#
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-
-"""
-Post-office Protocol version 3
-
-@author: U{Glyph Lefkowitz<mailto:glyph@twistedmatrix.com>}
-@author: U{Jp Calderone<mailto:exarkun@twistedmatrix.com>}
-"""
-
-import string
-import base64
-import binascii
-import md5
-import warnings
-
-from zope.interface import implements, Interface
-
-from twisted.mail import smtp
-from twisted.protocols import basic
-from twisted.protocols import policies
-from twisted.internet import task
-from twisted.internet import defer
-from twisted.internet import interfaces
-from twisted.python import log
-
-from twisted import cred
-import twisted.cred.error
-import twisted.cred.credentials
-
-##
-## Authentication
-##
-class APOPCredentials:
- implements(cred.credentials.IUsernamePassword)
-
- def __init__(self, magic, username, digest):
- self.magic = magic
- self.username = username
- self.digest = digest
-
- def checkPassword(self, password):
- seed = self.magic + password
- myDigest = md5.new(seed).hexdigest()
- return myDigest == self.digest
-
-
-class _HeadersPlusNLines:
- def __init__(self, f, n):
- self.f = f
- self.n = n
- self.linecount = 0
- self.headers = 1
- self.done = 0
- self.buf = ''
-
- def read(self, bytes):
- if self.done:
- return ''
- data = self.f.read(bytes)
- if not data:
- return data
- if self.headers:
- df, sz = data.find('\r\n\r\n'), 4
- if df == -1:
- df, sz = data.find('\n\n'), 2
- if df != -1:
- df += sz
- val = data[:df]
- data = data[df:]
- self.linecount = 1
- self.headers = 0
- else:
- val = ''
- if self.linecount > 0:
- dsplit = (self.buf+data).split('\n')
- self.buf = dsplit[-1]
- for ln in dsplit[:-1]:
- if self.linecount > self.n:
- self.done = 1
- return val
- val += (ln + '\n')
- self.linecount += 1
- return val
- else:
- return data
-
-
-
-class _POP3MessageDeleted(Exception):
- """
- Internal control-flow exception. Indicates the file of a deleted message
- was requested.
- """
-
-
-class POP3Error(Exception):
- pass
-
-
-
-class _IteratorBuffer(object):
- bufSize = 0
-
- def __init__(self, write, iterable, memoryBufferSize=None):
- """
- Create a _IteratorBuffer.
-
- @param write: A one-argument callable which will be invoked with a list
- of strings which have been buffered.
-
- @param iterable: The source of input strings as any iterable.
-
- @param memoryBufferSize: The upper limit on buffered string length,
- beyond which the buffer will be flushed to the writer.
- """
- self.lines = []
- self.write = write
- self.iterator = iter(iterable)
- if memoryBufferSize is None:
- memoryBufferSize = 2 ** 16
- self.memoryBufferSize = memoryBufferSize
-
-
- def __iter__(self):
- return self
-
-
- def next(self):
- try:
- v = self.iterator.next()
- except StopIteration:
- if self.lines:
- self.write(self.lines)
- # Drop some references, in case they're edges in a cycle.
- del self.iterator, self.lines, self.write
- raise
- else:
- if v is not None:
- self.lines.append(v)
- self.bufSize += len(v)
- if self.bufSize > self.memoryBufferSize:
- self.write(self.lines)
- self.lines = []
- self.bufSize = 0
-
-
-
-def iterateLineGenerator(proto, gen):
- """
- Hook the given protocol instance up to the given iterator with an
- _IteratorBuffer and schedule the result to be exhausted via the protocol.
-
- @type proto: L{POP3}
- @type gen: iterator
- @rtype: L{twisted.internet.defer.Deferred}
- """
- coll = _IteratorBuffer(proto.transport.writeSequence, gen)
- return proto.schedule(coll)
-
-
-
-def successResponse(response):
- """
- Format the given object as a positive response.
- """
- response = str(response)
- return '+OK %s\r\n' % (response,)
-
-
-
-def formatStatResponse(msgs):
- """
- Format the list of message sizes appropriately for a STAT response.
-
- Yields None until it finishes computing a result, then yields a str
- instance that is suitable for use as a response to the STAT command.
- Intended to be used with a L{twisted.internet.task.Cooperator}.
- """
- i = 0
- bytes = 0
- for size in msgs:
- i += 1
- bytes += size
- yield None
- yield successResponse('%d %d' % (i, bytes))
-
-
-
-def formatListLines(msgs):
- """
- Format a list of message sizes appropriately for the lines of a LIST
- response.
-
- Yields str instances formatted appropriately for use as lines in the
- response to the LIST command. Does not include the trailing '.'.
- """
- i = 0
- for size in msgs:
- i += 1
- yield '%d %d\r\n' % (i, size)
-
-
-
-def formatListResponse(msgs):
- """
- Format a list of message sizes appropriately for a complete LIST response.
-
- Yields str instances formatted appropriately for use as a LIST command
- response.
- """
- yield successResponse(len(msgs))
- for ele in formatListLines(msgs):
- yield ele
- yield '.\r\n'
-
-
-
-def formatUIDListLines(msgs, getUidl):
- """
- Format the list of message sizes appropriately for the lines of a UIDL
- response.
-
- Yields str instances formatted appropriately for use as lines in the
- response to the UIDL command. Does not include the trailing '.'.
- """
- for i, m in enumerate(msgs):
- if m is not None:
- uid = getUidl(i)
- yield '%d %s\r\n' % (i + 1, uid)
-
-
-
-def formatUIDListResponse(msgs, getUidl):
- """
- Format a list of message sizes appropriately for a complete UIDL response.
-
- Yields str instances formatted appropriately for use as a UIDL command
- response.
- """
- yield successResponse('')
- for ele in formatUIDListLines(msgs, getUidl):
- yield ele
- yield '.\r\n'
-
-
-
-class POP3(basic.LineOnlyReceiver, policies.TimeoutMixin):
- """
- POP3 server protocol implementation.
-
- @ivar portal: A reference to the L{twisted.cred.portal.Portal} instance we
- will authenticate through.
-
- @ivar factory: A L{twisted.mail.pop3.IServerFactory} which will be used to
- determine some extended behavior of the server.
-
- @ivar timeOut: An integer which defines the minimum amount of time which
- may elapse without receiving any traffic after which the client will be
- disconnected.
-
- @ivar schedule: A one-argument callable which should behave like
- L{twisted.internet.task.coiterate}.
- """
- implements(interfaces.IProducer)
-
- magic = None
- _userIs = None
- _onLogout = None
-
- AUTH_CMDS = ['CAPA', 'USER', 'PASS', 'APOP', 'AUTH', 'RPOP', 'QUIT']
-
- portal = None
- factory = None
-
- # The mailbox we're serving
- mbox = None
-
- # Set this pretty low -- POP3 clients are expected to log in, download
- # everything, and log out.
- timeOut = 300
-
- # Current protocol state
- state = "COMMAND"
-
- # PIPELINE
- blocked = None
-
- # Cooperate and suchlike.
- schedule = staticmethod(task.coiterate)
-
- # Message index of the highest retrieved message.
- _highest = 0
-
- def connectionMade(self):
- if self.magic is None:
- self.magic = self.generateMagic()
- self.successResponse(self.magic)
- self.setTimeout(self.timeOut)
- if getattr(self.factory, 'noisy', True):
- log.msg("New connection from " + str(self.transport.getPeer()))
-
-
- def connectionLost(self, reason):
- if self._onLogout is not None:
- self._onLogout()
- self._onLogout = None
- self.setTimeout(None)
-
-
- def generateMagic(self):
- return smtp.messageid()
-
-
- def successResponse(self, message=''):
- self.transport.write(successResponse(message))
-
- def failResponse(self, message=''):
- self.sendLine('-ERR ' + str(message))
-
-# def sendLine(self, line):
-# print 'S:', repr(line)
-# basic.LineOnlyReceiver.sendLine(self, line)
-
- def lineReceived(self, line):
-# print 'C:', repr(line)
- self.resetTimeout()
- getattr(self, 'state_' + self.state)(line)
-
- def _unblock(self, _):
- commands = self.blocked
- self.blocked = None
- while commands and self.blocked is None:
- cmd, args = commands.pop(0)
- self.processCommand(cmd, *args)
- if self.blocked is not None:
- self.blocked.extend(commands)
-
- def state_COMMAND(self, line):
- try:
- return self.processCommand(*line.split(' '))
- except (ValueError, AttributeError, POP3Error, TypeError), e:
- log.err()
- self.failResponse('bad protocol or server: %s: %s' % (e.__class__.__name__, e))
-
- def processCommand(self, command, *args):
- if self.blocked is not None:
- self.blocked.append((command, args))
- return
-
- command = string.upper(command)
- authCmd = command in self.AUTH_CMDS
- if not self.mbox and not authCmd:
- raise POP3Error("not authenticated yet: cannot do " + command)
- f = getattr(self, 'do_' + command, None)
- if f:
- return f(*args)
- raise POP3Error("Unknown protocol command: " + command)
-
-
- def listCapabilities(self):
- baseCaps = [
- "TOP",
- "USER",
- "UIDL",
- "PIPELINE",
- "CELERITY",
- "AUSPEX",
- "POTENCE",
- ]
-
- if IServerFactory.providedBy(self.factory):
- # Oh my god. We can't just loop over a list of these because
- # each has spectacularly different return value semantics!
- try:
- v = self.factory.cap_IMPLEMENTATION()
- except NotImplementedError:
- pass
- except:
- log.err()
- else:
- baseCaps.append("IMPLEMENTATION " + str(v))
-
- try:
- v = self.factory.cap_EXPIRE()
- except NotImplementedError:
- pass
- except:
- log.err()
- else:
- if v is None:
- v = "NEVER"
- if self.factory.perUserExpiration():
- if self.mbox:
- v = str(self.mbox.messageExpiration)
- else:
- v = str(v) + " USER"
- v = str(v)
- baseCaps.append("EXPIRE " + v)
-
- try:
- v = self.factory.cap_LOGIN_DELAY()
- except NotImplementedError:
- pass
- except:
- log.err()
- else:
- if self.factory.perUserLoginDelay():
- if self.mbox:
- v = str(self.mbox.loginDelay)
- else:
- v = str(v) + " USER"
- v = str(v)
- baseCaps.append("LOGIN-DELAY " + v)
-
- try:
- v = self.factory.challengers
- except AttributeError:
- pass
- except:
- log.err()
- else:
- baseCaps.append("SASL " + ' '.join(v.keys()))
- return baseCaps
-
- def do_CAPA(self):
- self.successResponse("I can do the following:")
- for cap in self.listCapabilities():
- self.sendLine(cap)
- self.sendLine(".")
-
- def do_AUTH(self, args=None):
- if not getattr(self.factory, 'challengers', None):
- self.failResponse("AUTH extension unsupported")
- return
-
- if args is None:
- self.successResponse("Supported authentication methods:")
- for a in self.factory.challengers:
- self.sendLine(a.upper())
- self.sendLine(".")
- return
-
- auth = self.factory.challengers.get(args.strip().upper())
- if not self.portal or not auth:
- self.failResponse("Unsupported SASL selected")
- return
-
- self._auth = auth()
- chal = self._auth.getChallenge()
-
- self.sendLine('+ ' + base64.encodestring(chal).rstrip('\n'))
- self.state = 'AUTH'
-
- def state_AUTH(self, line):
- self.state = "COMMAND"
- try:
- parts = base64.decodestring(line).split(None, 1)
- except binascii.Error:
- self.failResponse("Invalid BASE64 encoding")
- else:
- if len(parts) != 2:
- self.failResponse("Invalid AUTH response")
- return
- self._auth.username = parts[0]
- self._auth.response = parts[1]
- d = self.portal.login(self._auth, None, IMailbox)
- d.addCallback(self._cbMailbox, parts[0])
- d.addErrback(self._ebMailbox)
- d.addErrback(self._ebUnexpected)
-
- def do_APOP(self, user, digest):
- d = defer.maybeDeferred(self.authenticateUserAPOP, user, digest)
- d.addCallbacks(self._cbMailbox, self._ebMailbox, callbackArgs=(user,)
- ).addErrback(self._ebUnexpected)
-
- def _cbMailbox(self, (interface, avatar, logout), user):
- if interface is not IMailbox:
- self.failResponse('Authentication failed')
- log.err("_cbMailbox() called with an interface other than IMailbox")
- return
-
- self.mbox = avatar
- self._onLogout = logout
- self.successResponse('Authentication succeeded')
- if getattr(self.factory, 'noisy', True):
- log.msg("Authenticated login for " + user)
-
- def _ebMailbox(self, failure):
- failure = failure.trap(cred.error.LoginDenied, cred.error.LoginFailed)
- if issubclass(failure, cred.error.LoginDenied):
- self.failResponse("Access denied: " + str(failure))
- elif issubclass(failure, cred.error.LoginFailed):
- self.failResponse('Authentication failed')
- if getattr(self.factory, 'noisy', True):
- log.msg("Denied login attempt from " + str(self.transport.getPeer()))
-
- def _ebUnexpected(self, failure):
- self.failResponse('Server error: ' + failure.getErrorMessage())
- log.err(failure)
-
- def do_USER(self, user):
- self._userIs = user
- self.successResponse('USER accepted, send PASS')
-
- def do_PASS(self, password):
- if self._userIs is None:
- self.failResponse("USER required before PASS")
- return
- user = self._userIs
- self._userIs = None
- d = defer.maybeDeferred(self.authenticateUserPASS, user, password)
- d.addCallbacks(self._cbMailbox, self._ebMailbox, callbackArgs=(user,)
- ).addErrback(self._ebUnexpected)
-
-
- def _longOperation(self, d):
- # Turn off timeouts and block further processing until the Deferred
- # fires, then reverse those changes.
- timeOut = self.timeOut
- self.setTimeout(None)
- self.blocked = []
- d.addCallback(self._unblock)
- d.addCallback(lambda ign: self.setTimeout(timeOut))
- return d
-
-
- def _coiterate(self, gen):
- return self.schedule(_IteratorBuffer(self.transport.writeSequence, gen))
-
-
- def do_STAT(self):
- d = defer.maybeDeferred(self.mbox.listMessages)
- def cbMessages(msgs):
- return self._coiterate(formatStatResponse(msgs))
- def ebMessages(err):
- self.failResponse(err.getErrorMessage())
- log.msg("Unexpected do_STAT failure:")
- log.err(err)
- return self._longOperation(d.addCallbacks(cbMessages, ebMessages))
-
-
- def do_LIST(self, i=None):
- if i is None:
- d = defer.maybeDeferred(self.mbox.listMessages)
- def cbMessages(msgs):
- return self._coiterate(formatListResponse(msgs))
- def ebMessages(err):
- self.failResponse(err.getErrorMessage())
- log.msg("Unexpected do_LIST failure:")
- log.err(err)
- return self._longOperation(d.addCallbacks(cbMessages, ebMessages))
- else:
- try:
- i = int(i)
- if i < 1:
- raise ValueError()
- except ValueError:
- self.failResponse("Invalid message-number: %r" % (i,))
- else:
- d = defer.maybeDeferred(self.mbox.listMessages, i - 1)
- def cbMessage(msg):
- self.successResponse('%d %d' % (i, msg))
- def ebMessage(err):
- errcls = err.check(ValueError, IndexError)
- if errcls is not None:
- if errcls is IndexError:
- # IndexError was supported for a while, but really
- # shouldn't be. One error condition, one exception
- # type.
- warnings.warn(
- "twisted.mail.pop3.IMailbox.listMessages may not "
- "raise IndexError for out-of-bounds message numbers: "
- "raise ValueError instead.",
- PendingDeprecationWarning)
- self.failResponse("Invalid message-number: %r" % (i,))
- else:
- self.failResponse(err.getErrorMessage())
- log.msg("Unexpected do_LIST failure:")
- log.err(err)
- return self._longOperation(d.addCallbacks(cbMessage, ebMessage))
-
-
- def do_UIDL(self, i=None):
- if i is None:
- d = defer.maybeDeferred(self.mbox.listMessages)
- def cbMessages(msgs):
- return self._coiterate(formatUIDListResponse(msgs, self.mbox.getUidl))
- def ebMessages(err):
- self.failResponse(err.getErrorMessage())
- log.msg("Unexpected do_UIDL failure:")
- log.err(err)
- return self._longOperation(d.addCallbacks(cbMessages, ebMessages))
- else:
- try:
- i = int(i)
- if i < 1:
- raise ValueError()
- except ValueError:
- self.failResponse("Bad message number argument")
- else:
- try:
- msg = self.mbox.getUidl(i - 1)
- except IndexError:
- # XXX TODO See above comment regarding IndexError.
- warnings.warn(
- "twisted.mail.pop3.IMailbox.getUidl may not "
- "raise IndexError for out-of-bounds message numbers: "
- "raise ValueError instead.",
- PendingDeprecationWarning)
- self.failResponse("Bad message number argument")
- except ValueError:
- self.failResponse("Bad message number argument")
- else:
- self.successResponse(str(msg))
-
-
- def _getMessageFile(self, i):
- """
- Retrieve the size and contents of a given message, as a two-tuple.
-
- @param i: The number of the message to operate on. This is a base-ten
- string representation starting at 1.
-
- @return: A Deferred which fires with a two-tuple of an integer and a
- file-like object.
- """
- try:
- msg = int(i) - 1
- if msg < 0:
- raise ValueError()
- except ValueError:
- self.failResponse("Bad message number argument")
- return defer.succeed(None)
-
- sizeDeferred = defer.maybeDeferred(self.mbox.listMessages, msg)
- def cbMessageSize(size):
- if not size:
- return defer.fail(_POP3MessageDeleted())
- fileDeferred = defer.maybeDeferred(self.mbox.getMessage, msg)
- fileDeferred.addCallback(lambda fObj: (size, fObj))
- return fileDeferred
-
- def ebMessageSomething(err):
- errcls = err.check(_POP3MessageDeleted, ValueError, IndexError)
- if errcls is _POP3MessageDeleted:
- self.failResponse("message deleted")
- elif errcls in (ValueError, IndexError):
- if errcls is IndexError:
- # XXX TODO See above comment regarding IndexError.
- warnings.warn(
- "twisted.mail.pop3.IMailbox.listMessages may not "
- "raise IndexError for out-of-bounds message numbers: "
- "raise ValueError instead.",
- PendingDeprecationWarning)
- self.failResponse("Bad message number argument")
- else:
- log.msg("Unexpected _getMessageFile failure:")
- log.err(err)
- return None
-
- sizeDeferred.addCallback(cbMessageSize)
- sizeDeferred.addErrback(ebMessageSomething)
- return sizeDeferred
-
-
- def _sendMessageContent(self, i, fpWrapper, successResponse):
- d = self._getMessageFile(i)
- def cbMessageFile(info):
- if info is None:
- # Some error occurred - a failure response has been sent
- # already, just give up.
- return
-
- self._highest = max(self._highest, int(i))
- resp, fp = info
- fp = fpWrapper(fp)
- self.successResponse(successResponse(resp))
- s = basic.FileSender()
- d = s.beginFileTransfer(fp, self.transport, self.transformChunk)
-
- def cbFileTransfer(lastsent):
- if lastsent != '\n':
- line = '\r\n.'
- else:
- line = '.'
- self.sendLine(line)
-
- def ebFileTransfer(err):
- self.transport.loseConnection()
- log.msg("Unexpected error in _sendMessageContent:")
- log.err(err)
-
- d.addCallback(cbFileTransfer)
- d.addErrback(ebFileTransfer)
- return d
- return self._longOperation(d.addCallback(cbMessageFile))
-
-
- def do_TOP(self, i, size):
- try:
- size = int(size)
- if size < 0:
- raise ValueError
- except ValueError:
- self.failResponse("Bad line count argument")
- else:
- return self._sendMessageContent(
- i,
- lambda fp: _HeadersPlusNLines(fp, size),
- lambda size: "Top of message follows")
-
-
- def do_RETR(self, i):
- return self._sendMessageContent(
- i,
- lambda fp: fp,
- lambda size: "%d" % (size,))
-
-
- def transformChunk(self, chunk):
- return chunk.replace('\n', '\r\n').replace('\r\n.', '\r\n..')
-
-
- def finishedFileTransfer(self, lastsent):
- if lastsent != '\n':
- line = '\r\n.'
- else:
- line = '.'
- self.sendLine(line)
-
-
- def do_DELE(self, i):
- i = int(i)-1
- self.mbox.deleteMessage(i)
- self.successResponse()
-
-
- def do_NOOP(self):
- """Perform no operation. Return a success code"""
- self.successResponse()
-
-
- def do_RSET(self):
- """Unset all deleted message flags"""
- try:
- self.mbox.undeleteMessages()
- except:
- log.err()
- self.failResponse()
- else:
- self._highest = 0
- self.successResponse()
-
-
- def do_LAST(self):
- """
- Return the index of the highest message yet downloaded.
- """
- self.successResponse(self._highest)
-
-
- def do_RPOP(self, user):
- self.failResponse('permission denied, sucker')
-
-
- def do_QUIT(self):
- if self.mbox:
- self.mbox.sync()
- self.successResponse()
- self.transport.loseConnection()
-
-
- def authenticateUserAPOP(self, user, digest):
- """Perform authentication of an APOP login.
-
- @type user: C{str}
- @param user: The name of the user attempting to log in.
-
- @type digest: C{str}
- @param digest: The response string with which the user replied.
-
- @rtype: C{Deferred}
- @return: A deferred whose callback is invoked if the login is
- successful, and whose errback will be invoked otherwise. The
- callback will be passed a 3-tuple consisting of IMailbox,
- an object implementing IMailbox, and a zero-argument callable
- to be invoked when this session is terminated.
- """
- if self.portal is not None:
- return self.portal.login(
- APOPCredentials(self.magic, user, digest),
- None,
- IMailbox
- )
- raise cred.error.UnauthorizedLogin()
-
- def authenticateUserPASS(self, user, password):
- """Perform authentication of a username/password login.
-
- @type user: C{str}
- @param user: The name of the user attempting to log in.
-
- @type password: C{str}
- @param password: The password to attempt to authenticate with.
-
- @rtype: C{Deferred}
- @return: A deferred whose callback is invoked if the login is
- successful, and whose errback will be invoked otherwise. The
- callback will be passed a 3-tuple consisting of IMailbox,
- an object implementing IMailbox, and a zero-argument callable
- to be invoked when this session is terminated.
- """
- if self.portal is not None:
- return self.portal.login(
- cred.credentials.UsernamePassword(user, password),
- None,
- IMailbox
- )
- raise cred.error.UnauthorizedLogin()
-
-
-class IServerFactory(Interface):
- """Interface for querying additional parameters of this POP3 server.
-
- Any cap_* method may raise NotImplementedError if the particular
- capability is not supported. If cap_EXPIRE() does not raise
- NotImplementedError, perUserExpiration() must be implemented, otherwise
- they are optional. If cap_LOGIN_DELAY() is implemented,
- perUserLoginDelay() must be implemented, otherwise they are optional.
-
- @ivar challengers: A dictionary mapping challenger names to classes
- implementing C{IUsernameHashedPassword}.
- """
-
- def cap_IMPLEMENTATION():
- """Return a string describing this POP3 server implementation."""
-
- def cap_EXPIRE():
- """Return the minimum number of days messages are retained."""
-
- def perUserExpiration():
- """Indicate whether message expiration is per-user.
-
- @return: True if it is, false otherwise.
- """
-
- def cap_LOGIN_DELAY():
- """Return the minimum number of seconds between client logins."""
-
- def perUserLoginDelay():
- """Indicate whether the login delay period is per-user.
-
- @return: True if it is, false otherwise.
- """
-
-class IMailbox(Interface):
- """
- @type loginDelay: C{int}
- @ivar loginDelay: The number of seconds between allowed logins for the
- user associated with this mailbox. None
-
- @type messageExpiration: C{int}
- @ivar messageExpiration: The number of days messages in this mailbox will
- remain on the server before being deleted.
- """
-
- def listMessages(index=None):
- """Retrieve the size of one or more messages.
-
- @type index: C{int} or C{None}
- @param index: The number of the message for which to retrieve the
- size (starting at 0), or None to retrieve the size of all messages.
-
- @rtype: C{int} or any iterable of C{int} or a L{Deferred} which fires
- with one of these.
-
- @return: The number of octets in the specified message, or an iterable
- of integers representing the number of octets in all the messages. Any
- value which would have referred to a deleted message should be set to 0.
-
- @raise ValueError: if C{index} is greater than the index of any message
- in the mailbox.
- """
-
- def getMessage(index):
- """Retrieve a file-like object for a particular message.
-
- @type index: C{int}
- @param index: The number of the message to retrieve
-
- @rtype: A file-like object
- @return: A file containing the message data with lines delimited by
- C{\\n}.
- """
-
- def getUidl(index):
- """Get a unique identifier for a particular message.
-
- @type index: C{int}
- @param index: The number of the message for which to retrieve a UIDL
-
- @rtype: C{str}
- @return: A string of printable characters uniquely identifying for all
- time the specified message.
-
- @raise ValueError: if C{index} is greater than the index of any message
- in the mailbox.
- """
-
- def deleteMessage(index):
- """Delete a particular message.
-
- This must not change the number of messages in this mailbox. Further
- requests for the size of deleted messages should return 0. Further
- requests for the message itself may raise an exception.
-
- @type index: C{int}
- @param index: The number of the message to delete.
- """
-
- def undeleteMessages():
- """
- Undelete any messages which have been marked for deletion since the
- most recent L{sync} call.
-
- Any message which can be undeleted should be returned to its
- original position in the message sequence and retain its original
- UID.
- """
-
- def sync():
- """Perform checkpointing.
-
- This method will be called to indicate the mailbox should attempt to
- clean up any remaining deleted messages.
- """
-
-
-
-class Mailbox:
- implements(IMailbox)
-
- def listMessages(self, i=None):
- return []
- def getMessage(self, i):
- raise ValueError
- def getUidl(self, i):
- raise ValueError
- def deleteMessage(self, i):
- raise ValueError
- def undeleteMessages(self):
- pass
- def sync(self):
- pass
-
-
-NONE, SHORT, FIRST_LONG, LONG = range(4)
-
-NEXT = {}
-NEXT[NONE] = NONE
-NEXT[SHORT] = NONE
-NEXT[FIRST_LONG] = LONG
-NEXT[LONG] = NONE
-
-class POP3Client(basic.LineOnlyReceiver):
-
- mode = SHORT
- command = 'WELCOME'
- import re
- welcomeRe = re.compile('<(.*)>')
-
- def __init__(self):
- import warnings
- warnings.warn("twisted.mail.pop3.POP3Client is deprecated, "
- "please use twisted.mail.pop3.AdvancedPOP3Client "
- "instead.", DeprecationWarning,
- stacklevel=3)
-
- def sendShort(self, command, params=None):
- if params is not None:
- self.sendLine('%s %s' % (command, params))
- else:
- self.sendLine(command)
- self.command = command
- self.mode = SHORT
-
- def sendLong(self, command, params):
- if params:
- self.sendLine('%s %s' % (command, params))
- else:
- self.sendLine(command)
- self.command = command
- self.mode = FIRST_LONG
-
- def handle_default(self, line):
- if line[:-4] == '-ERR':
- self.mode = NONE
-
- def handle_WELCOME(self, line):
- code, data = line.split(' ', 1)
- if code != '+OK':
- self.transport.loseConnection()
- else:
- m = self.welcomeRe.match(line)
- if m:
- self.welcomeCode = m.group(1)
-
- def _dispatch(self, command, default, *args):
- try:
- method = getattr(self, 'handle_'+command, default)
- if method is not None:
- method(*args)
- except:
- log.err()
-
- def lineReceived(self, line):
- if self.mode == SHORT or self.mode == FIRST_LONG:
- self.mode = NEXT[self.mode]
- self._dispatch(self.command, self.handle_default, line)
- elif self.mode == LONG:
- if line == '.':
- self.mode = NEXT[self.mode]
- self._dispatch(self.command+'_end', None)
- return
- if line[:1] == '.':
- line = line[1:]
- self._dispatch(self.command+"_continue", None, line)
-
- def apopAuthenticate(self, user, password, magic):
- digest = md5.new(magic + password).hexdigest()
- self.apop(user, digest)
-
- def apop(self, user, digest):
- self.sendLong('APOP', ' '.join((user, digest)))
- def retr(self, i):
- self.sendLong('RETR', i)
- def dele(self, i):
- self.sendShort('DELE', i)
- def list(self, i=''):
- self.sendLong('LIST', i)
- def uidl(self, i=''):
- self.sendLong('UIDL', i)
- def user(self, name):
- self.sendShort('USER', name)
- def pass_(self, pass_):
- self.sendShort('PASS', pass_)
- def quit(self):
- self.sendShort('QUIT')
-
-from twisted.mail.pop3client import POP3Client as AdvancedPOP3Client
-from twisted.mail.pop3client import POP3ClientError
-from twisted.mail.pop3client import InsecureAuthenticationDisallowed
-from twisted.mail.pop3client import ServerErrorResponse
-from twisted.mail.pop3client import LineTooLong
-
-__all__ = [
- # Interfaces
- 'IMailbox', 'IServerFactory',
-
- # Exceptions
- 'POP3Error', 'POP3ClientError', 'InsecureAuthenticationDisallowed',
- 'ServerErrorResponse', 'LineTooLong',
-
- # Protocol classes
- 'POP3', 'POP3Client', 'AdvancedPOP3Client',
-
- # Misc
- 'APOPCredentials', 'Mailbox']
« no previous file with comments | « third_party/twisted_8_1/twisted/mail/pb.py ('k') | third_party/twisted_8_1/twisted/mail/pop3client.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698