| Index: third_party/twisted_8_1/twisted/mail/mail.py
|
| diff --git a/third_party/twisted_8_1/twisted/mail/mail.py b/third_party/twisted_8_1/twisted/mail/mail.py
|
| deleted file mode 100644
|
| index 233c1b66fe132027f47bf5c4fc19ad7ad513daea..0000000000000000000000000000000000000000
|
| --- a/third_party/twisted_8_1/twisted/mail/mail.py
|
| +++ /dev/null
|
| @@ -1,333 +0,0 @@
|
| -# -*- test-case-name: twisted.mail.test.test_mail -*-
|
| -# Copyright (c) 2001-2007 Twisted Matrix Laboratories.
|
| -# See LICENSE for details.
|
| -
|
| -
|
| -"""Mail support for twisted python.
|
| -"""
|
| -
|
| -# Twisted imports
|
| -from twisted.internet import defer
|
| -from twisted.application import service, internet
|
| -from twisted.python import util
|
| -from twisted.python import log
|
| -
|
| -from twisted import cred
|
| -import twisted.cred.portal
|
| -
|
| -# Sibling imports
|
| -from twisted.mail import protocols, smtp
|
| -
|
| -# System imports
|
| -import os
|
| -from zope.interface import implements, Interface
|
| -
|
| -
|
| -class DomainWithDefaultDict:
|
| - '''Simulate a dictionary with a default value for non-existing keys.
|
| - '''
|
| - def __init__(self, domains, default):
|
| - self.domains = domains
|
| - self.default = default
|
| -
|
| - def setDefaultDomain(self, domain):
|
| - self.default = domain
|
| -
|
| - def has_key(self, name):
|
| - return 1
|
| -
|
| - def fromkeys(klass, keys, value=None):
|
| - d = klass()
|
| - for k in keys:
|
| - d[k] = value
|
| - return d
|
| - fromkeys = classmethod(fromkeys)
|
| -
|
| - def __contains__(self, name):
|
| - return 1
|
| -
|
| - def __getitem__(self, name):
|
| - return self.domains.get(name, self.default)
|
| -
|
| - def __setitem__(self, name, value):
|
| - self.domains[name] = value
|
| -
|
| - def __delitem__(self, name):
|
| - del self.domains[name]
|
| -
|
| - def __iter__(self):
|
| - return iter(self.domains)
|
| -
|
| - def __len__(self):
|
| - return len(self.domains)
|
| -
|
| -
|
| - def __str__(self):
|
| - """
|
| - Return a string describing the underlying domain mapping of this
|
| - object.
|
| - """
|
| - return '<DomainWithDefaultDict %s>' % (self.domains,)
|
| -
|
| -
|
| - def __repr__(self):
|
| - """
|
| - Return a pseudo-executable string describing the underlying domain
|
| - mapping of this object.
|
| - """
|
| - return 'DomainWithDefaultDict(%s)' % (self.domains,)
|
| -
|
| -
|
| - def get(self, key, default=None):
|
| - return self.domains.get(key, default)
|
| -
|
| - def copy(self):
|
| - return DomainWithDefaultDict(self.domains.copy(), self.default)
|
| -
|
| - def iteritems(self):
|
| - return self.domains.iteritems()
|
| -
|
| - def iterkeys(self):
|
| - return self.domains.iterkeys()
|
| -
|
| - def itervalues(self):
|
| - return self.domains.itervalues()
|
| -
|
| - def keys(self):
|
| - return self.domains.keys()
|
| -
|
| - def values(self):
|
| - return self.domains.values()
|
| -
|
| - def items(self):
|
| - return self.domains.items()
|
| -
|
| - def popitem(self):
|
| - return self.domains.popitem()
|
| -
|
| - def update(self, other):
|
| - return self.domains.update(other)
|
| -
|
| - def clear(self):
|
| - return self.domains.clear()
|
| -
|
| - def setdefault(self, key, default):
|
| - return self.domains.setdefault(key, default)
|
| -
|
| -class IDomain(Interface):
|
| - """An email domain."""
|
| -
|
| - def exists(user):
|
| - """
|
| - Check whether or not the specified user exists in this domain.
|
| -
|
| - @type user: C{twisted.protocols.smtp.User}
|
| - @param user: The user to check
|
| -
|
| - @rtype: No-argument callable
|
| - @return: A C{Deferred} which becomes, or a callable which
|
| - takes no arguments and returns an object implementing C{IMessage}.
|
| - This will be called and the returned object used to deliver the
|
| - message when it arrives.
|
| -
|
| - @raise twisted.protocols.smtp.SMTPBadRcpt: Raised if the given
|
| - user does not exist in this domain.
|
| - """
|
| -
|
| - def addUser(user, password):
|
| - """Add a username/password to this domain."""
|
| -
|
| - def startMessage(user):
|
| - """Create and return a new message to be delivered to the given user.
|
| -
|
| - DEPRECATED. Implement validateTo() correctly instead.
|
| - """
|
| -
|
| - def getCredentialsCheckers():
|
| - """Return a list of ICredentialsChecker implementors for this domain.
|
| - """
|
| -
|
| -class IAliasableDomain(IDomain):
|
| - def setAliasGroup(aliases):
|
| - """Set the group of defined aliases for this domain
|
| -
|
| - @type aliases: C{dict}
|
| - @param aliases: Mapping of domain names to objects implementing
|
| - C{IAlias}
|
| - """
|
| -
|
| - def exists(user, memo=None):
|
| - """
|
| - Check whether or not the specified user exists in this domain.
|
| -
|
| - @type user: C{twisted.protocols.smtp.User}
|
| - @param user: The user to check
|
| -
|
| - @type memo: C{dict}
|
| - @param memo: A record of the addresses already considered while
|
| - resolving aliases. The default value should be used by all
|
| - external code.
|
| -
|
| - @rtype: No-argument callable
|
| - @return: A C{Deferred} which becomes, or a callable which
|
| - takes no arguments and returns an object implementing C{IMessage}.
|
| - This will be called and the returned object used to deliver the
|
| - message when it arrives.
|
| -
|
| - @raise twisted.protocols.smtp.SMTPBadRcpt: Raised if the given
|
| - user does not exist in this domain.
|
| - """
|
| -
|
| -class BounceDomain:
|
| - """A domain in which no user exists.
|
| -
|
| - This can be used to block off certain domains.
|
| - """
|
| -
|
| - implements(IDomain)
|
| -
|
| - def exists(self, user):
|
| - raise smtp.SMTPBadRcpt(user)
|
| -
|
| - def willRelay(self, user, protocol):
|
| - return False
|
| -
|
| - def addUser(self, user, password):
|
| - pass
|
| -
|
| - def startMessage(self, user):
|
| - """
|
| - No code should ever call this function.
|
| - """
|
| - raise NotImplementedError(
|
| - "No code should ever call this method for any reason")
|
| -
|
| - def getCredentialsCheckers(self):
|
| - return []
|
| -
|
| -
|
| -class FileMessage:
|
| - """A file we can write an email too."""
|
| -
|
| - implements(smtp.IMessage)
|
| -
|
| - def __init__(self, fp, name, finalName):
|
| - self.fp = fp
|
| - self.name = name
|
| - self.finalName = finalName
|
| -
|
| - def lineReceived(self, line):
|
| - self.fp.write(line+'\n')
|
| -
|
| - def eomReceived(self):
|
| - self.fp.close()
|
| - os.rename(self.name, self.finalName)
|
| - return defer.succeed(self.finalName)
|
| -
|
| - def connectionLost(self):
|
| - self.fp.close()
|
| - os.remove(self.name)
|
| -
|
| -
|
| -class MailService(service.MultiService):
|
| - """An email service."""
|
| -
|
| - queue = None
|
| - domains = None
|
| - portals = None
|
| - aliases = None
|
| - smtpPortal = None
|
| -
|
| - def __init__(self):
|
| - service.MultiService.__init__(self)
|
| - # Domains and portals for "client" protocols - POP3, IMAP4, etc
|
| - self.domains = DomainWithDefaultDict({}, BounceDomain())
|
| - self.portals = {}
|
| -
|
| - self.monitor = FileMonitoringService()
|
| - self.monitor.setServiceParent(self)
|
| - self.smtpPortal = cred.portal.Portal(self)
|
| -
|
| - def getPOP3Factory(self):
|
| - return protocols.POP3Factory(self)
|
| -
|
| - def getSMTPFactory(self):
|
| - return protocols.SMTPFactory(self, self.smtpPortal)
|
| -
|
| - def getESMTPFactory(self):
|
| - return protocols.ESMTPFactory(self, self.smtpPortal)
|
| -
|
| - def addDomain(self, name, domain):
|
| - portal = cred.portal.Portal(domain)
|
| - map(portal.registerChecker, domain.getCredentialsCheckers())
|
| - self.domains[name] = domain
|
| - self.portals[name] = portal
|
| - if self.aliases and IAliasableDomain.providedBy(domain):
|
| - domain.setAliasGroup(self.aliases)
|
| -
|
| - def setQueue(self, queue):
|
| - """Set the queue for outgoing emails."""
|
| - self.queue = queue
|
| -
|
| - def requestAvatar(self, avatarId, mind, *interfaces):
|
| - if smtp.IMessageDelivery in interfaces:
|
| - a = protocols.ESMTPDomainDelivery(self, avatarId)
|
| - return smtp.IMessageDelivery, a, lambda: None
|
| - raise NotImplementedError()
|
| -
|
| - def lookupPortal(self, name):
|
| - return self.portals[name]
|
| -
|
| - def defaultPortal(self):
|
| - return self.portals['']
|
| -
|
| -
|
| -class FileMonitoringService(internet.TimerService):
|
| -
|
| - def __init__(self):
|
| - self.files = []
|
| - self.intervals = iter(util.IntervalDifferential([], 60))
|
| -
|
| - def startService(self):
|
| - service.Service.startService(self)
|
| - self._setupMonitor()
|
| -
|
| - def _setupMonitor(self):
|
| - from twisted.internet import reactor
|
| - t, self.index = self.intervals.next()
|
| - self._call = reactor.callLater(t, self._monitor)
|
| -
|
| - def stopService(self):
|
| - service.Service.stopService(self)
|
| - if self._call:
|
| - self._call.cancel()
|
| - self._call = None
|
| -
|
| - def monitorFile(self, name, callback, interval=10):
|
| - try:
|
| - mtime = os.path.getmtime(name)
|
| - except:
|
| - mtime = 0
|
| - self.files.append([interval, name, callback, mtime])
|
| - self.intervals.addInterval(interval)
|
| -
|
| - def unmonitorFile(self, name):
|
| - for i in range(len(self.files)):
|
| - if name == self.files[i][1]:
|
| - self.intervals.removeInterval(self.files[i][0])
|
| - del self.files[i]
|
| - break
|
| -
|
| - def _monitor(self):
|
| - self._call = None
|
| - if self.index is not None:
|
| - name, callback, mtime = self.files[self.index][1:]
|
| - try:
|
| - now = os.path.getmtime(name)
|
| - except:
|
| - now = 0
|
| - if now > mtime:
|
| - log.msg("%s changed, notifying listener" % (name,))
|
| - self.files[self.index][3] = now
|
| - callback(name)
|
| - self._setupMonitor()
|
|
|