| OLD | NEW |
| (Empty) |
| 1 # -*- test-case-name: twisted.test.test_postfix -*- | |
| 2 # | |
| 3 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. | |
| 4 # See LICENSE for details. | |
| 5 | |
| 6 # | |
| 7 | |
| 8 """Postfix mail transport agent related protocols.""" | |
| 9 | |
| 10 import sys | |
| 11 | |
| 12 # Twisted imports | |
| 13 from twisted.protocols import basic | |
| 14 from twisted.protocols import policies | |
| 15 from twisted.internet import protocol, defer | |
| 16 from twisted.python import log | |
| 17 import UserDict | |
| 18 import urllib | |
| 19 | |
| 20 # urllib's quote functions just happen to match | |
| 21 # the postfix semantics. | |
| 22 | |
| 23 def quote(s): | |
| 24 return urllib.quote(s) | |
| 25 | |
| 26 def unquote(s): | |
| 27 return urllib.unquote(s) | |
| 28 | |
| 29 class PostfixTCPMapServer(basic.LineReceiver, policies.TimeoutMixin): | |
| 30 """Postfix mail transport agent TCP map protocol implementation. | |
| 31 | |
| 32 Receive requests for data matching given key via lineReceived, | |
| 33 asks it's factory for the data with self.factory.get(key), and | |
| 34 returns the data to the requester. None means no entry found. | |
| 35 | |
| 36 You can use postfix's postmap to test the map service:: | |
| 37 | |
| 38 /usr/sbin/postmap -q KEY tcp:localhost:4242 | |
| 39 | |
| 40 """ | |
| 41 | |
| 42 timeout = 600 | |
| 43 delimiter = '\n' | |
| 44 | |
| 45 def connectionMade(self): | |
| 46 self.setTimeout(self.timeout) | |
| 47 | |
| 48 def sendCode(self, code, message=''): | |
| 49 "Send an SMTP-like code with a message." | |
| 50 self.sendLine('%3.3d %s' % (code, message or '')) | |
| 51 | |
| 52 def lineReceived(self, line): | |
| 53 self.resetTimeout() | |
| 54 try: | |
| 55 request, params = line.split(None, 1) | |
| 56 except ValueError: | |
| 57 request = line | |
| 58 params = None | |
| 59 try: | |
| 60 f = getattr(self, 'do_' + request) | |
| 61 except AttributeError: | |
| 62 self.sendCode(400, 'unknown command') | |
| 63 else: | |
| 64 try: | |
| 65 f(params) | |
| 66 except: | |
| 67 self.sendCode(400, 'Command %r failed: %s.' % (request, sys.exc_
info()[1])) | |
| 68 | |
| 69 def do_get(self, key): | |
| 70 if key is None: | |
| 71 self.sendCode(400, 'Command %r takes 1 parameters.' % 'get') | |
| 72 else: | |
| 73 d = defer.maybeDeferred(self.factory.get, key) | |
| 74 d.addCallbacks(self._cbGot, self._cbNot) | |
| 75 d.addErrback(log.err) | |
| 76 | |
| 77 def _cbNot(self, fail): | |
| 78 self.sendCode(400, fail.getErrorMessage()) | |
| 79 | |
| 80 def _cbGot(self, value): | |
| 81 if value is None: | |
| 82 self.sendCode(500) | |
| 83 else: | |
| 84 self.sendCode(200, quote(value)) | |
| 85 | |
| 86 def do_put(self, keyAndValue): | |
| 87 if keyAndValue is None: | |
| 88 self.sendCode(400, 'Command %r takes 2 parameters.' % 'put') | |
| 89 else: | |
| 90 try: | |
| 91 key, value = keyAndValue.split(None, 1) | |
| 92 except ValueError: | |
| 93 self.sendCode(400, 'Command %r takes 2 parameters.' % 'put') | |
| 94 else: | |
| 95 self.sendCode(500, 'put is not implemented yet.') | |
| 96 | |
| 97 | |
| 98 class PostfixTCPMapDictServerFactory(protocol.ServerFactory, | |
| 99 UserDict.UserDict): | |
| 100 """An in-memory dictionary factory for PostfixTCPMapServer.""" | |
| 101 | |
| 102 protocol = PostfixTCPMapServer | |
| 103 | |
| 104 class PostfixTCPMapDeferringDictServerFactory(protocol.ServerFactory): | |
| 105 """An in-memory dictionary factory for PostfixTCPMapServer.""" | |
| 106 | |
| 107 protocol = PostfixTCPMapServer | |
| 108 | |
| 109 def __init__(self, data=None): | |
| 110 self.data = {} | |
| 111 if data is not None: | |
| 112 self.data.update(data) | |
| 113 | |
| 114 def get(self, key): | |
| 115 return defer.succeed(self.data.get(key)) | |
| 116 | |
| 117 if __name__ == '__main__': | |
| 118 """Test app for PostfixTCPMapServer. Call with parameters | |
| 119 KEY1=VAL1 KEY2=VAL2 ...""" | |
| 120 from twisted.internet import reactor | |
| 121 log.startLogging(sys.stdout) | |
| 122 d = {} | |
| 123 for arg in sys.argv[1:]: | |
| 124 try: | |
| 125 k,v = arg.split('=', 1) | |
| 126 except ValueError: | |
| 127 k = arg | |
| 128 v = '' | |
| 129 d[k]=v | |
| 130 f=PostfixTCPMapDictServerFactory(d) | |
| 131 port = reactor.listenTCP(4242, f, interface='127.0.0.1') | |
| 132 reactor.run() | |
| OLD | NEW |