diff --git a/modoboa/extensions/amavis/general_callbacks.py b/modoboa/extensions/amavis/general_callbacks.py index 1246c7202..ce2f76e91 100644 --- a/modoboa/extensions/amavis/general_callbacks.py +++ b/modoboa/extensions/amavis/general_callbacks.py @@ -1,6 +1,7 @@ from django.core.urlresolvers import reverse from django.utils.translation import ugettext as _ from django.template import Template, Context + from modoboa.lib import events, parameters from modoboa.extensions.admin.models import DomainAlias from modoboa.extensions.amavis.lib import ( @@ -96,12 +97,12 @@ $(document).bind('domform_init', function() { @events.observe("TopNotifications") def display_requests(user): - from .sql_listing import get_wrapper + from .sql_connector import get_connector if parameters.get_admin("USER_CAN_RELEASE") == "yes" \ or user.group == "SimpleUsers": return [] - nbrequests = get_wrapper().get_pending_requests(user) + nbrequests = get_connector(user=user).get_pending_requests() url = reverse("modoboa.extensions.amavis.views.index") url += "#listing/?viewrequests=1" diff --git a/modoboa/extensions/amavis/lib.py b/modoboa/extensions/amavis/lib.py index 9a9ed39bd..20f02a6c3 100644 --- a/modoboa/extensions/amavis/lib.py +++ b/modoboa/extensions/amavis/lib.py @@ -75,7 +75,7 @@ recipient=%s """ % (mailid, secretid, recipient)) answer = self.sock.recv(1024) answer = self.decode(answer) - if re.search("250 [\d\.]+ Ok", answer): + if re.search(r"250 [\d\.]+ Ok", answer): return True return False @@ -88,7 +88,9 @@ class QuarantineNavigationParameters(NavigationParameters): super(QuarantineNavigationParameters, self).__init__( request, 'quarantine_navparams' ) - self.parameters += [('msgtype', None, False)] + self.parameters += [ + ('msgtype', None, False), ('viewrequests', None, False) + ] def back_to_listing(self): """Return the current listing URL. diff --git a/modoboa/extensions/amavis/management/commands/amnotify.py b/modoboa/extensions/amavis/management/commands/amnotify.py index 54846b12e..1ed96f37d 100644 --- a/modoboa/extensions/amavis/management/commands/amnotify.py +++ b/modoboa/extensions/amavis/management/commands/amnotify.py @@ -1,20 +1,23 @@ #!/usr/bin/env python # coding: utf-8 from optparse import make_option + from django import db 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.core.models import User from modoboa.lib import parameters from modoboa.lib.emailutils import sendmail_simple from modoboa.extensions.admin.models import Domain + from modoboa.extensions.amavis import Amavis from modoboa.extensions.amavis.models import ( Msgrcpt ) -from modoboa.extensions.amavis.sql_listing import get_wrapper +from modoboa.extensions.amavis.sql_connector import get_connector class Command(BaseCommand): @@ -75,7 +78,7 @@ class Command(BaseCommand): if not da.mailbox_set.count(): continue rcpt = da.mailbox_set.all()[0].full_address - reqs = get_wrapper().get_domains_pending_requests( + reqs = get_connector().get_domains_pending_requests( Domain.objects.get_for_admin(da) ) if reqs.count(): diff --git a/modoboa/extensions/amavis/sql_connector.py b/modoboa/extensions/amavis/sql_connector.py new file mode 100644 index 000000000..12637781f --- /dev/null +++ b/modoboa/extensions/amavis/sql_connector.py @@ -0,0 +1,291 @@ +""" +SQL connector module. +""" +from django.db.models import Q + +from modoboa.extensions.admin.models import Domain +from modoboa.lib.dbutils import db_type +from modoboa.lib.webutils import static_url + +from .models import Quarantine, Msgrcpt, Maddr + + +class SQLconnector(object): + + """ + This class handles all database operations. + """ + + ORDER_TRANSLATION_TABLE = { + "type": "content", + "score": "bspam_level", + "date": "mail__time_num", + "subject": "mail__subject", + "from": "mail__from_addr", + "to": "rid__email" + } + + QUARANTINE_FIELDS = [ + "content", + "bspam_level", + "rs", + "rid__email", + "mail__from_addr", + "mail__subject", + "mail__mail_id", + "mail__time_num", + ] + + def __init__(self, user=None, navparams=None): + """Constructor.""" + self.user = user + self.navparams = navparams + self.messages = None + + self._messages_count = None + + def _exec(self, query, args): + """Execute a raw SQL query. + + :param string query: query to execute + :param list args: a list of arguments to replace in :kw:`query` + """ + from django.db import connections, transaction + + cursor = connections['amavis'].cursor() + cursor.execute(query, args) + transaction.commit_unless_managed(using='amavis') + + def _apply_msgrcpt_filters(self, flt): + """Return filters based on user's role. + + """ + if self.user.group == 'SimpleUsers': + rcpts = [self.user.email] \ + + self.user.mailbox_set.all()[0].alias_addresses + flt &= Q(rid__email__in=rcpts) + elif not self.user.is_superuser: + doms = Domain.objects.get_for_admin(self.user) + regexp = "(%s)" % '|'.join([dom.name for dom in doms]) + flt &= Q(rid__email__regex=regexp) + + def _apply_extra_search_filter(self, crit, pattern): + if crit == "to": + return Q(rid__email__contains=pattern) + return None + + def _apply_extra_select_filters(self, messages): + pass + + def _get_quarantine_content(self): + """Fetch quarantine content. + + Filters: rs, rid, content + """ + flt = Q(rs__in=[' ', 'V', 'R', 'p']) \ + if self.navparams.get('viewrequests', '0') != '1' else Q(rs='p') + self._apply_msgrcpt_filters(flt) + pattern = self.navparams.get("pattern", "") + if pattern: + criteria = self.navparams.get('criteria') + if criteria == "both": + criteria = "from_addr,subject,to" + search_flt = None + for crit in criteria.split(","): + if crit == "from_addr": + nfilter = Q(mail__from_addr__contains=pattern) + elif crit == "subject": + nfilter = Q(mail__subject__contains=pattern) + else: + nfilter = self._apply_extra_search_filter(crit, pattern) + if nfilter is None: + continue + search_flt = nfilter \ + if search_flt is None else search_flt | nfilter + if search_flt: + flt &= search_flt + msgtype = self.navparams.get('msgtype', None) + if msgtype is not None: + flt &= Q(content=msgtype) + + flt &= Q( + mail__in=Quarantine.objects.filter(chunk_ind=1).values("mail_id") + ) + + messages = Msgrcpt.objects.select_related().filter(flt) + self._apply_extra_select_filters(messages) + return messages + + def messages_count(self, **kwargs): + """Return the total number of messages living in the quarantine. + + We also store the built queryset for a later use. + """ + if self.user is None or self.navparams is None: + return None + if self._messages_count is None: + self.messages = self._get_quarantine_content() + self.messages = self.messages.values(*self.QUARANTINE_FIELDS) + + order = self.navparams.get("order") + if order is not None: + sign = "" + if order[0] == "-": + sign = "-" + order = order[1:] + order = self.ORDER_TRANSLATION_TABLE[order] + self.messages = self.messages.order_by(sign + order) + + self._messages_count = self.messages.count() + + return self._messages_count + + def fetch(self, start=None, stop=None, **kwargs): + """Fetch a range of messages from the internal cache. + + """ + emails = [] + for qm in self.messages[start - 1:stop]: + m = {"from": qm["mail__from_addr"], + "to": qm["rid__email"], + "subject": qm["mail__subject"], + "mailid": qm["mail__mail_id"], + "date": qm["mail__time_num"], + "type": qm["content"], + "score": qm["bspam_level"]} + rs = qm["rs"] + if rs == 'D': + continue + elif rs in ['', ' ']: + m["class"] = "unseen" + elif rs == 'R': + m["img_rstatus"] = static_url("pics/release.png") + elif rs == 'p': + m["class"] = "pending" + emails.append(m) + return emails + + def set_msgrcpt_status(self, address, mailid, status): + """Change the status (rs field) of a message recipient. + + :param string status: status + """ + addr = Maddr.objects.get(email=address) + self._exec( + "UPDATE msgrcpt SET rs=%s WHERE mail_id=%s AND rid=%s", + [status, mailid, addr.id] + ) + + def get_recipient_messages(self, address, mailids): + return Msgrcpt.objects.filter(mail__in=mailids, rid__email=address) + + def get_domains_pending_requests(self, domains): + regexp = "(%s)" % '|'.join([dom.name for dom in domains]) + return Msgrcpt.objects.filter(rs='p', rid__email__regex=regexp) + + def get_pending_requests(self): + """Return the number of requests currently pending. + + :param user: a ``User`` instance + """ + rq = Q(rs='p') + if not self.user.is_superuser: + doms = Domain.objects.get_for_admin(self.user) + if not doms.count(): + return 0 + regexp = "(%s)" % '|'.join([dom.name for dom in doms]) + doms_q = Q(rid__email__regex=regexp) + rq &= doms_q + return Msgrcpt.objects.filter(rq).count() + + def get_mail_content(self, mailid): + return Quarantine.objects.filter(mail=mailid) + + +class PgSQLconnector(SQLconnector): + + """ + The postgres version. + + Make use of ``QuerySet.extra`` and postgres ``convert_from`` + function to let the quarantine manager work as expected ! + """ + + def _apply_msgrcpt_filters(self, flt): + """Return filters based on user's role. + + """ + self._where = ["U0.rid=maddr.id"] + if self.user.group == 'SimpleUsers': + rcpts = [self.user.email] \ + + self.user.mailbox_set.all()[0].alias_addresses + self._where.append( + "convert_from(maddr.email, 'UTF8') IN (%s)" \ + % (','.join(["'%s'" % rcpt for rcpt in rcpts]))) + elif not self.user.is_superuser: + doms = Domain.objects.get_for_admin(self.user) + regexp = "(%s)" % '|'.join([dom.name for dom in doms]) + self._where.append( + "convert_from(maddr.email, 'UTF8') ~ '%s'" % regexp) + + def _apply_extra_search_filter(self, crit, pattern): + if crit == "to": + self._where.append( + "convert_from(maddr.email, 'UTF8') LIKE '%%%s%%'" + % pattern) + return None + + def _apply_extra_select_filters(self, messages): + messages = messages.extra(where=self._where, tables=['maddr']) + + def get_recipient_message(self, address, mailid): + qset = Msgrcpt.objects.filter(mail=mailid).extra( + where=["msgrcpt.rid=maddr.id", + "convert_from(maddr.email, 'UTF8') = '%s'" % address], + tables=['maddr'] + ) + return qset.all()[0] + + def get_recipient_messages(self, address, mailids): + return Msgrcpt.objects.filter(mail__in=mailids).extra( + where=["U0.rid=maddr.id", + "convert_from(maddr.email, 'UTF8') = '%s'" % address], + tables=['maddr'] + ) + + def get_domains_pending_requests(self, domains): + regexp = "(%s)" % '|'.join([dom.name for dom in domains]) + return Msgrcpt.objects.filter(rs='p').extra( + where=["msgrcpt.rid=maddr.id", + "convert_from(maddr.email, 'UTF8') ~ '%s'" % regexp], + tables=['maddr'] + ) + + def get_pending_requests(self): + rq = Q(rs='p') + if not self.user.is_superuser: + doms = Domain.objects.get_for_admin(self.user) + if not doms.count(): + return 0 + regexp = "(%s)" % '|'.join([dom.name for dom in doms]) + return Msgrcpt.objects.filter(rq).extra( + where=["msgrcpt.rid=maddr.id", + "convert_from(maddr.email, 'UTF8') ~ '%s'" % (regexp,)], + tables=['maddr'] + ).count() + return Msgrcpt.objects.filter(rq).count() + + def get_mail_content(self, mailid): + return Quarantine.objects.filter(mail=mailid).extra( + select={'mail_text': "convert_from(mail_text, 'UTF8')"} + ) + + +def get_connector(**kwargs): + """Return the appropriate *connector* class. + + The result depends on the DB engine in use. + """ + if db_type("amavis") == 'postgres': + return PgSQLconnector(**kwargs) + return SQLconnector(**kwargs) diff --git a/modoboa/extensions/amavis/sql_listing.py b/modoboa/extensions/amavis/sql_listing.py index ac1b378ed..c8cbaf122 100644 --- a/modoboa/extensions/amavis/sql_listing.py +++ b/modoboa/extensions/amavis/sql_listing.py @@ -1,16 +1,14 @@ # coding: utf-8 -import re from datetime import datetime + from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy -from django.db.models import Q + from modoboa.lib import tables -from modoboa.lib.webutils import static_url -from modoboa.lib.email_listing import MBconnector, EmailListing +from modoboa.lib.email_listing import EmailListing from modoboa.lib.emailutils import Email -from modoboa.lib.dbutils import db_type -from modoboa.extensions.admin.models import Domain -from .models import Quarantine, Msgrcpt + +from .sql_connector import get_connector class Qtable(tables.Table): @@ -60,238 +58,6 @@ class Qtable(tables.Table): return datetime.fromtimestamp(value) -class SQLconnector(MBconnector): - order_translation_table = { - "type": "mail__msgrcpt__content", - "score": "mail__msgrcpt__bspam_level", - "date": "mail__time_num", - "subject": "mail__subject", - "from": "mail__from_addr", - "to": "mail__msgrcpt__rid__email" - } - - def __init__(self, mail_ids=None, filter=None): - self.count = None - self.messages = None - self.mail_ids = mail_ids - self.filter = filter - - def messages_count(self, **kwargs): - if self.count is None: - filter = Q(chunk_ind=1) - if self.mail_ids is not None: - filter &= Q(mail__in=self.mail_ids) - if self.filter: - filter &= self.filter - self.messages = Quarantine.objects.filter(filter).values( - "mail__from_addr", - "mail__msgrcpt__rid__email", - "mail__subject", - "mail__mail_id", - "mail__time_num", - "mail__msgrcpt__content", - "mail__msgrcpt__bspam_level", - "mail__msgrcpt__rs" - ) - if "order" in kwargs: - order = kwargs["order"] - sign = "" - if order[0] == "-": - sign = "-" - order = order[1:] - order = self.order_translation_table[order] - self.messages = self.messages.order_by(sign + order) - - self.count = self.messages.count() - return self.count - - def fetch(self, start=None, stop=None, **kwargs): - emails = [] - for qm in self.messages[start - 1:stop]: - m = {"from": qm["mail__from_addr"], - "to": qm["mail__msgrcpt__rid__email"], - "subject": qm["mail__subject"], - "mailid": qm["mail__mail_id"], - "date": qm["mail__time_num"], - "type": qm["mail__msgrcpt__content"], - "score": qm["mail__msgrcpt__bspam_level"]} - rs = qm["mail__msgrcpt__rs"] - if rs == 'D': - continue - elif rs in ['', ' ']: - m["class"] = "unseen" - elif rs == 'R': - m["img_rstatus"] = static_url("pics/release.png") - elif rs == 'p': - m["class"] = "pending" - emails.append(m) - return emails - - -class SQLWrapper(object): - """A simple SQL wrapper. - - This wrapper has been added just to answer the *Postgres bytea - fields* issue :p - - The base class doesn't add anything special but defines the method - (and so piece of SQL queries) that should be overloaded when - Postgres is in use. - - See ``PgWrapper`` for the real mess... - """ - - def _exec(self, query, args): - """Execute a raw SQL query. - - :param string query: query to execute - :param list args: a list of arguments to replace in :kw:`query` - """ - from django.db import connections, transaction - - cursor = connections['amavis'].cursor() - cursor.execute(query, args) - transaction.commit_unless_managed(using='amavis') - - def get_mails(self, request, rcptfilter=None): - """Retrieve all messages visible by a user. - - Simple users can only see the messages - - :rtype: QuerySet - """ - q = Q(rs='p') \ - if request.GET.get("viewrequests", None) == "1" else ~Q(rs='D') - if request.user.group == 'SimpleUsers': - rcpts = [request.user.email] \ - + request.user.mailbox_set.all()[0].alias_addresses - q &= Q(rid__email__in=rcpts) - elif not request.user.is_superuser: - doms = Domain.objects.get_for_admin(request.user) - regexp = "(%s)" % '|'.join([dom.name for dom in doms]) - doms_q = Q(rid__email__regex=regexp) - q &= doms_q - if rcptfilter is not None: - q &= Q(rid__email__contains=rcptfilter) - return Msgrcpt.objects.filter(q).values("mail_id") - - def get_recipient_message(self, address, mailid): - return Msgrcpt.objects.get(mail=mailid, rid__email=address) - - def set_msgrcpt_status(self, address, mailid, status): - """Change the status (rs field) of a message recipient. - - :param string status: status - """ - from modoboa.extensions.amavis.models import Maddr - - addr = Maddr.objects.get(email=address) - self._exec( - "UPDATE msgrcpt SET rs=%s WHERE mail_id=%s AND rid=%s", - [status, mailid, addr.id] - ) - - def get_recipient_messages(self, address, mailids): - return Msgrcpt.objects.filter(mail__in=mailids, rid__email=address) - - def get_domains_pending_requests(self, domains): - regexp = "(%s)" % '|'.join([dom.name for dom in domains]) - return Msgrcpt.objects.filter(rs='p', rid__email__regex=regexp) - - def get_pending_requests(self, user): - """Return the number of current pending requests - - :param user: a ``User`` instance - """ - rq = Q(rs='p') - if not user.is_superuser: - doms = Domain.objects.get_for_admin(user) - if not doms.count(): - return 0 - regexp = "(%s)" % '|'.join([dom.name for dom in doms]) - doms_q = Q(rid__email__regex=regexp) - rq &= doms_q - return Msgrcpt.objects.filter(rq).count() - - def get_mail_content(self, mailid): - return Quarantine.objects.filter(mail=mailid) - - -class PgWrapper(SQLWrapper): - """The postgres wrapper - - Make use of ``QuerySet.extra`` and postgres ``convert_from`` - function to let the quarantine manager work as expected ! - """ - - def get_mails(self, request, rcptfilter=None): - q = Q(rs='p') \ - if request.GET.get("viewrequests", None) == "1" else ~Q(rs='D') - where = ["U0.rid=maddr.id"] - if request.user.group == 'SimpleUsers': - rcpts = [request.user.email] \ - + request.user.mailbox_set.all()[0].alias_addresses - where.append("convert_from(maddr.email, 'UTF8') IN (%s)" \ - % (','.join(["'%s'" % rcpt for rcpt in rcpts]))) - elif not request.user.is_superuser: - doms = Domain.objects.get_for_admin(request.user) - regexp = "(%s)" % '|'.join([dom.name for dom in doms]) - where.append("convert_from(maddr.email, 'UTF8') ~ '%s'" % regexp) - if rcptfilter is not None: - where.append("convert_from(maddr.email, 'UTF8') LIKE '%%%s%%'" - % rcptfilter) - return Msgrcpt.objects.filter(q)\ - .extra(where=where, tables=['maddr']).values("mail_id") - - def get_recipient_message(self, address, mailid): - qset = Msgrcpt.objects.filter(mail=mailid).extra( - where=["msgrcpt.rid=maddr.id", "convert_from(maddr.email, 'UTF8') = '%s'" % address], - tables=['maddr'] - ) - return qset.all()[0] - - def get_recipient_messages(self, address, mailids): - return Msgrcpt.objects.filter(mail__in=mailids).extra( - where=["U0.rid=maddr.id", "convert_from(maddr.email, 'UTF8') = '%s'" % address], - tables=['maddr'] - ) - - def get_domains_pending_requests(self, domains): - regexp = "(%s)" % '|'.join([dom.name for dom in domains]) - return Msgrcpt.objects.filter(rs='p').extra( - where=["msgrcpt.rid=maddr.id", "convert_from(maddr.email, 'UTF8') ~ '%s'" % regexp], - tables=['maddr'] - ) - - def get_pending_requests(self, user): - rq = Q(rs='p') - if not user.is_superuser: - doms = Domain.objects.get_for_admin(user) - if not doms.count(): - return 0 - regexp = "(%s)" % '|'.join([dom.name for dom in doms]) - return Msgrcpt.objects.filter(rq).extra( - where=["msgrcpt.rid=maddr.id", "convert_from(maddr.email, 'UTF8') ~ '%s'" % (regexp,)], - tables=['maddr'] - ).count() - return Msgrcpt.objects.filter(rq).count() - - def get_mail_content(self, mailid): - return Quarantine.objects.filter(mail=mailid).extra( - select={'mail_text': "convert_from(mail_text, 'UTF8')"} - ) - - -def get_wrapper(): - """Return the appropriate *Wrapper class - - The result depends on the DB engine in use. - """ - if db_type("amavis") == 'postgres': - return PgWrapper() - return SQLWrapper() - - class SQLlisting(EmailListing): tpl = "amavis/index.html" tbltype = Qtable @@ -299,8 +65,8 @@ class SQLlisting(EmailListing): defcallback = "updatelisting" reset_wm_url = True - def __init__(self, user, msgs, filter, **kwargs): - self.mbc = SQLconnector(msgs, filter) + def __init__(self, user, **kwargs): + self.mbc = get_connector(user=user, navparams=kwargs["navparams"]) super(SQLlisting, self).__init__(**kwargs) self.show_listing_headers = True @@ -333,7 +99,7 @@ class SQLemail(Email): import email if self._msg is None: - qmails = get_wrapper().get_mail_content(self.mailid) + qmails = get_connector().get_mail_content(self.mailid) self._msg = email.message_from_string( "".join([qm.mail_text for qm in qmails]) ) diff --git a/modoboa/extensions/amavis/views.py b/modoboa/extensions/amavis/views.py index 8eb7da2fb..31514820a 100644 --- a/modoboa/extensions/amavis/views.py +++ b/modoboa/extensions/amavis/views.py @@ -7,7 +7,6 @@ from django.utils.translation import ugettext as _, ungettext from django.core.urlresolvers import reverse from django.contrib.auth.decorators \ import login_required, user_passes_test -from django.db.models import Q from modoboa.lib import parameters from modoboa.lib.exceptions import BadRequest from modoboa.lib.webutils import ( @@ -19,8 +18,9 @@ from modoboa.extensions.amavis.templatetags.amavis_tags import ( quar_menu, viewm_menu ) from .lib import selfservice, AMrelease, QuarantineNavigationParameters -from .sql_listing import SQLlisting, SQLemail, get_wrapper from .models import Msgrcpt +from .sql_connector import get_connector +from .sql_listing import SQLlisting, SQLemail def empty_quarantine(request): @@ -31,45 +31,21 @@ def empty_quarantine(request): @login_required def _listing(request): - flt = None - rcptfilter = None - msgs = None - if not request.user.is_superuser and request.user.group != 'SimpleUsers': if not Domain.objects.get_for_admin(request.user).count(): return empty_quarantine(request) navparams = QuarantineNavigationParameters(request) navparams.store() - pattern = navparams.get('pattern', '') - if pattern: - criteria = navparams.get('criteria') - if criteria == "both": - criteria = "from_addr,subject,to" - for c in criteria.split(","): - if c == "from_addr": - nfilter = Q(mail__from_addr__contains=pattern) - elif c == "subject": - nfilter = Q(mail__subject__contains=pattern) - elif c == "to": - rcptfilter = pattern - continue - else: - raise BadRequest("unsupported search criteria %s" % c) - flt = nfilter if flt is None else flt | nfilter - msgtype = navparams.get('msgtype', None) - if msgtype is not None: - nfilter = Q(mail__msgrcpt__content=msgtype) - flt = flt | nfilter if flt is not None else nfilter - msgs = get_wrapper().get_mails(request, rcptfilter) - page = navparams.get('page') lst = SQLlisting( - request.user, msgs, flt, - navparams=request.session["quarantine_navparams"], - elems_per_page=int(parameters.get_user(request.user, "MESSAGES_PER_PAGE")) + request.user, + navparams=navparams, + elems_per_page=int( + parameters.get_user(request.user, "MESSAGES_PER_PAGE") + ) ) - page = lst.paginator.getpage(page) + page = lst.paginator.getpage(navparams.get('page')) if not page: return empty_quarantine(request) @@ -129,7 +105,7 @@ def viewmail(request, mail_id): if request.user.mailbox_set.count(): mb = Mailbox.objects.get(user=request.user) if rcpt == mb.full_address or rcpt in mb.alias_addresses: - get_wrapper().set_msgrcpt_status(rcpt, mail_id, 'V') + get_connector().set_msgrcpt_status(rcpt, mail_id, 'V') content = Template(""" @@ -143,7 +119,7 @@ def viewmail(request, mail_id): @login_required def viewheaders(request, mail_id): content = "" - for qm in get_wrapper().get_mail_content(mail_id): + for qm in get_connector().get_mail_content(mail_id): content += qm.mail_text msg = email.message_from_string(content) return render(request, 'amavis/viewheader.html', { @@ -165,7 +141,7 @@ def delete_selfservice(request, mail_id): if rcpt is None: raise BadRequest(_("Invalid request")) try: - get_wrapper().set_msgrcpt_status(rcpt, mail_id, 'D') + get_connector().set_msgrcpt_status(rcpt, mail_id, 'D') except Msgrcpt.DoesNotExist: raise BadRequest(_("Invalid request")) return render_to_json_response(_("Message deleted")) @@ -178,7 +154,7 @@ def delete(request, mail_id): :param str mail_id: message unique identifier """ mail_id = check_mail_id(request, mail_id) - wrapper = get_wrapper() + connector = get_connector() mb = Mailbox.objects.get(user=request.user) \ if request.user.group == 'SimpleUsers' else None for mid in mail_id: @@ -186,7 +162,7 @@ def delete(request, mail_id): if mb is not None and r != mb.full_address \ and not r in mb.alias_addresses: continue - wrapper.set_msgrcpt_status(r, i, 'D') + connector.set_msgrcpt_status(r, i, 'D') message = ungettext("%(count)d message deleted successfully", "%(count)d messages deleted successfully", len(mail_id)) % {"count": len(mail_id)} @@ -201,21 +177,21 @@ def release_selfservice(request, mail_id): secret_id = request.GET.get("secret_id", None) if rcpt is None or secret_id is None: raise BadRequest(_("Invalid request")) - wrapper = get_wrapper() + connector = get_connector() try: - msgrcpt = wrapper.get_recipient_message(rcpt, mail_id) + msgrcpt = connector.get_recipient_message(rcpt, mail_id) except Msgrcpt.DoesNotExist: raise BadRequest(_("Invalid request")) if secret_id != msgrcpt.mail.secret_id: raise BadRequest(_("Invalid request")) if parameters.get_admin("USER_CAN_RELEASE") == "no": - wrapper.set_msgrcpt_status(rcpt, mail_id, 'p') + connector.set_msgrcpt_status(rcpt, mail_id, 'p') msg = _("Request sent") else: amr = AMrelease() result = amr.sendreq(mail_id, secret_id, rcpt) if result: - wrapper.set_msgrcpt_status(rcpt, mail_id, 'R') + connector.set_msgrcpt_status(rcpt, mail_id, 'R') msg = _("Message released") else: raise BadRequest(result) @@ -230,7 +206,7 @@ def release(request, mail_id): """ mail_id = check_mail_id(request, mail_id) msgrcpts = [] - wrapper = get_wrapper() + connector = get_connector() mb = Mailbox.objects.get(user=request.user) \ if request.user.group == 'SimpleUsers' else None for mid in mail_id: @@ -238,10 +214,10 @@ def release(request, mail_id): if mb is not None and r != mb.full_address \ and not r in mb.alias_addresses: continue - msgrcpts += [wrapper.get_recipient_message(r, i)] + msgrcpts += [connector.get_recipient_message(r, i)] if mb is not None and parameters.get_admin("USER_CAN_RELEASE") == "no": for msgrcpt in msgrcpts: - wrapper.set_msgrcpt_status( + connector.set_msgrcpt_status( msgrcpt.rid.email, msgrcpt.mail.mail_id, 'p' ) message = ungettext("%(count)d request sent", @@ -259,7 +235,7 @@ def release(request, mail_id): rcpt.mail.mail_id, rcpt.mail.secret_id, rcpt.rid.email ) if result: - wrapper.set_msgrcpt_status(rcpt.rid.email, rcpt.mail.mail_id, 'R') + connector.set_msgrcpt_status(rcpt.rid.email, rcpt.mail.mail_id, 'R') else: error = result break @@ -293,5 +269,5 @@ def process(request): @login_required @user_passes_test(lambda u: u.group != 'SimpleUsers') def nbrequests(request): - result = get_wrapper().get_pending_requests(request.user) + result = get_connector(user=request.user).get_pending_requests() return render_to_json_response({'requests': result}) diff --git a/modoboa/lib/email_listing.py b/modoboa/lib/email_listing.py index 8f7ff64c9..8d4c6e904 100644 --- a/modoboa/lib/email_listing.py +++ b/modoboa/lib/email_listing.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -import re from django.conf import settings from django.template.loader import render_to_string from django.template import Template, Context @@ -8,15 +7,6 @@ from django.utils.translation import ugettext as _ attached_map = {} -class MBconnector(object): - def __init__(self, address, port): - self.address = address - self.port = port - - def messages_count(self, **kwargs): - pass - - class Page(object): def __init__(self, pageid, id_start, id_stop, items, items_per_page, has_previous, has_next, diff --git a/modoboa/lib/webutils.py b/modoboa/lib/webutils.py index 9b6ecccf1..ac882535c 100644 --- a/modoboa/lib/webutils.py +++ b/modoboa/lib/webutils.py @@ -175,6 +175,16 @@ class NavigationParameters(object): self.parameters = [('pattern', '', True), ('criteria', 'from_addr', False)] + def __getitem__(self, key): + """ + """ + return self.request.session[self.sessionkey][key] + + def __contains__(self, key): + """ + """ + return key in self.request.session[self.sessionkey] + def store(self): """Store navigation parameters into session. """