diff --git a/data/hooks/diagnosis/24-mail.py b/data/hooks/diagnosis/24-mail.py index 4ced72959..afb88f7cf 100644 --- a/data/hooks/diagnosis/24-mail.py +++ b/data/hooks/diagnosis/24-mail.py @@ -13,6 +13,7 @@ from moulinette.utils.filesystem import read_yaml from yunohost.diagnosis import Diagnoser from yunohost.domain import _get_maindomain, domain_list from yunohost.settings import settings_get +from yunohost.utils.network import dig DEFAULT_DNS_BLACKLIST = "/usr/share/yunohost/other/dnsbl_list.yml" @@ -155,26 +156,25 @@ class MailDiagnoser(Diagnoser): if not blacklist[item_type]: continue - # Determine if we are listed on this RBL - try: - subdomain = item - if item_type != "domain": - rev = dns.reversename.from_address(item) - subdomain = str(rev.split(3)[0]) - query = subdomain + '.' + blacklist['dns_server'] - # TODO add timeout lifetime - dns.resolver.query(query, "A") - except (dns.resolver.NXDOMAIN, dns.resolver.NoNameservers, dns.resolver.NoAnswer, - dns.exception.Timeout): + # Build the query for DNSBL + subdomain = item + if item_type != "domain": + rev = dns.reversename.from_address(item) + subdomain = str(rev.split(3)[0]) + query = subdomain + '.' + blacklist['dns_server'] + + # Do the DNS Query + status, answers = dig(query, 'A') + if status != 'ok': continue # Try to get the reason details = [] - try: - reason = str(dns.resolver.query(query, "TXT")[0]) + status, answers = dig(query, 'TXT') + reason = "-" + if status == 'ok': + reason = ', '.join(answers) details.append("diagnosis_mail_blacklist_reason") - except Exception: - reason = "-" details.append("diagnosis_mail_blacklist_website") diff --git a/src/yunohost/utils/network.py b/src/yunohost/utils/network.py index 3ae1ba910..6dc4c22a0 100644 --- a/src/yunohost/utils/network.py +++ b/src/yunohost/utils/network.py @@ -21,6 +21,7 @@ import os import re import logging +import dns.resolver from moulinette.utils.network import download_text from moulinette.utils.process import check_output @@ -84,6 +85,24 @@ def get_gateway(): return addr.popitem()[1] if len(addr) == 1 else None +def dig(qname, rdtype="A", timeout=5, resolvers=["127.0.0.1"], edns_size=1500): + """ + Do a quick DNS request and avoid the "search" trap inside /etc/resolv.conf + """ + + resolver = dns.resolver.Resolver(configure=False) + resolver.use_edns(0, 0, edns_size) + resolver.nameservers = resolvers + resolver.timeout = timeout + try: + answers = resolver.query(qname, rdtype) + except (dns.resolver.NXDOMAIN, dns.resolver.NoNameservers, dns.resolver.NoAnswer, + dns.exception.Timeout) as e: + return ("nok", e.__class__.__name__, e) + + return ("ok", [(answer.to_text(), answer) for answer in answers]) + + def _extract_inet(string, skip_netmask=False, skip_loopback=True): """ Extract IP addresses (v4 and/or v6) from a string limited to one