From 560e1196062b7001f00e0050d860e6be5c4b32c6 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Mon, 25 Jun 2012 15:58:06 +0200 Subject: [PATCH] Notification for release requests. fixes #251 --- modoboa/extensions/amavis/__init__.py | 6 +- .../extensions/amavis/{ => script}/cleanup.py | 4 +- modoboa/extensions/amavis/script/notify.py | 70 +++++++++++++++++++ .../notifications/pending_requests.html | 14 ++++ modoboa/lib/emailutils.py | 7 +- modoboa/lib/templatetags/libextras.py | 5 ++ 6 files changed, 99 insertions(+), 7 deletions(-) rename modoboa/extensions/amavis/{ => script}/cleanup.py (95%) create mode 100755 modoboa/extensions/amavis/script/notify.py create mode 100644 modoboa/extensions/amavis/templates/amavis/notifications/pending_requests.html diff --git a/modoboa/extensions/amavis/__init__.py b/modoboa/extensions/amavis/__init__.py index 89a44c34b..07e6a0cf9 100644 --- a/modoboa/extensions/amavis/__init__.py +++ b/modoboa/extensions/amavis/__init__.py @@ -9,7 +9,7 @@ from django.template import Template, Context from modoboa.lib import events, parameters from modoboa.extensions import ModoExtension, exts_pool -class AmavisQuarantine(ModoExtension): +class Amavis(ModoExtension): name = "amavis" label = "Amavis frontend" version = "1.0" @@ -67,6 +67,8 @@ class AmavisQuarantine(ModoExtension): help=ugettext_lazy("Allow users to directly release their messages")) parameters.register_admin("SELF_SERVICE", type="list_yesno", deflt="no", help=ugettext_lazy("Activate the 'self-service' mode")) + parameters.register_admin("NOTIFICATIONS_SENDER", type="string", deflt="notification@modoboa.org", + help=ugettext_lazy("The e-mail address used to send notitications")) parameters.register_user( "MESSAGES_PER_PAGE", type="int", deflt=40, @@ -78,7 +80,7 @@ class AmavisQuarantine(ModoExtension): events.unregister("UserMenuDisplay", menu) parameters.unregister_app("amavis") -exts_pool.register_extension(AmavisQuarantine) +exts_pool.register_extension(Amavis) @events.observe("UserMenuDisplay") def menu(target, user): diff --git a/modoboa/extensions/amavis/cleanup.py b/modoboa/extensions/amavis/script/cleanup.py similarity index 95% rename from modoboa/extensions/amavis/cleanup.py rename to modoboa/extensions/amavis/script/cleanup.py index e16b8b3ce..df384cf31 100755 --- a/modoboa/extensions/amavis/cleanup.py +++ b/modoboa/extensions/amavis/script/cleanup.py @@ -5,7 +5,7 @@ import time from modoboa.extensions.amavis.models import * if __name__ == "__main__": - from modoboa.extensions import amavis + from modoboa.extensions.amavis import Amavis from modoboa.lib import parameters from optparse import OptionParser @@ -20,7 +20,7 @@ if __name__ == "__main__": l.setLevel(logging.DEBUG) l.addHandler(logging.StreamHandler()) - amavis.load() + Amavis().load() max_messages_age = int(parameters.get_admin("MAX_MESSAGES_AGE", app="amavis")) diff --git a/modoboa/extensions/amavis/script/notify.py b/modoboa/extensions/amavis/script/notify.py new file mode 100755 index 000000000..c88e9d2f1 --- /dev/null +++ b/modoboa/extensions/amavis/script/notify.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +# coding: utf-8 + +import sys, os +from django.template.loader import render_to_string +from django.core.urlresolvers import reverse +from django.utils.translation import ugettext as _ +from modoboa.lib import parameters +from modoboa.lib.emailutils import sendmail_simple +from modoboa.admin.models import User, Domain +from modoboa.extensions.amavis import Amavis +from modoboa.extensions.amavis.models import * + +sender = None +baseurl = None +listingurl = None + +def send_pr_notification(rcpt, reqs): + total = len(reqs) + reqs = reqs.all()[:10] + content = render_to_string("amavis/notifications/pending_requests.html", dict( + total=total, requests=reqs, baseurl=baseurl, listingurl=listingurl + )) + sendmail_simple(sender, rcpt, subject=_("[modoboa] Pending release requests"), + content=content, server=options.smtp_host, port=options.smtp_port) + +def notify_admins_pending_requests(): + sender = parameters.get_admin("NOTIFICATIONS_SENDER", app="amavis") + baseurl = options.baseurl.strip("/") + listingurl = baseurl + reverse("modoboa.extensions.amavis.views._listing") + "?viewrequests=1" + for da in User.objects.filter(groups__name="DomainAdmins"): + if not da.has_mailbox: + continue + rcpt = da.mailbox_set.all()[0].full_address + regexp = "(%s)" % '|'.join(map(lambda dom: dom.name, da.get_domains())) + reqs = Msgrcpt.objects.filter(rs='p', rid__email__regex=regexp) + if len(reqs): + send_pr_notification(rcpt, reqs) + + reqs = Msgrcpt.objects.filter(rs='p') + if not len(reqs): + return + for su in User.objects.filter(is_superuser=True): + if not su.has_mailbox: + continue + rcpt = su.mailbox_set.all()[0].full_address + send_pr_notification(rcpt, reqs) + +if __name__ == "__main__": + from optparse import OptionParser + + parser = OptionParser() + parser.add_option("--baseurl", type="string", default=None, + help="The scheme and hostname used to access Modoboa") + parser.add_option("--smtp_host", type="string", default="localhost", + help="The address of the SMTP server used to send notifications") + parser.add_option("--smtp_port", type="int", default=25, + help="The listening port of the SMTP server used to send notifications") + options, args = parser.parse_args() + + if not options.baseurl: + print >>sys.stderr, "You must provide the --baseurl option" + sys.exit(2) + + Amavis().load() + sender = parameters.get_admin("NOTIFICATIONS_SENDER", app="amavis") + baseurl = options.baseurl.strip("/") + listingurl = baseurl + reverse("modoboa.extensions.amavis.views._listing") + "?viewrequests=1" + notify_admins_pending_requests() + diff --git a/modoboa/extensions/amavis/templates/amavis/notifications/pending_requests.html b/modoboa/extensions/amavis/templates/amavis/notifications/pending_requests.html new file mode 100644 index 000000000..6628d7a04 --- /dev/null +++ b/modoboa/extensions/amavis/templates/amavis/notifications/pending_requests.html @@ -0,0 +1,14 @@ +{% load i18n libextras %}{% blocktrans count counter=total %} +{{ counter }} release request is pending for action. +{% plural %} +{{ counter }} release requests are pending for action. +{% endblocktrans %} +{% trans "Sketch:" %} +{% for msg in requests %} +{% trans "From:" %} {{ msg.mail.sid.email }} +{% trans "To:" %} {{ msg.rid.email }} +{% trans "Date:" %} {{ msg.mail.time_num|fromunix|date:"DATETIME_FORMAT" }} +{% trans "Subject:" %} {{ msg.mail.subject }} +{% trans "Act on this message:" %} {{ baseurl }}{% url modoboa.extensions.amavis.views.index %}#{{ msg.mail.mail_id }}/?rcpt={{ msg.rid.email }} +{% endfor %} +{% blocktrans %}Please visit {{ listingurl }} for a full listing.{% endblocktrans %} diff --git a/modoboa/lib/emailutils.py b/modoboa/lib/emailutils.py index 3d7b3d820..75b97695a 100644 --- a/modoboa/lib/emailutils.py +++ b/modoboa/lib/emailutils.py @@ -235,7 +235,7 @@ def __sendmail(sender, rcpt, msgstring, server='localhost', port=25): return False, "SMTP error: %s" % str(e) return True, None -def sendmail_simple(sender, rcpt, content=""): +def sendmail_simple(sender, rcpt, subject="Sample message", content="", **kwargs): """Simple way to send a text message Send a text/plain message with basic headers (msg-id, date). @@ -245,17 +245,18 @@ def sendmail_simple(sender, rcpt, content=""): :param sender: sender address :param rcpt: recipient address + :param subject: message's subject :param content: message's content :return: tuple """ msg = MIMEText(content) - msg["Subject"] = "Sample message" + msg["Subject"] = subject msg["From"] = sender msg["To"] = rcpt msg["Message-ID"] = make_msgid() msg["Date"] = formatdate(time.time(), True) - return __sendmail(sender, rcpt, msg.as_string()) + return __sendmail(sender, rcpt, msg.as_string(), **kwargs) def sendmail_fromfile(sender, rcpt, fname): """Send a message contained within a file diff --git a/modoboa/lib/templatetags/libextras.py b/modoboa/lib/templatetags/libextras.py index bab30a277..f65039c6f 100644 --- a/modoboa/lib/templatetags/libextras.py +++ b/modoboa/lib/templatetags/libextras.py @@ -1,5 +1,6 @@ # coding: utf-8 import os +import datetime from django.conf import settings from django import template from django.contrib import messages @@ -168,3 +169,7 @@ def progress_color(value): if value < 80: return "progress-warning" return "progress-danger" + +@register.filter +def fromunix(value): + return datetime.datetime.fromtimestamp(int(value))