Below is the file 'twistedrbl.py' from this revision. You can also download the file.

#!/usr/bin/env python2.4

from twisted.internet import stdio
from twisted.protocols import basic
from twisted.names import client
import fcntl, os, sys, re
import datetime, time

rbls_to_check = ['bl.spamcop.net', 'sbl-xbl.spamhaus.org', 'dnsbl.sorbs.net']
spam_info_re = re.compile(r'^(?P<date>[^ ]+ [^ ]+ [^ ]+) (?P<scannerhost>[^ ]+) filter-module\[(?P<pid>\d+)\]: (?P<queueid>\w+): spam_status=(?P<spamstatus>[^ ]+) \(from=(?P<from>[^ ]*) to=(?P<to>[^ ]*) uwa_client_ip= ?(?P<ip>[\d\.]+) \((?P<class>[^\)]+)\) message_id= ?(?P<message_id>.*)$')

def set_nonblocking(fd):
    fl = fcntl.fcntl(fd, fcntl.F_GETFL)
    fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NDELAY)

class Echo(basic.LineReceiver):
    delimiter = '\n'
    def __init__(self, log_fd, result_fd):
        self.log_fd = log_fd
        self.result_fd = result_fd
        self.resolver = client.createResolver()
        self.track = 0

    def connectionMade(self):
        self.log_fd.write('Connection established.\n')

    def dns_response(self, result, args):
        querying_rbl, ipr, track, line, is_ok = args
        in_rbl = is_ok and result and result.startswith('127.0.0')
        in_kas = line['spamstatus'] != 'no'
        log_fd.write('result for %s (%d)\n' % (ipr, track))
        line_time = time.mktime(time.strptime(line['date'] + ' 2006', '%b %d %H:%M:%S %Y'))
        self.result_fd.write("%d %s %s %s in_kas=%s in_rbl=%s\n" % (int(line_time),
                                                                   querying_rbl,
                                                                   line['ip'],
                                                                   line['from'].split('@')[-1],
                                                                   in_kas,
                                                                   in_rbl))

    def lineReceived(self, line):
        match = spam_info_re.match(line)
        if match:
            match = match.groupdict()
            ip_address = match['ip']
            for rbl in rbls_to_check:
                self.track += 1
                ipr = '.'.join(reversed(ip_address.split('.'))) + '.' + rbl
                log_fd.write('%s (%d) issued\n' % (ipr, self.track))
                deferred = self.resolver.getHostByName(ipr)
                deferred.addCallback(self.dns_response, [rbl, ipr, self.track, match, True])
                deferred.addErrback(self.dns_response, [rbl, ipr, self.track, match, False])

if __name__ == '__main__':
    log_fd = open('log.txt', 'w')
    result_fd = open('result.txt', 'w')
    stdio.StandardIO(Echo(log_fd, result_fd))
    from twisted.internet import reactor
    reactor.run()