Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

postfix.py 3.5KB

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