#!/usr/bin/env python # # checkdbl.py - TCP lookup table for Postfix header_checks # # This script implements the same functionality as the Perl # version available here: # # http://people.freebsd.org/~sahil/scripts/checkdbl.pl.txt # # To integrate in $config_directory/master.cf: # # 127.0.0.1:2526 inet n n n - 0 spawn # user=nobody argv=/path/to/checkdbl.py # # And in $config_directory/main.cf: # # header_checks = tcp:[127.0.0.1]:2526 # 127.0.0.1:2526_time_limit = 3600s # # UPDATED: 2011-09-05 import os, re, socket, sys # # Define the headers and DBL zones we care about, and # compile a repeatedly used regular expression. # headers = ['from', 'message-id', 'reply-to'] zones = ['dbl.spamhaus.org', 'multi.surbl.org', 'black.uribl.com'] regx = re.compile(r'([\w.-]+\.[^\W\d_]+)', re.IGNORECASE) # # Autoflush the standard output stream. # sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) # # Verify that we have a domain, then query DBLs until # we get a hit. Do not waste time checking additional # DBLs if a query suceeds. # def querybl(domain): m = regx.search(domain) if m is not None: domain = m.group(0) for zone in zones: try: if socket.gethostbyname(domain + '.' + zone).startswith('127'): return (domain, zone) except: pass # # Parse input from Postfix, and do some basic sanity # checks; then, send the domain to query function. # def parse(request): if request.startswith('get'): header = request.lstrip('get ').lower() if header.startswith(tuple(headers)): hsplit = header.rsplit('@',1) if len(hsplit) == 2 and hsplit[1] != '': return querybl(hsplit[1]) while True: rval = parse(raw_input()) try: print('200 REJECT ' + rval[0] + ' listed in ' + rval[1]) except: print('200 DUNNO')