Merge pull request #1594 from modoboa/fix/mx_lookup

Fix/mx lookup
This commit is contained in:
Antoine Nguyen
2018-10-17 09:55:02 +02:00
committed by GitHub
22 changed files with 5819 additions and 5625 deletions
+8 -8
View File
@@ -59,6 +59,14 @@ class AdminParametersForm(param_forms.AdminParametersForm):
)
)
custom_dns_server = GenericIPAddressField(
label=ugettext_lazy("Custom DNS server"),
required=False,
help_text=ugettext_lazy(
"Use a custom DNS server instead of local server configuration"
)
)
dkim_keys_storage_dir = forms.CharField(
label=ugettext_lazy("DKIM keys storage directory"),
initial="",
@@ -79,14 +87,6 @@ class AdminParametersForm(param_forms.AdminParametersForm):
)
)
use_specific_dns_server = GenericIPAddressField(
label=ugettext_lazy("Use specific DNS server"),
required=False,
help_text=ugettext_lazy(
"Use a specific DNS server instead of local server configuration"
)
)
mbsep = SeparatorField(label=ugettext_lazy("Mailboxes"))
handle_mailboxes = YesNoField(
+29 -27
View File
@@ -7,7 +7,6 @@ from __future__ import unicode_literals
import ipaddress
import logging
import random
import socket
import string
from functools import wraps
from itertools import chain
@@ -175,12 +174,15 @@ def get_domain_mx_list(domain):
"""Return a list of MX IP address for domain."""
result = []
logger = logging.getLogger("modoboa.admin")
dns_server = param_tools.get_global_parameter("use_specific_dns_server")
dns_server = param_tools.get_global_parameter("custom_dns_server")
if dns_server:
dns.resolver.default_resolver.nameservers = [dns_server]
resolver = dns.resolver.Resolver()
resolver.nameservers = [dns_server]
else:
resolver = dns.resolver
try:
dns_answers = dns.resolver.query(domain, "MX")
dns_answers = resolver.query(domain, "MX")
except dns.resolver.NXDOMAIN as e:
logger.error(_("No DNS records found for %s") % domain, exc_info=e)
except dns.resolver.NoAnswer as e:
@@ -193,29 +195,29 @@ def get_domain_mx_list(domain):
domain, exc_info=e)
else:
for dns_answer in dns_answers:
try:
mx_domain = dns_answer.exchange.to_unicode(
omit_final_dot=True, idna_codec=IDNA_2008_UTS_46)
ip_answers = dns.resolver.query(mx_domain)
except dns.resolver.NXDOMAIN as e:
logger.error(_("No DNS records found without MX for %s")
% domain, exc_info=e)
else:
for ip_answer in ip_answers:
for answer_set in ip_answer.response.answer:
for address in answer_set:
try:
address_smart = smart_text(address)
mx_ip = ipaddress.ip_address(address_smart)
except ValueError as e:
logger.warning(
_("Invalid IP address format for "
"%(domain)s; %(addr)s")
% {"domain": mx_domain,
"addr": smart_text(address)},
exc_info=e)
else:
result.append((mx_domain, mx_ip))
for rtype in ["A", "AAAA"]:
try:
mx_domain = dns_answer.exchange.to_unicode(
omit_final_dot=True, idna_codec=IDNA_2008_UTS_46)
ip_answers = resolver.query(mx_domain, rtype)
except dns.resolver.NXDOMAIN as e:
logger.error(
_("No {type} record found for MX {mx}").format(
type=rtype, mx=domain), exc_info=e)
else:
for ip_answer in ip_answers:
try:
address_smart = smart_text(ip_answer.address)
mx_ip = ipaddress.ip_address(address_smart)
except ValueError as e:
logger.warning(
_("Invalid IP address format for "
"{domain}; {addr}").format(
domain=mx_domain,
addr=smart_text(ip_answer.address)
), exc_info=e)
else:
result.append((mx_domain, mx_ip))
return result
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+4 -3
View File
@@ -19,8 +19,9 @@ from django.utils.translation import ugettext as _, ugettext_lazy
from modoboa.core.models import User
from modoboa.lib import exceptions as lib_exceptions
from modoboa.lib.email_utils import split_mailbox
from modoboa.lib.sysutils import exec_cmd
from modoboa.lib.sysutils import doveadm_cmd
from modoboa.parameters import tools as param_tools
from .base import AdminObject
from .domain import Domain
@@ -158,8 +159,8 @@ class Mailbox(AdminObject):
options = {}
if curuser != mbowner:
options["sudo_user"] = mbowner
code, output = exec_cmd(
"doveadm user -f home %s" % self.full_address, **options
code, output = doveadm_cmd(
"user -f home %s" % self.full_address, **options
)
if code:
raise lib_exceptions.InternalError(
+11 -5
View File
@@ -114,7 +114,7 @@ class MXTestCase(ModoTestCase):
"""Test to get mx list from specific DNS server."""
mock_query.side_effect = utils.mock_dns_query_result
mock_getaddrinfo.side_effect = utils.mock_ip_query_result
self.set_global_parameter("use_specific_dns_server", "123.45.67.89")
self.set_global_parameter("custom_dns_server", "123.45.67.89")
get_domain_mx_list("does-not-exist.example.com")
@mock.patch("ipaddress.ip_address")
@@ -139,13 +139,19 @@ class MXTestCase(ModoTestCase):
("modoboa.admin", "ERROR", _("No working name servers found")),
("modoboa.admin", "WARNING",
_("DNS resolution timeout, unable to query %s at the moment")
% "timeout.example.com"),
% "timeout.example.com"),
("modoboa.admin", "ERROR",
_("No DNS records found without MX for %(domain)s")
_("No A record found for MX %(domain)s")
% {"domain": "no-lookup.example.com"}),
("modoboa.admin", "ERROR",
_("No AAAA record found for MX %(domain)s")
% {"domain": "no-lookup.example.com"}),
("modoboa.admin", "WARNING",
_("Invalid IP address format for %(domain)s; %(addr)s")
% {"domain": "bad-response.example.com", "addr": "000.0.0.0"}),
_("Invalid IP address format for %(domain)s; %(addr)s")
% {"domain": "bad-response.example.com", "addr": "000.0.0.0"}),
("modoboa.admin", "WARNING",
_("Invalid IP address format for %(domain)s; %(addr)s")
% {"domain": "bad-response.example.com", "addr": "000.0.0.0"}),
)
+9 -24
View File
@@ -3,7 +3,6 @@
"""Test utilities."""
from __future__ import unicode_literals
from dns.rrset import RRset
import socket
@@ -12,27 +11,16 @@ from dns.rdtypes.ANY.MX import MX
from dns.resolver import NXDOMAIN, NoAnswer, NoNameservers, Timeout
class RRsetResponse(object):
def __init__(self):
self.answer = [["192.0.2.1"]]
class RRset(object):
def __init__(self):
self.response = RRsetResponse()
self.address = "192.0.2.1"
class RRsetResponseInvalid(object):
def __init__(self):
self.answer = [["000.0.0.0"]]
class RRsetInvalid(object):
def __init__(self):
self.response = RRsetResponseInvalid()
self.address = "000.0.0.0"
_MX_RECORD_1 = MX("IN", "MX", 10, Name("mx.example.com".split(".")))
@@ -42,7 +30,6 @@ _DNE_MX_RECORD = MX("IN", "MX", 10, Name(
"does-not-exist.example.com".split(".")))
_MX_RECORDS = [_MX_RECORD_1]
_IP_SET_RECORDS = [RRset()]
_IPV4_RECORD_1 = (socket.AF_INET, socket.SOCK_STREAM, 6, "", ("192.0.2.1", 25))
_IPV4_RECORD_2 = (socket.AF_INET, socket.SOCK_STREAM, 6, "", ("192.0.2.2", 25))
@@ -79,20 +66,20 @@ _POSSIBLE_IP_RESULTS = {
def mock_dns_query_result(qname, *args, **kwargs):
if "MX" in args:
if qname in _POSSIBLE_DNS_RESULTS:
return get_mock_dns_query_response(_POSSIBLE_DNS_RESULTS, qname)
return _MX_RECORDS
if qname in _POSSIBLE_DNS_RESULTS:
return get_mock_dns_query_response(_POSSIBLE_DNS_RESULTS, qname)
return _MX_RECORDS
elif qname in _POSSIBLE_DNS_RESULTS_NO_MX:
return get_mock_dns_query_response(_POSSIBLE_DNS_RESULTS_NO_MX, qname)
else:
return _IP_SET_RECORDS
def get_mock_dns_query_response(responses, attributeName):
if isinstance(responses[attributeName], Exception):
raise responses[attributeName]
else:
return responses[attributeName]
return responses[attributeName]
def mock_ip_address_result(host, *args, **kwargs):
if host in _POSSIBLE_IP_RESULTS:
@@ -100,9 +87,8 @@ def mock_ip_address_result(host, *args, **kwargs):
raise _POSSIBLE_IP_RESULTS[host]
else:
return _POSSIBLE_IP_RESULTS[host]
return _IP_RECORDS
def mock_ip_query_result(host, port, *args, **kwargs):
if host in _POSSIBLE_IP_RESULTS:
@@ -110,5 +96,4 @@ def mock_ip_query_result(host, port, *args, **kwargs):
raise _POSSIBLE_IP_RESULTS[host]
else:
return _POSSIBLE_IP_RESULTS[host]
return _IP_RECORDS
+1 -1
View File
@@ -69,7 +69,7 @@ SETTINGS_SAMPLE = {
"admin-create_alias_on_mbox_rename": False,
"admin-dkim_keys_storage_dir": "",
"admin-dkim_default_key_length": 1024,
"admin-use_specific_dns_server": "193.43.55.67"
"admin-custom_dns_server": "193.43.55.67"
}