mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
@@ -7,8 +7,8 @@ from . import models
|
||||
|
||||
|
||||
@receiver(signals.post_save, sender=models.Domain)
|
||||
def update_domain_mailboxes(sender, instance, **kwargs):
|
||||
"""Update associated mailboxes."""
|
||||
def update_domain_mxs_and_mailboxes(sender, instance, **kwargs):
|
||||
"""Update associated MXs and mailboxes."""
|
||||
if kwargs.get("created"):
|
||||
return
|
||||
instance.mailbox_set.filter(use_domain_quota=True).update(
|
||||
|
||||
@@ -57,6 +57,9 @@ class CheckMXRecords(BaseCommand):
|
||||
"--skip-admin-emails", action="store_true",
|
||||
default=False,
|
||||
help="Skip domain's admins email notification.")
|
||||
parser.add_argument(
|
||||
"--domain", type=str, action="append", default=[],
|
||||
help="Domain name or id to update.")
|
||||
parser.add_argument(
|
||||
"--timeout", type=int, default=3,
|
||||
help="Timeout used for queries.")
|
||||
@@ -80,28 +83,29 @@ class CheckMXRecords(BaseCommand):
|
||||
models.MXRecord.objects.filter(domain=domain).delete()
|
||||
try:
|
||||
answers = dns.resolver.query(domain.name, "MX")
|
||||
except (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN):
|
||||
except (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN,
|
||||
dns.resolver.NoNameservers):
|
||||
raise StopIteration()
|
||||
|
||||
delta = timedelta(seconds=ttl)
|
||||
|
||||
for answer in answers:
|
||||
address = None
|
||||
try:
|
||||
ipaddress.ip_address(str(answer.exchange))
|
||||
except ValueError:
|
||||
try:
|
||||
address = socket.gethostbyname(str(answer.exchange))
|
||||
except socket.gaierror:
|
||||
pass
|
||||
# work if .exchange is a name or IP
|
||||
address = socket.gethostbyname(str(answer.exchange))
|
||||
except socket.gaierror:
|
||||
pass
|
||||
else:
|
||||
address = str(answer.exchange)
|
||||
finally:
|
||||
if address is not None:
|
||||
try:
|
||||
# we must have a valid IP
|
||||
address = ipaddress.ip_address(u'{}'.format(address))
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
record = models.MXRecord.objects.create(
|
||||
domain=domain,
|
||||
name=str(answer.exchange).strip("."),
|
||||
address=address,
|
||||
name=u'{}'.format(str(answer.exchange).strip(".")),
|
||||
address=u'{}'.format(address),
|
||||
updated=now + delta)
|
||||
yield record
|
||||
|
||||
@@ -237,5 +241,19 @@ class CheckMXRecords(BaseCommand):
|
||||
models.DNSBLResult.objects.exclude(
|
||||
provider__in=self.providers).delete()
|
||||
|
||||
for domain in models.Domain.objects.filter(enabled=True):
|
||||
if options['domain']:
|
||||
domains = []
|
||||
for domain in options['domain']:
|
||||
if isinstance(domain, models.Domain):
|
||||
domains.append(domain)
|
||||
elif domain.isdigit():
|
||||
domains.append(models.Domain.objects.get(domain))
|
||||
else:
|
||||
domains.append(models.Domain.objects.filter(name=domain))
|
||||
else:
|
||||
domains = models.Domain.objects.filter(enabled=True)
|
||||
|
||||
options.pop('domain')
|
||||
|
||||
for domain in domains:
|
||||
self.check_domain(domain, **options)
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
"""Models related to domains management."""
|
||||
|
||||
import datetime
|
||||
|
||||
from django.db import models
|
||||
from django.db.models.manager import Manager
|
||||
from django.utils import timezone
|
||||
from django.utils.encoding import python_2_unicode_compatible, smart_text
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
@@ -103,8 +106,18 @@ class Domain(AdminObject):
|
||||
return self.domainalias_set
|
||||
|
||||
@property
|
||||
def mx_records(self):
|
||||
self.mxrecord_set
|
||||
def just_created(self):
|
||||
"""return true if the domain was created in the latest 24h"""
|
||||
now = timezone.now()
|
||||
delta = datetime.timedelta(days=1)
|
||||
return self.creation + delta > now
|
||||
|
||||
def awaiting_checks(self):
|
||||
"""return true if the domain has no valid MX records and was created
|
||||
in the latest 24h"""
|
||||
if (not self.mxrecord_set.has_valids()) and self.just_created:
|
||||
return True
|
||||
return False
|
||||
|
||||
@cached_property
|
||||
def dnsbl_status_color(self):
|
||||
|
||||
@@ -24,11 +24,15 @@
|
||||
{% if enable_mx_checks == "yes" or enable_dnsbl_checks == "yes" %}
|
||||
<div class="row">
|
||||
<span class="title">{% trans "DNS status" %}</span>
|
||||
{% if enable_mx_checks == "yes" %}
|
||||
<span class="label label-mini label-{% if not domain.mxrecord_set.has_valids %}danger{% else %}success{% endif %}"><a href="{% url 'admin:mx_domain_detail' domain.pk %}" data-toggle="ajaxmodal">MX</a></span>
|
||||
{% endif %}
|
||||
{% if enable_dnsbl_checks == "yes" %}
|
||||
<span class="label label-{{ domain.dnsbl_status_color }}"><a href="{% url 'admin:dnsbl_domain_detail' domain.pk %}" data-toggle="ajaxmodal">DNSBL</a></span>
|
||||
{% if domain.awaiting_checks %}
|
||||
<span class="label label-mini label-info">{% trans "Awaiting checks" %}</span>
|
||||
{% else %}
|
||||
{% if enable_mx_checks == "yes" %}
|
||||
<span class="label label-mini label-{% if not domain.mxrecord_set.has_valids %}danger{% else %}success{% endif %}"><a href="{% url 'admin:mx_domain_detail' domain.pk %}" data-toggle="ajaxmodal">MX</a></span>
|
||||
{% endif %}
|
||||
{% if enable_dnsbl_checks == "yes" %}
|
||||
<span class="label label-mini label-{{ domain.dnsbl_status_color }}"><a href="{% url 'admin:dnsbl_domain_detail' domain.pk %}" data-toggle="ajaxmodal">DNSBL</a></span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -8,11 +8,15 @@
|
||||
{% if enable_mx_checks == "yes" or enable_dnsbl_checks == "yes" %}
|
||||
<td name="dns">
|
||||
<small>
|
||||
{% if enable_mx_checks == "yes" %}
|
||||
<span class="label label-mini label-{% if not domain.mxrecord_set.has_valids %}danger{% else %}success{% endif %}"><a href="{% url 'admin:mx_domain_detail' domain.pk %}" data-toggle="ajaxmodal">MX</a></span>
|
||||
{% endif %}
|
||||
{% if enable_dnsbl_checks == "yes" %}
|
||||
<span class="label label-mini label-{{ domain.dnsbl_status_color }}"><a href="{% url 'admin:dnsbl_domain_detail' domain.pk %}" data-toggle="ajaxmodal">DNSBL</a></span>
|
||||
{% if domain.awaiting_checks %}
|
||||
<span class="label label-mini label-info">{% trans "Awaiting checks" %}</span>
|
||||
{% else %}
|
||||
{% if enable_mx_checks == "yes" %}
|
||||
<span class="label label-mini label-{% if not domain.mxrecord_set.has_valids %}danger{% else %}success{% endif %}"><a href="{% url 'admin:mx_domain_detail' domain.pk %}" data-toggle="ajaxmodal">MX</a></span>
|
||||
{% endif %}
|
||||
{% if enable_dnsbl_checks == "yes" %}
|
||||
<span class="label label-mini label-{{ domain.dnsbl_status_color }}"><a href="{% url 'admin:dnsbl_domain_detail' domain.pk %}" data-toggle="ajaxmodal">DNSBL</a></span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</small>
|
||||
</td>
|
||||
|
||||
@@ -21,6 +21,7 @@ class MXTestCase(ModoTestCase):
|
||||
cls.domain = factories.DomainFactory(name="modoboa.org")
|
||||
factories.DomainFactory(name="pouet.com") # should not exist
|
||||
parameters.save_admin('VALID_MXS', '127.0.0.1', app='admin')
|
||||
models.MXRecord.objects.all().delete()
|
||||
|
||||
def test_management_command(self):
|
||||
"""Check that command works fine."""
|
||||
@@ -53,6 +54,7 @@ class DNSBLTestCase(ModoTestCase):
|
||||
super(DNSBLTestCase, cls).setUpTestData()
|
||||
cls.domain = factories.DomainFactory(name="modoboa.org")
|
||||
factories.DomainFactory(name="pouet.com") # should not exist
|
||||
models.DNSBLResult.objects.all().delete()
|
||||
|
||||
@override_settings(DNSBL_PROVIDERS=["zen.spamhaus.org"])
|
||||
def test_management_command(self):
|
||||
|
||||
Reference in New Issue
Block a user