From 87e8f5213e8590da559bacdb2d7169cbe2a91f0e Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Tue, 17 Jan 2017 16:52:09 +0100 Subject: [PATCH 1/2] Allow local addresses for forward definition. fix #998 --- modoboa/admin/forms/forward.py | 30 +++++++++--------------------- modoboa/admin/views/user.py | 2 +- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/modoboa/admin/forms/forward.py b/modoboa/admin/forms/forward.py index 00334f14a..5cd7b1b7c 100644 --- a/modoboa/admin/forms/forward.py +++ b/modoboa/admin/forms/forward.py @@ -1,15 +1,13 @@ """Forms related to forwards management.""" from django import forms -from django.utils.translation import ugettext as _, ugettext_lazy - -from modoboa.lib.email_utils import split_mailbox -from modoboa.lib.exceptions import BadRequest, PermDeniedException - -from ..models import Domain +from django.core import validators +from django.utils.translation import ugettext_lazy class ForwardForm(forms.Form): + """Forward definition form.""" + dest = forms.CharField( label=ugettext_lazy("Recipient(s)"), widget=forms.Textarea(attrs={"class": "form-control"}), @@ -24,23 +22,13 @@ class ForwardForm(forms.Form): "Forward messages and store copies into your local mailbox") ) - def get_recipients(self): + def clean_dest(self): + """Check recipients validity.""" + rawdata = self.cleaned_data.get("dest", "").strip() recipients = [] - rawdata = self.cleaned_data["dest"].strip() if not rawdata: return recipients for rcpt in rawdata.split(","): - local_part, domname = split_mailbox(rcpt) - if not local_part or not domname: - raise BadRequest("Invalid mailbox syntax for %s" % rcpt) - try: - Domain.objects.get(name=domname) - except Domain.DoesNotExist: - recipients += [rcpt] - else: - raise PermDeniedException( - _("You can't define a forward to a local destination. " - "Please ask your administrator to create an alias " - "instead.") - ) + validators.validate_email(rcpt) + recipients += [rcpt] return recipients diff --git a/modoboa/admin/views/user.py b/modoboa/admin/views/user.py index 9afa398a5..18808e74c 100644 --- a/modoboa/admin/views/user.py +++ b/modoboa/admin/views/user.py @@ -27,7 +27,7 @@ def forward(request, tplname="admin/forward.html"): al = Alias.objects.create( address=mb.full_address, domain=mb.domain, enabled=mb.user.is_active) - recipients = form.get_recipients() + recipients = form.cleaned_data["dest"] if form.cleaned_data["keepcopies"]: recipients.append(mb.full_address) al.set_recipients(recipients) From a4685334117f0f1bf8380b55f9e3d11831c8751e Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Tue, 17 Jan 2017 17:28:21 +0100 Subject: [PATCH 2/2] Increase coverage. see #998 --- modoboa/admin/models/alias.py | 3 ++- modoboa/admin/tests/test_user.py | 23 +++++++++++++++-------- modoboa/admin/views/user.py | 5 ++++- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/modoboa/admin/models/alias.py b/modoboa/admin/models/alias.py index 77229c845..db6c8ca9c 100644 --- a/modoboa/admin/models/alias.py +++ b/modoboa/admin/models/alias.py @@ -100,8 +100,9 @@ class Alias(AdminObject): grant_access_to_object(admin, self) def set_recipients(self, address_list): - """Set recipients for this alias. Special recipients: + """Set recipients for this alias. + Special recipients: * local mailbox + extension: r_mailbox will be set to local mailbox * alias address == recipient address: valid only to keep local copies (when a forward is defined) and to create exceptions when a catchall diff --git a/modoboa/admin/tests/test_user.py b/modoboa/admin/tests/test_user.py index 4734ae3e6..25eebb8c5 100644 --- a/modoboa/admin/tests/test_user.py +++ b/modoboa/admin/tests/test_user.py @@ -20,19 +20,26 @@ class ForwardTestCase(ModoTestCase): def test_set_forward(self): self.client.logout() - self.client.login(username='user@test.com', password='toto') - url = reverse('user_forward') + self.client.login(username="user@test.com", password="toto") + url = reverse("user_forward") self.ajax_post( url, - {'dest': 'user@extdomain.com', 'keepcopies': True} + {"dest": "user@extdomain.com", "keepcopies": True} ) response = self.client.get(url) self.assertEqual(response.status_code, 200) content = json.loads(response.content) - self.assertIn('user@extdomain.com', content["content"]) - self.assertNotIn('user@test.com', content["content"]) - forward = Alias.objects.get(address='user@test.com', internal=False) - sadmin = User.objects.get(username='admin') + self.assertIn("user@extdomain.com", content["content"]) + self.assertNotIn("user@test.com", content["content"]) + forward = Alias.objects.get(address="user@test.com", internal=False) + sadmin = User.objects.get(username="admin") self.assertTrue(sadmin.can_access(forward)) - domadmin = User.objects.get(username='admin@test.com') + domadmin = User.objects.get(username="admin@test.com") self.assertTrue(domadmin.can_access(forward)) + + # Now, empty forward + self.ajax_post(url, {"dest": "", "keepcopies": False}) + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + content = json.loads(response.content) + self.assertNotIn("user@extdomain.com", content["content"]) diff --git a/modoboa/admin/views/user.py b/modoboa/admin/views/user.py index 18808e74c..c9d548f09 100644 --- a/modoboa/admin/views/user.py +++ b/modoboa/admin/views/user.py @@ -31,7 +31,10 @@ def forward(request, tplname="admin/forward.html"): if form.cleaned_data["keepcopies"]: recipients.append(mb.full_address) al.set_recipients(recipients) - al.post_create(request.user) + if len(recipients) == 0: + al.delete() + else: + al.post_create(request.user) return render_to_json_response(_("Forward updated")) return render_to_json_response(