diff --git a/modoboa/admin/models.py b/modoboa/admin/models.py index fbc561465..5bc96858e 100644 --- a/modoboa/admin/models.py +++ b/modoboa/admin/models.py @@ -840,11 +840,6 @@ class Extension(models.Model): path = os.path.join(settings.MEDIA_ROOT, self.name) exec_cmd("mkdir %s" % path) - scriptdir = "%s/%s" % (self.extdir, "scripts") - if os.path.exists(scriptdir): - targetdir = os.path.join(settings.MODOBOA_DIR, "scripts") - exec_cmd("ln -s %s %s/%s" % (scriptdir, targetdir, self.name)) - events.raiseEvent("ExtEnabled", self) def off(self): @@ -858,11 +853,6 @@ class Extension(models.Model): path = os.path.join(settings.MEDIA_ROOT, self.name) exec_cmd("rm -r %s" % path) - scriptdir = "%s/%s" % (self.extdir, "scripts") - if os.path.exists(scriptdir): - target = "%s/scripts/%s" % (settings.MODOBOA_DIR, self.name) - exec_cmd("rm %s" % target) - events.raiseEvent("ExtDisabled", self) def populate_callback(sender, user=None, **kwargs): diff --git a/modoboa/extensions/amavis/management/__init__.py b/modoboa/extensions/amavis/management/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/modoboa/extensions/amavis/management/commands/__init__.py b/modoboa/extensions/amavis/management/commands/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/modoboa/extensions/amavis/management/commands/amnotify.py b/modoboa/extensions/amavis/management/commands/amnotify.py new file mode 100644 index 000000000..7e4da1c66 --- /dev/null +++ b/modoboa/extensions/amavis/management/commands/amnotify.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +# coding: utf-8 + +import sys, os +from optparse import make_option +from django.core.management.base import BaseCommand, CommandError +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 * + +class Command(BaseCommand): + help = 'Amavis notification tool' + + sender = None + baseurl = None + listingurl = None + + option_list = BaseCommand.option_list + ( + make_option("--baseurl", type="string", default=None, + help="The scheme and hostname used to access Modoboa"), + make_option("--smtp_host", type="string", default="localhost", + help="The address of the SMTP server used to send notifications"), + make_option("--smtp_port", type="int", default=25, + help="The listening port of the SMTP server used to send notifications") + ) + + def handle(self, *args, **options): + if options["baseurl"] is None: + raise CommandError("You must provide the --baseurl option") + self.options = options + Amavis().load() + self.notify_admins_pending_requests() + + def send_pr_notification(self, rcpt, reqs): + total = len(reqs) + reqs = reqs.all()[:10] + content = render_to_string("amavis/notifications/pending_requests.html", dict( + total=total, requests=reqs, baseurl=self.baseurl, listingurl=self.listingurl + )) + sendmail_simple(self.sender, rcpt, subject=_("[modoboa] Pending release requests"), + content=content, + server=self.options["smtp_host"], port=self.options["smtp_port"]) + + def notify_admins_pending_requests(self): + self.sender = parameters.get_admin("NOTIFICATIONS_SENDER", app="amavis") + self.baseurl = self.options["baseurl"].strip("/") + self.listingurl = self.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): + self.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 + self.send_pr_notification(rcpt, reqs) diff --git a/modoboa/extensions/amavis/management/commands/qcleanup.py b/modoboa/extensions/amavis/management/commands/qcleanup.py new file mode 100644 index 000000000..d383f3b2c --- /dev/null +++ b/modoboa/extensions/amavis/management/commands/qcleanup.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# coding: utf-8 + +import time +from optparse import make_option +from django.core.management.base import BaseCommand +from modoboa.lib import parameters +from modoboa.extensions.amavis import Amavis +from modoboa.extensions.amavis.models import * + +class Command(BaseCommand): + args = '' + help = 'Amavis quarantine cleanup' + + option_list = BaseCommand.option_list + ( + make_option('--debug', + action='store_true', + default=False, + help='Activate debug output'), + ) + + def handle(self, *args, **options): + if options["debug"]: + import logging + l = logging.getLogger("django.db.backends") + l.setLevel(logging.DEBUG) + l.addHandler(logging.StreamHandler()) + + Amavis().load() + + max_messages_age = int(parameters.get_admin("MAX_MESSAGES_AGE", + app="amavis")) + + flags = ['D'] + if parameters.get_admin("RELEASED_MSGS_CLEANUP", + app="amavis") == "yes": + flags += ['R'] + + print "Deleting marked messages..." + ids = Msgrcpt.objects.filter(rs__in=flags).values("mail_id") + for msg in Msgs.objects.filter(mail_id__in=ids): + if not msg.msgrcpt_set.exclude(rs__in=flags).count(): + msg.delete() + + print "Deleting messages older than %d days..." % max_messages_age + limit = int(time.time()) - (max_messages_age * 24 * 3600) + Msgs.objects.filter(time_num__lt=limit).delete() + + print "Deleting unreferenced e-mail addresses..." + for maddr in Maddr.objects.all(): + if not len(maddr.msgs_set.all()) and not len(maddr.msgrcpt_set.all()): + maddr.delete() + + print "Done." diff --git a/modoboa/extensions/amavis/script/cleanup.py b/modoboa/extensions/amavis/script/cleanup.py deleted file mode 100755 index df384cf31..000000000 --- a/modoboa/extensions/amavis/script/cleanup.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import time -from modoboa.extensions.amavis.models import * - -if __name__ == "__main__": - from modoboa.extensions.amavis import Amavis - from modoboa.lib import parameters - from optparse import OptionParser - - parser = OptionParser() - parser.add_option("--debug", action="store_true", - help="Activate debug output") - options, args = parser.parse_args() - - if options.debug: - import logging - l = logging.getLogger("django.db.backends") - l.setLevel(logging.DEBUG) - l.addHandler(logging.StreamHandler()) - - Amavis().load() - - max_messages_age = int(parameters.get_admin("MAX_MESSAGES_AGE", - app="amavis")) - - flags = ['D'] - if parameters.get_admin("RELEASED_MSGS_CLEANUP", - app="amavis") == "yes": - flags += ['R'] - - print "Deleting marked messages..." - ids = Msgrcpt.objects.filter(rs__in=flags).values("mail_id") - for msg in Msgs.objects.filter(mail_id__in=ids): - if not msg.msgrcpt_set.exclude(rs__in=flags).count(): - msg.delete() - - print "Deleting messages older than %d days..." % max_messages_age - limit = int(time.time()) - (max_messages_age * 24 * 3600) - Msgs.objects.filter(time_num__lt=limit).delete() - - print "Deleting unreferenced e-mail addresses..." - for maddr in Maddr.objects.all(): - if not len(maddr.msgs_set.all()) and not len(maddr.msgrcpt_set.all()): - maddr.delete() - - print "Done." - diff --git a/modoboa/extensions/amavis/script/notify.py b/modoboa/extensions/amavis/script/notify.py deleted file mode 100755 index c88e9d2f1..000000000 --- a/modoboa/extensions/amavis/script/notify.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/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/postfix_autoreply/management/__init__.py b/modoboa/extensions/postfix_autoreply/management/__init__.py new file mode 100644 index 000000000..394a0a067 --- /dev/null +++ b/modoboa/extensions/postfix_autoreply/management/__init__.py @@ -0,0 +1,2 @@ +#!/usr/bin/env python +# coding: utf-8 diff --git a/modoboa/extensions/postfix_autoreply/management/commands/__init__.py b/modoboa/extensions/postfix_autoreply/management/commands/__init__.py new file mode 100644 index 000000000..394a0a067 --- /dev/null +++ b/modoboa/extensions/postfix_autoreply/management/commands/__init__.py @@ -0,0 +1,2 @@ +#!/usr/bin/env python +# coding: utf-8 diff --git a/modoboa/extensions/postfix_autoreply/scripts/autoreply.py b/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py old mode 100755 new mode 100644 similarity index 63% rename from modoboa/extensions/postfix_autoreply/scripts/autoreply.py rename to modoboa/extensions/postfix_autoreply/management/commands/autoreply.py index 6b94427f1..442bfc251 --- a/modoboa/extensions/postfix_autoreply/scripts/autoreply.py +++ b/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py @@ -5,6 +5,7 @@ import sys import smtplib from email.mime.text import MIMEText import datetime +from django.core.management.base import BaseCommand, CommandError from modoboa.lib import parameters from modoboa.lib.emailutils import split_mailbox from modoboa.admin.models import Mailbox @@ -44,22 +45,26 @@ def send_autoreply(sender, mailbox, armessage): lastar.last_sent = datetime.datetime.now() lastar.save() -if __name__ == "__main__": - if len(sys.argv) < 3: - print "Not enough arguments, aborting." - sys.exit(1) - sender = sys.argv[1] - for fulladdress in sys.argv[2:]: - address, domain = split_mailbox(fulladdress) - try: - mbox = Mailbox.objects.get(address=address, domain__name=domain) - except Mailbox.DoesNotExist: - print "Unknown recipient %s" % (mbox) - continue - try: - armessage = ARmessage.objects.get(mbox=mbox.id, enabled=True) - except ARmessage.DoesNotExist: - continue +class Command(BaseCommand): + args = ' ' + help = 'Send autoreply emails' - send_autoreply(sender, mbox, armessage) + def handle(self, *args, **options): + if len(args) < 2: + raise CommandError("usage: ./manage.py autoreply ") + + sender = args[0] + for fulladdress in args[1:]: + address, domain = split_mailbox(fulladdress) + try: + mbox = Mailbox.objects.get(address=address, domain__name=domain) + except Mailbox.DoesNotExist: + print "Unknown recipient %s" % (mbox) + continue + try: + armessage = ARmessage.objects.get(mbox=mbox.id, enabled=True) + except ARmessage.DoesNotExist: + continue + + send_autoreply(sender, mbox, armessage) diff --git a/modoboa/extensions/postfix_autoreply/scripts/autoreply b/modoboa/extensions/postfix_autoreply/scripts/autoreply deleted file mode 100755 index 588e1f6bc..000000000 --- a/modoboa/extensions/postfix_autoreply/scripts/autoreply +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -PYTHON=python -BASEDIR=/var/www -# If the user executing this script has no homedir or no shell, you -# must need to set the above variable. -EGG_CACHE="" - -PYTHON_EGG_CACHE=$EGG_CACHE PYTHONPATH=$BASEDIR \ - DJANGO_SETTINGS_MODULE=modoboa.settings $PYTHON \ - $BASEDIR/modoboa/scripts/postfix_autoreply/autoreply.py $@ diff --git a/modoboa/extensions/stats/management/__init__.py b/modoboa/extensions/stats/management/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/modoboa/extensions/stats/management/commands/__init__.py b/modoboa/extensions/stats/management/commands/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/modoboa/extensions/stats/scripts/logparser.py b/modoboa/extensions/stats/management/commands/logparser.py old mode 100755 new mode 100644 similarity index 88% rename from modoboa/extensions/stats/scripts/logparser.py rename to modoboa/extensions/stats/management/commands/logparser.py index 0d9a9adc4..7abb37af8 --- a/modoboa/extensions/stats/scripts/logparser.py +++ b/modoboa/extensions/stats/management/commands/logparser.py @@ -1,16 +1,5 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- -import time -import sys -import os -import re -import rrdtool -import string, pdb -from optparse import OptionParser -from modoboa.lib import parameters -from modoboa.admin.models import Domain -import modoboa.extensions.stats.grapher as grapher - +# coding: utf-8 """ Postfix log parser. @@ -28,27 +17,32 @@ Predefined events are: * Global consolidation of all previous events. """ - -rrdstep = 60 -xpoints = 540 -points_per_sample = 3 -variables = ["sent", "recv", "bounced", "reject", "spam", "virus", - "size_sent", "size_recv"] - +import time +import sys +import os +import re +import rrdtool +import string +from django.core.management.base import BaseCommand, CommandError +from optparse import make_option +from modoboa.lib import parameters +from modoboa.admin.models import Domain +from modoboa.extensions.stats import Stats +import modoboa.extensions.stats.grapher as grapher class LogParser(object): def __init__(self, options, workdir, year=None): - self.logfile = options.logfile + self.logfile = options["logfile"] try: self.f = open(self.logfile) except IOError, errno: - if options.debug: + if options["debug"]: print "%s" % errno sys.exit(1) self.workdir = workdir self.year = year - self.debug = options.debug - self.verbose = options.verbose + self.debug = options["debug"] + self.verbose = options["verbose"] self.cfs = ['AVERAGE', 'MAX'] self.last_month = None @@ -256,22 +250,22 @@ class LogParser(object): G.make_defaults(dom, tpl=grapher.badtraffic_avg_template) G.make_defaults(dom, tpl=grapher.size_avg_template) -if __name__ == "__main__": - from modoboa.extensions.stats import Stats - Stats().load() +class Command(BaseCommand): + help = 'Log file parser' - log_file = parameters.get_admin("LOGFILE", app="stats") - rrd_rootdir = parameters.get_admin("RRD_ROOTDIR", app="stats") + option_list = BaseCommand.option_list + ( + make_option("--logfile", default=None, + help="postfix log in syslog format", metavar="FILE"), + make_option("--verbose", default=False, action="store_true", + dest="verbose", help="Set verbose mode"), + make_option("--debug", default=False, action="store_true", + help="Set debug mode") + ) - parser = OptionParser() - parser.add_option("-l","--logfile", default=log_file, - help="postfix log in syslog format", metavar="FILE") - parser.add_option("-v","--verbose", default=False, action="store_true", - dest="verbose", help="set verbose mode") - parser.add_option("-d","--debug", default=False, action="store_true", - help="set debug mode") - (options, args) = parser.parse_args() - - P = LogParser(options, rrd_rootdir) - P.process() + def handle(self, *args, **options): + Stats().load() + if options["logfile"] is None: + options["logfile"] = parameters.get_admin("LOGFILE", app="stats") + p = LogParser(options, parameters.get_admin("RRD_ROOTDIR", app="stats")) + p.process()