Send notifications.

see #879
This commit is contained in:
Antoine Nguyen
2016-06-09 14:40:17 +02:00
parent f2c8736d02
commit 27dd441111
5 changed files with 90 additions and 15 deletions
@@ -8,10 +8,14 @@ from gevent import socket
from django.conf import settings
from django.core.management.base import BaseCommand
from django.template.loader import render_to_string
from django.utils.functional import cached_property
from django.utils.translation import ugettext as _
from modoboa.admin import constants
from modoboa.admin import models
from modoboa.lib import parameters
from modoboa.lib import email_utils
class CheckDNSBLCommand(BaseCommand):
@@ -19,6 +23,18 @@ class CheckDNSBLCommand(BaseCommand):
help = "Check defined domains against DNSBL providers."
@cached_property
def providers(self):
"""Return a list of DNSBL providers."""
if not hasattr(settings, "DNSBL_PROVIDERS"):
return constants.DNSBL_PROVIDERS
return settings.DNSBL_PROVIDERS
@cached_property
def sender(self):
"""Return sender address for notifications."""
return parameters.get_admin("SENDER_ADDRESS", app="core")
def add_arguments(self, parser):
"""Add extra arguments to command."""
parser.add_argument(
@@ -37,6 +53,45 @@ class CheckDNSBLCommand(BaseCommand):
results[ip] = False
return provider, results
def store_domain_result(self, domain, provider, results):
"""Store provider results for domain."""
alerts = {}
to_create = []
for ip in results.keys():
result = "" if not results[ip] else results[ip]
dnsbl_result = models.DNSBLResult.objects.filter(
domain=domain, provider=provider, mx=ip).first()
if dnsbl_result is None:
to_create.append(
models.DNSBLResult(
domain=domain, provider=provider, mx=ip,
status=result)
)
else:
if not dnsbl_result.status and result:
if domain not in alerts:
alerts[domain] = []
alerts[domain].append((provider, ip))
dnsbl_result.status = result
dnsbl_result.save()
models.DNSBLResult.objects.bulk_create(to_create)
if not alerts:
return
content = render_to_string(
"admin/notifications/domain_in_dnsbl.html", {
"domain": domain, "alerts": alerts
})
subject = _("[modoboa] DNSBL issue(s) for domain {}").format(
domain.name)
for admin in domain.admins:
if not admin.email:
continue
status, msg = email_utils.sendmail_simple(
self.sender, admin.email,
domainsubject=subject, content=content)
if not status:
print msg
def check_domain(self, domain, timeout):
"""Check specified domain."""
resolver = dns.resolver.Resolver()
@@ -59,30 +114,24 @@ class CheckDNSBLCommand(BaseCommand):
finally:
if address is not None:
ip_list.append(address)
print domain.name, ip_list
if len(ip_list) == 0:
return
if not hasattr(settings, "DNSBL_PROVIDERS"):
providers = constants.DNSBL_PROVIDERS
else:
providers = settings.DNSBL_PROVIDERS
jobs = [
gevent.spawn(self.query, ip_list, provider)
for provider in providers]
for provider in self.providers]
gevent.joinall(jobs, timeout)
for job in jobs:
if not job.successful():
continue
provider, results = job.value
for ip in results.keys():
result = "" if not results[ip] else results[ip]
models.DNSBLResult.objects.update_or_create(
domain=domain, provider=provider, mx=ip,
status=result)
self.store_domain_result(domain, provider, results)
def handle(self, *args, **options):
"""Command entry point."""
if parameters.get_admin("ENABLE_DNSBL_CHECKS") == "no":
return
# Remove deprecated records first
models.DNSBLResult.objects.exclude(
provider__in=self.providers).delete()
for domain in models.Domain.objects.filter(enabled=True):
self.check_domain(domain, options.get("timeout"))
@@ -17,9 +17,9 @@ class Migration(migrations.Migration):
name='DNSBLResult',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('provider', models.CharField(max_length=254)),
('provider', models.CharField(max_length=254, db_index=True)),
('mx', models.GenericIPAddressField()),
('status', models.CharField(blank=True, max_length=45)),
('status', models.CharField(blank=True, max_length=45, db_index=True)),
('domain', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='admin.Domain')),
],
),
+2 -2
View File
@@ -232,9 +232,9 @@ class DNSBLResult(models.Model):
"""Store a DNSBL query result."""
domain = models.ForeignKey(Domain)
provider = models.CharField(max_length=254)
provider = models.CharField(max_length=254, db_index=True)
mx = models.GenericIPAddressField()
status = models.CharField(max_length=45, blank=True)
status = models.CharField(max_length=45, blank=True, db_index=True)
objects = models.Manager.from_queryset(DNSBLQuerySet)()
@@ -0,0 +1,15 @@
{% load i18n %}
{% blocktrans trimmed domain=domain.name %}
Modoboa detected that domain {{ domain }} is listed by the following DNSBL providers:
{% endblocktrans %}
{% for provider, ip in alerts %}
{{ provider }}: {{ ip }}
{% endfor %}
{% blocktrans trimmed %}
The domain's reputation will be affected and there is a chance that
emails coming from it are considered as spam. You should contact
those providers and ask them to unlist detected IP address(es).
{% endblocktrans %}
+11
View File
@@ -4,6 +4,7 @@ from django.conf import settings
from django.utils.translation import ugettext as _, ugettext_lazy
from modoboa.lib import parameters
from modoboa.lib import fields as lib_fields
from modoboa.lib.cryptutils import random_key
from modoboa.lib.form_utils import (
YesNoField, SeparatorField, InlineRadioSelect
@@ -209,6 +210,16 @@ class GeneralParametersForm(parameters.AdminParametersForm):
required=False
)
notif_sep = SeparatorField(label=ugettext_lazy("Notifications"))
sender_address = lib_fields.UTF8EmailField(
label=_("Sender address"),
initial="noreply@modoboa.org",
help_text=_(
"Email address used to send notifications."
)
)
sep3 = SeparatorField(label=ugettext_lazy("Miscellaneous"))
top_notifications_check_interval = forms.IntegerField(