From 9cad0547469671c357986019844d969fc44dbac2 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Mon, 26 Feb 2024 19:41:07 +0100 Subject: [PATCH] fix: catch SMTPException when sending secret edit link --- .../integration/test_anonymous_owned_map.py | 34 +++++++++++++++++-- umap/views.py | 22 +++++++----- 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/umap/tests/integration/test_anonymous_owned_map.py b/umap/tests/integration/test_anonymous_owned_map.py index 24cc46a7..0f2ee25c 100644 --- a/umap/tests/integration/test_anonymous_owned_map.py +++ b/umap/tests/integration/test_anonymous_owned_map.py @@ -1,10 +1,12 @@ import re +from smtplib import SMTPException +from unittest.mock import patch import pytest from django.core.signing import get_cookie_signer from playwright.sync_api import expect -from umap.models import DataLayer +from umap.models import DataLayer, Map from ..base import DataLayerFactory @@ -152,7 +154,9 @@ def test_can_change_perms_after_create(tilelayer, live_server, page): expect(option).to_have_text("Inherit") -def test_alert_message_after_create(tilelayer, live_server, page): +def test_alert_message_after_create( + tilelayer, live_server, page, monkeypatch, settings +): page.goto(f"{live_server.url}/en/map/new") save = page.get_by_role("button", name="Save") expect(save).to_be_visible() @@ -160,6 +164,7 @@ def test_alert_message_after_create(tilelayer, live_server, page): expect(alert).to_be_hidden() with page.expect_response(re.compile(r".*/map/create/")): save.click() + new_map = Map.objects.last() expect(alert).to_be_visible() expect( alert.get_by_text( @@ -169,3 +174,28 @@ def test_alert_message_after_create(tilelayer, live_server, page): ).to_be_visible() expect(alert.get_by_role("button", name="Copy")).to_be_visible() expect(alert.get_by_role("button", name="Send me the link")).to_be_visible() + alert.get_by_placeholder("Email").fill("foo@bar.com") + with patch("umap.views.send_mail") as patched: + with page.expect_response(re.compile("/en/map/.*/send-edit-link/")): + alert.get_by_role("button", name="Send me the link").click() + assert patched.called + patched.assert_called_with( + "The uMap edit link for your map: Untitled map", + f"Here is your secret edit link: {new_map.get_anonymous_edit_url()}", + "test@test.org", + ["foo@bar.com"], + fail_silently=False, + ) + + +def test_email_sending_error_are_catched(tilelayer, page, live_server): + page.goto(f"{live_server.url}/en/map/new") + alert = page.locator(".umap-alert") + with page.expect_response(re.compile(r".*/map/create/")): + page.get_by_role("button", name="Save").click() + alert.get_by_placeholder("Email").fill("foo@bar.com") + with patch("umap.views.send_mail", side_effect=SMTPException) as patched: + with page.expect_response(re.compile("/en/map/.*/send-edit-link/")): + alert.get_by_role("button", name="Send me the link").click() + assert patched.called + expect(alert.get_by_text("Can't send email to foo@bar.com")).to_be_visible() diff --git a/umap/views.py b/umap/views.py index 5c90fe97..7b8c0c9f 100644 --- a/umap/views.py +++ b/umap/views.py @@ -9,6 +9,7 @@ from datetime import datetime, timedelta from http.client import InvalidURL from io import BytesIO from pathlib import Path +from smtplib import SMTPException from urllib.error import HTTPError, URLError from urllib.parse import quote, quote_plus, urlparse from urllib.request import Request, build_opener @@ -836,16 +837,19 @@ class SendEditLink(FormLessEditMixin, FormView): return HttpResponseBadRequest("Invalid") link = self.object.get_anonymous_edit_url() - send_mail( - _( - "The uMap edit link for your map: %(map_name)s" - % {"map_name": self.object.name} - ), - _("Here is your secret edit link: %(link)s" % {"link": link}), - settings.DEFAULT_FROM_EMAIL, - [email], - fail_silently=False, + subject = _( + "The uMap edit link for your map: %(map_name)s" + % {"map_name": self.object.name} ) + body = _("Here is your secret edit link: %(link)s" % {"link": link}) + try: + send_mail( + subject, body, settings.DEFAULT_FROM_EMAIL, [email], fail_silently=False + ) + except SMTPException: + return simple_json_response( + error=_("Can't send email to %(email)s" % {"email": email}) + ) return simple_json_response( info=_("Email sent to %(email)s" % {"email": email}) )