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