[Twisted-Python] Implementing Postfix Inet Policy Check Client

Ex Vito ex.vitorino at gmail.com
Tue Nov 17 19:14:22 MST 2015


Tom,

I guess LineReceiver can help you with that, it's a matter of using a
different delimiter. Here is a rough sketch of something you can start
exploring:

from __future__ import print_function

from twisted.internet import reactor, protocol, endpoints, defer
from twisted.protocols import basic


class PostfixProtocol(basic.LineReceiver):

    # Assuming Postfix sends '\r\n' line breaks (does it?)
    delimiter = '\r\n\r\n'

    def lineReceived(self, multi_line):
        input_dict = {
            k: v for k, v in (
                line.split('=') for line in multi_line.split('\r\n')
            )
        }
        self.gotPostfixRequest(input_dict)

    def gotPostfixRequest(self, request_dict):
        # Silly deferred-based implementation.
        d = defer.Deferred()
        d.addCallback(self.sendPostfixAction)
        # Simulate a deferred being fired with success.
        reactor.callLater(1, d.callback, 'OK')

    def sendPostfixAction(self, response):
        # NOTE: Sends self.delimiter after the payload.
        #       Use self.tranport.write if you don't want it.
        self.sendLine('action={}'.format(response))


if __name__ == '__main__':

    ep = endpoints.serverFromString(reactor, 'tcp:10000')
    f = protocol.Factory()
    f.protocol = PostfixProtocol
    ep.listen(f)
    reactor.run()

Key ideas:
- PostfixProtocol overrides LineReceiver's delimiter (setting it to
'\r\n\r\n')
- lineReceived parses the muti_line and calls gotPostfixRequest.
- gotPostfixRequest should decide (or delegate, you choice) what kind of
response to send back.
- sendPostfixAction sends a response back to Postfix.

Notes:
- The multi_line parsing code is short(ish) but not very robust. It may
fail in bad ways with invalid input.
- The gotPostfixRequest implementation is written for the sake of a
deferred-based example.

Does this help you in any way?
Cheers,
--
exvito


On Tue, Nov 17, 2015 at 4:56 PM, Tom Boland <tom at t0mb.net> wrote:
> Greetings all.
>
> This may be a very basic question.  I'm hoping to implement a postfix
> policy check client in twisted.  It's a simple protocol.  You send
> newline separated key value pairs like:
>
> recipient=email at ddr.ess
> sender=another at ddr.ess
> size=1024
> helo_name=mail.server
> etc..
>
> you terminate the request with an additional newline.  The response
> comes back like
>
> action=OK
>
> You can send mutliple requests in the same connection.  What I'm
> envisaging is a module that can be used to provide a deferred
> request/response pairing to my calling application.  The module class
> will manage the single connection to the postfix policy daemon (I'm
> actually going to have persistent connections to a few daemons), and
> reconnect when necessary etc.  Any requests will return a deferred that
> I can add callbacks to.  How would you design this with twisted?  I can
> easily envisage a way of using a clientfactory to instantiate separate
> connections for each request/response, but actually being able to simply
> send a request and receive the single response for that request is
> something I'm struggling to do within a LineReceiver instance (for
> instance).  Would the twisted.protocols.amp module help given that I
> can't change the server-side protocol?
>
> Any advice much appreciated!
>
> Thanks.  Tom.
>
> _______________________________________________
> Twisted-Python mailing list
> Twisted-Python at twistedmatrix.com
> http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python



-- 
--
  exvito
-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/twisted-python/attachments/20151118/66efa429/attachment-0002.html>


More information about the Twisted-Python mailing list