From 5fd03242ad2cdbf017ff11e80489c847aed822b7 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Tue, 20 Jan 2015 14:43:26 +0100 Subject: [PATCH 1/5] Make sure to always return a list. fix #675 --- modoboa/extensions/amavis/views.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modoboa/extensions/amavis/views.py b/modoboa/extensions/amavis/views.py index 7a69b6528..ed48ab722 100644 --- a/modoboa/extensions/amavis/views.py +++ b/modoboa/extensions/amavis/views.py @@ -205,8 +205,9 @@ def check_mail_id(request, mail_id): def get_user_valid_addresses(user): """Retrieve all valid addresses of a user.""" + valid_addresses = [] if user.group == 'SimpleUsers': - valid_addresses = user.email + valid_addresses.append(user.email) try: mb = Mailbox.objects.get(user=user) except Mailbox.DoesNotExist: @@ -240,7 +241,7 @@ def delete(request, mail_id): valid_addresses = get_user_valid_addresses(request.user) for mid in mail_id: r, i = mid.split() - if valid_addresses is not None and r not in valid_addresses: + if valid_addresses and r not in valid_addresses: continue connector.set_msgrcpt_status(r, i, 'D') message = ungettext("%(count)d message deleted successfully", @@ -290,7 +291,7 @@ def release(request, mail_id): valid_addresses = get_user_valid_addresses(request.user) for mid in mail_id: r, i = mid.split() - if valid_addresses is not None and r not in valid_addresses: + if valid_addresses and r not in valid_addresses: continue msgrcpts += [connector.get_recipient_message(r, i)] if request.user.group == "SimpleUsers" and \ From 6ec51d271a4ce63a4825a913e2c11d244371df98 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Tue, 20 Jan 2015 14:46:52 +0100 Subject: [PATCH 2/5] End of previous commit. fix #675 --- modoboa/extensions/amavis/views.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/modoboa/extensions/amavis/views.py b/modoboa/extensions/amavis/views.py index ed48ab722..8a05008a9 100644 --- a/modoboa/extensions/amavis/views.py +++ b/modoboa/extensions/amavis/views.py @@ -214,8 +214,6 @@ def get_user_valid_addresses(user): pass else: valid_addresses += mb.alias_addresses - else: - valid_addresses = None return valid_addresses From b251b85e2b0a6b157f5fa806327a8ffe4dcd668c Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Sun, 25 Jan 2015 16:18:57 +0100 Subject: [PATCH 3/5] Use a BinaryField and build the content. see #677 --- modoboa/extensions/amavis/models.py | 2 +- modoboa/extensions/amavis/sql_connector.py | 27 +++++++++------------- modoboa/extensions/amavis/sql_email.py | 5 +--- modoboa/extensions/amavis/views.py | 10 ++------ 4 files changed, 15 insertions(+), 29 deletions(-) diff --git a/modoboa/extensions/amavis/models.py b/modoboa/extensions/amavis/models.py index 7a711fdd8..1688d6fed 100644 --- a/modoboa/extensions/amavis/models.py +++ b/modoboa/extensions/amavis/models.py @@ -162,7 +162,7 @@ class Quarantine(models.Model): partition_tag = models.IntegerField(null=True, blank=True) mail = models.ForeignKey(Msgs, primary_key=True) chunk_ind = models.IntegerField() - mail_text = models.TextField() + mail_text = models.BinaryField() class Meta: db_table = u'quarantine' diff --git a/modoboa/extensions/amavis/sql_connector.py b/modoboa/extensions/amavis/sql_connector.py index 46f0075ae..1be908b03 100644 --- a/modoboa/extensions/amavis/sql_connector.py +++ b/modoboa/extensions/amavis/sql_connector.py @@ -1,6 +1,7 @@ """ SQL connector module. """ + import datetime from django.db.models import Q @@ -209,9 +210,14 @@ class SQLconnector(object): return Msgrcpt.objects.filter(rq).count() def get_mail_content(self, mailid): - """Retrieve the content of a message. - """ - return Quarantine.objects.filter(mail=mailid) + """Retrieve the content of a message.""" + content = "".join([ + str(qmail.mail_text) + for qmail in Quarantine.objects.filter(mail=mailid) + ]) + if isinstance(content, unicode): + content = content.encode("utf-8") + return content class PgSQLconnector(SQLconnector): @@ -229,9 +235,7 @@ class PgSQLconnector(SQLconnector): """ def _apply_msgrcpt_filters(self, flt): - """Return filters based on user's role. - - """ + """Return filters based on user's role. """ self._where = [] if self.user.group == 'SimpleUsers': rcpts = [self.user.email] @@ -248,10 +252,7 @@ class PgSQLconnector(SQLconnector): return flt def _apply_extra_search_filter(self, crit, pattern): - """Apply search filters using additional criterias. - - - """ + """Apply search filters using additional criterias.""" if crit == "to": self._where.append( "convert_from(maddr.email, 'UTF8') LIKE '%%{0}%%'".format( @@ -300,12 +301,6 @@ class PgSQLconnector(SQLconnector): ).count() return Msgrcpt.objects.filter(rq).count() - def get_mail_content(self, mailid): - """Retrieve the content of a message.""" - return Quarantine.objects.filter(mail=mailid).extra( - select={'mail_text': "convert_from(mail_text, 'UTF8')"} - ) - def get_connector(**kwargs): """Return the appropriate *connector* class. diff --git a/modoboa/extensions/amavis/sql_email.py b/modoboa/extensions/amavis/sql_email.py index 2722f09a8..067004d7d 100644 --- a/modoboa/extensions/amavis/sql_email.py +++ b/modoboa/extensions/amavis/sql_email.py @@ -40,10 +40,7 @@ class SQLemail(Email): import email if self._msg is None: - qmails = get_connector().get_mail_content(self.mailid) - mail_text = "".join([qm.mail_text for qm in qmails]) - if type(mail_text) is unicode: - mail_text = mail_text.encode("utf-8") + mail_text = get_connector().get_mail_content(self.mailid) self._msg = email.message_from_string(mail_text) self._parse(self._msg) return self._msg diff --git a/modoboa/extensions/amavis/views.py b/modoboa/extensions/amavis/views.py index 8a05008a9..a15165090 100644 --- a/modoboa/extensions/amavis/views.py +++ b/modoboa/extensions/amavis/views.py @@ -176,11 +176,7 @@ def viewmail(request, mail_id): @login_required def viewheaders(request, mail_id): """Display message headers.""" - content = "" - for qm in get_connector().get_mail_content(mail_id): - content += qm.mail_text - if type(content) is unicode: - content = content.encode("utf-8") + content = get_connector().get_mail_content(mail_id) msg = email.message_from_string(content) headers = [] for name, value in msg.items(): @@ -348,9 +344,7 @@ def mark_messages(request, selection, mtype, recipient_db=None): saclient = SpamassassinClient(request.user, recipient_db) for item in selection: rcpt, mail_id = item.split() - content = "".join( - [msg.mail_text for msg in connector.get_mail_content(mail_id)] - ) + content = connector.get_mail_content(mail_id) result = saclient.learn_spam(rcpt, content) if mtype == "spam" \ else saclient.learn_ham(rcpt, content) if not result: From 6fbdc0e679b76adb3d07f751744f43ce631602d6 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Mon, 26 Jan 2015 21:46:21 +0100 Subject: [PATCH 4/5] Prevent the creation of a duplicated domain. fix #674 --- modoboa/extensions/admin/forms/domain.py | 8 +++++++- modoboa/extensions/admin/lib.py | 6 +----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/modoboa/extensions/admin/forms/domain.py b/modoboa/extensions/admin/forms/domain.py index e9efb0c78..84673d84f 100644 --- a/modoboa/extensions/admin/forms/domain.py +++ b/modoboa/extensions/admin/forms/domain.py @@ -94,8 +94,14 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm): if cleaned_data[k] == "": del cleaned_data[k] continue + if cleaned_data[k] == name: + self._errors[k] = self.error_class( + [_("A %s with this name already exists") % _("domain")] + ) + del cleaned_data[k] + continue label = check_if_domain_exists( - cleaned_data[k], [(Domain, _('domain'))]) + cleaned_data[k], [(Domain, _("domain"))]) if label is not None: self._errors[k] = self.error_class( [_("A %s with this name already exists" % unicode(label))] diff --git a/modoboa/extensions/admin/lib.py b/modoboa/extensions/admin/lib.py index 5b68e1273..f91952fbc 100644 --- a/modoboa/extensions/admin/lib.py +++ b/modoboa/extensions/admin/lib.py @@ -109,10 +109,6 @@ def check_if_domain_exists(name, extra_checks=None): if extra_checks is not None: dtypes = extra_checks + dtypes for dtype, label in dtypes: - try: - dtype.objects.get(name=name) - except dtype.DoesNotExist: - pass - else: + if dtype.objects.filter(name=name).exists(): return label return None From f2bfca665c69b1313a53e6041585224290ae732e Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Thu, 29 Jan 2015 16:14:06 +0100 Subject: [PATCH 5/5] Manually join with the admin_quota table. fix #679 --- modoboa/extensions/admin/views/identity.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/modoboa/extensions/admin/views/identity.py b/modoboa/extensions/admin/views/identity.py index 0c0a29b20..28209ec36 100644 --- a/modoboa/extensions/admin/views/identity.py +++ b/modoboa/extensions/admin/views/identity.py @@ -74,8 +74,16 @@ def list_quotas(request): request.user, request.GET.get("searchquery", None) ) mboxes = mboxes.exclude(quota=0) - if sort_order in ["address", "quota", "quota_value__bytes"]: + if sort_order in ["address", "quota"]: mboxes = mboxes.order_by("%s%s" % (sort_dir, sort_order)) + elif sort_order == "quota_value__bytes": + where = "admin_mailbox.address||'@'||admin_domain.name" + mboxes = mboxes.extra( + select={"quota_value__bytes": "admin_quota.bytes"}, + where=["admin_quota.username=%s" % where], + tables=["admin_quota", "admin_domain"], + order_by=["%s%s" % (sort_dir, sort_order)] + ) elif sort_order == "quota_usage": where = "admin_mailbox.address||'@'||admin_domain.name" db_type = db_type()