From 9ff4ca64e59144361645527e203d6c7c627a3513 Mon Sep 17 00:00:00 2001 From: Andrew Fyfe Date: Wed, 3 Jan 2018 17:56:40 +0000 Subject: [PATCH] only query an ip address once during dnsbl checks - IP addresses are used for DNSBL queries, only query each unique IP address once per DNSBL provider - add support for MXs with IPv6 addresses fixes #1335 --- .../management/commands/subcommands/_mx.py | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/modoboa/admin/management/commands/subcommands/_mx.py b/modoboa/admin/management/commands/subcommands/_mx.py index 009d4ec81..b7ce24fd1 100644 --- a/modoboa/admin/management/commands/subcommands/_mx.py +++ b/modoboa/admin/management/commands/subcommands/_mx.py @@ -72,13 +72,21 @@ class CheckMXRecords(BaseCommand): def query_dnsbl(self, mx_list, provider): """Check given IP against given DNSBL provider.""" results = {} - for mx in mx_list: - reverse = ".".join(reversed(mx.address.split("."))) + for ip, mxs in mx_list.items(): + try: + ip = ipaddress.ip_address(smart_text(ip)) + except ValueError as e: + continue + else: + delim = "." if ip.version == 4 else ":" + reverse = delim.join(ip.exploded.split(delim)[::-1]) pattern = "{}.{}.".format(reverse, provider) try: - results[mx] = socket.gethostbyname(pattern) + result = socket.gethostbyname(pattern) except socket.gaierror: - results[mx] = False + result = False + for mx in mxs: + results[mx] = result return provider, results def store_dnsbl_result(self, domain, provider, results, **options): @@ -191,8 +199,16 @@ class CheckMXRecords(BaseCommand): options["no_dnsbl"] is True) if condition or not mx_list: return + + mx_by_ip = {} + for mx in mx_list: + if mx.address not in mx_by_ip: + mx_by_ip[mx.address] = [mx] + elif mx not in mx_by_ip[mx.address]: + mx_by_ip[mx.address].append(mx) + jobs = [ - gevent.spawn(self.query_dnsbl, mx_list, provider) + gevent.spawn(self.query_dnsbl, mx_by_ip, provider) for provider in self.providers] gevent.joinall(jobs, timeout) for job in jobs: