diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/leap/mx/alias_resolver.py | 113 |
1 files changed, 88 insertions, 25 deletions
diff --git a/src/leap/mx/alias_resolver.py b/src/leap/mx/alias_resolver.py index 12b29fd..4774d78 100644 --- a/src/leap/mx/alias_resolver.py +++ b/src/leap/mx/alias_resolver.py @@ -22,10 +22,10 @@ except ImportError: print "This software requires Twisted. Please see the README file" print "for instructions on getting required dependencies." -from leap.mx import net, log ## xxx implement log +from leap.mx.util import net, log, config, exceptions -def createID(alias): +def aliasToUUID(alias): """ Creates Universal Unique ID by taking the SHA-1 HASH of an email alias: @@ -91,50 +91,113 @@ class AliasResolver(postfix.PostfixTCPMapServer): query the local Postfix server. You can test it with: $ ./alias_resolver.py & - $ /usr/bin/postmap -q <key> tcp:localhost:4242 + $ /usr/bin/postmap -q <key> tcp:localhost:1347 + Resources: + http://www.postfix.org/proxymap.8.html + https://www.iana.org/assignments/smtp-enhanced-status-codes/smtp-enhanced-status-codes.txt """ def __init__(self, *args, **kwargs): + """Create a server which listens for Postfix aliases to resolve.""" + super(postfix.PostfixTCPMapServer, self).__init__(*args, **kwargs) + self.status_codes = StatusCodes() + + def sendCode(self, code, message=None): + """Send an SMTP-like code with a message.""" + if not message: + message = self.status_codes.get(code) + self.sendLine('%3.3d %s' % (code, message or '')) + + def do_get(self, key): + """Make a query to resolve an alias.""" + if key is None: + self.sendCode(500) + log.warn("Command 'get' takes one parameter.") + else: + d = defer.maybeDeferred(self.factory.get, key) + d.addCallbacks(self._cbGot, self._cbNot) + d.addErrback(log.err) + + def do_query(self, key): + """Make a query to resolve an alias.""" + self.do_get(self, key) + + @defer.inlineCallbacks + def do_put(self, keyAndValue): + """Add a key and value to the database, provided it does not exist.""" + if keyAndValue is None: + self.sendCode(500) + log.warn("Command 'put' takes two parameters.") + else: + try: + key, value = keyAndValue.split(None, 1) + except ValueError: + self.sendCode(500) + log.warn("Command 'put' takes two parameters.") + else: + alreadyThere = yield self.do_query(key) + if alreadyThere is None: + d = defer.maybeDeferred(self.factory.put, key, value) + d.addCallbacks(self._cbPut, self._cbPout) + d.addCallbacks(log.err) + else: + self.sendCode(553) + + @defer.inlineCallbacks + def do_delete(self, key): """ - Create a local LineReceiver server which listens for Postfix aliases - to resolve. + Delete an alias from the mapping database. + + xxx not sure if this is a good idea... """ - super(postfix.PostfixTCPMapServer, self).__init__(*args, **kwargs) + raise NotImplemented + + def _cbGot(self, value): + """Callback for self.get()""" + if value is None: + self.sendCode(550) + else: + self.sendCode(250, quote(value)) + def _cbNot(self, fail): + """Errback for self.get()""" + self.sendCode(554, fail.getErrorMessage()) -class PostfixAliasResolverFactory(postfix.PostfixTCPMapDeferringDictServerFactory): + def _cbPut(self, value): + """xxx fill me in""" + pass + + def _cbPout(self, fail): + """xxx fill me in""" + pass + + +class AliasResolverFactory(postfix.PostfixTCPMapDeferringDictServerFactory): """ - A Factory for creating PostfixAliasResolver servers, which handles inputs + A Factory for creating :class:`AliasResolver` servers, which handles inputs and outputs, and keeps an in-memory mapping of Postfix aliases in the form - of a dict. + of a dictionary. xxx fill me in - """ - protocol = PostfixAliasResolver + protocol = AliasResolver def __init__(self, addr='127.0.0.1', port=4242, timeout=120, data=None): """ - Create a Factory which returns :class:`PostfixAliasResolver` servers. + Create a Factory which returns :class:`AliasResolver` servers. - @param addr: - (optional) A string giving the IP address of the Postfix server. + @param addr: A string giving the IP address of this server. Default: '127.0.0.1' - @param port: - (optional) An integer that specifies the port number of the - Postfix server. Default: 4242 - @param timeout: - (optional) An integer specifying the number of seconds to wait + @param port: An integer that specifies the port number to listen + on. Default: 4242 + @param timeout: An integer specifying the number of seconds to wait until we should time out. Default: 120 - @param data: - (optional) A dict to use to initialise or update the alias - mapping. + @param data: A dict to use to initialise or update the alias mapping. """ - super(postfix.PostfixTCPMapDeferringDictServerFactory, + super(postfix.PostfixTCPMapDeferringDictServerFactory, self).__init__(data=data) self.timeout = timeout - ## xxx get config value, should be something like verbose = no - self.noisy = False + self.noisy = True if config.advanced.noisy else False try: assert isinstance(port, int), "Port number must be an integer" |