import base64
import pytest
from smtplib import SMTPException, SMTPResponseException
from celery.exceptions import Retry
from core_notifications import tasks
from core_notifications.settings import Settings
def test_send_email_task_with_clicks_tracking(mocker, faker, app):
mocked_mail = mocker.patch("core_notifications.tasks.mail.send")
mocked_message = mocker.patch("core_notifications.tasks.Message")
mocked_replace_urls = mocker.patch("core_notifications.tasks.replace_urls")
test_subject = faker.pystr()
test_to = faker.email()
test_body = faker.text()
test_body_html = f"
{test_body}
"
mocked_replace_urls.return_value = test_body_html
test_cc = faker.email()
test_analytics = dict()
test_analytic_url = faker.pystr()
with app.test_request_context():
tasks.send_email_task(
test_subject,
test_to,
test_body_html,
test_analytic_url,
test_analytics,
test_cc,
track_clicks=True,
)
assert mocked_message.call_args_list == [
mocker.call(
subject=test_subject,
recipients=[test_to],
body=test_body,
html=test_body_html,
sender=app.config.get("MAIL_DEFAULT_SENDER"),
extra_headers={"X-SES-CONFIGURATION-SET": "cmn-delphi-atlas"},
cc=[test_cc],
)
]
assert mocked_mail.call_args_list == [
mocker.call(mocked_message.return_value)
]
assert mocked_replace_urls.call_args_list == [
mocker.call(
body=test_body_html,
email_id=None,
to=test_to,
analytic_url=test_analytic_url,
)
]
def test_send_email_task_no_clicks_tracking(mocker, faker, app):
mocked_mail = mocker.patch("core_notifications.tasks.mail.send")
mocked_message = mocker.patch("core_notifications.tasks.Message")
mocked_replace_urls = mocker.patch("core_notifications.tasks.replace_urls")
test_subject = faker.pystr()
test_to = faker.email()
test_body = faker.text()
test_body_html = f"{test_body}
"
mocked_replace_urls.return_value = test_body_html
test_cc = faker.email()
test_analytics = dict()
test_analytic_url = faker.pystr()
with app.test_request_context():
tasks.send_email_task(
test_subject,
test_to,
test_body_html,
test_analytic_url,
test_analytics,
test_cc,
)
assert mocked_message.call_args_list == [
mocker.call(
subject=test_subject,
recipients=[test_to],
body=test_body,
html=test_body_html,
sender=app.config.get("MAIL_DEFAULT_SENDER"),
extra_headers={"X-SES-CONFIGURATION-SET": "cmn-delphi-atlas"},
cc=[test_cc],
)
]
assert mocked_mail.call_args_list == [
mocker.call(mocked_message.return_value)
]
assert not mocked_replace_urls.called
def test_send_email_task_long_lines(mocker, faker, app):
mocked_mail = mocker.patch("core_notifications.tasks.mail.send")
mocked_message = mocker.patch("core_notifications.tasks.Message")
test_subject = faker.pystr()
test_to = faker.email()
test_body = "0" * (app.config.get("MAX_LINE_LENGTH", 1) + 1)
test_body_html = test_body
expected_body = ("0" * app.config.get("MAX_LINE_LENGTH", 1)) + "\n0"
expected_body_html = expected_body
test_cc = faker.email()
test_analytic_url = faker.pystr()
test_analytics = dict()
with app.test_request_context():
tasks.send_email_task(
test_subject,
test_to,
test_body_html,
test_analytic_url,
test_analytics,
test_cc,
)
assert mocked_message.call_args_list == [
mocker.call(
subject=test_subject,
recipients=[test_to],
body=expected_body,
html=expected_body_html,
sender=app.config.get("MAIL_DEFAULT_SENDER"),
extra_headers={"X-SES-CONFIGURATION-SET": "cmn-delphi-atlas"},
cc=[test_cc],
)
]
assert mocked_mail.call_args_list == [
mocker.call(mocked_message.return_value)
]
def test_send_email_no_cc(mocker, faker, app):
mocked_mail = mocker.patch("core_notifications.tasks.mail.send")
mocked_message = mocker.patch("core_notifications.tasks.Message")
test_subject = faker.pystr()
test_to = faker.email()
test_body = faker.text()
test_body_html = f"{test_body}
"
test_analytic_url = faker.pystr()
test_analytics = dict()
with app.test_request_context():
tasks.send_email_task(
test_subject,
test_to,
test_body_html,
test_analytic_url,
test_analytics,
)
assert mocked_message.call_args_list == [
mocker.call(
subject=test_subject,
recipients=[test_to],
body=test_body,
html=test_body_html,
sender=app.config.get("MAIL_DEFAULT_SENDER"),
extra_headers={"X-SES-CONFIGURATION-SET": "cmn-delphi-atlas"},
cc=None,
)
]
assert mocked_mail.call_args_list == [
mocker.call(mocked_message.return_value)
]
def test_send_email_with_attachments(mocker, faker, app):
mocked_mail = mocker.patch("core_notifications.tasks.mail.send")
mocked_message = mocker.patch("core_notifications.tasks.Message")
mocked_message.return_value.attach.return_value = "foo"
test_subject = faker.pystr()
test_to = faker.email()
test_body = faker.text()
test_body_html = f"{test_body}
"
test_cc = faker.email()
test_analytic_url = faker.pystr()
test_analytics = dict()
att_filename = "some_name.csv"
att_filetype = "text/csv"
att_base64_data = base64.b64encode("some_data".encode()).decode()
attachments = [
{
"filename": att_filename,
"filetype": att_filetype,
"base64_data": att_base64_data,
}
]
with app.test_request_context():
tasks.send_email_task(
test_subject,
test_to,
test_body_html,
test_analytic_url,
test_analytics,
test_cc,
attachments,
)
assert mocked_message.call_args_list == [
mocker.call(
subject=test_subject,
recipients=[test_to],
body=test_body,
html=test_body_html,
sender=app.config.get("MAIL_DEFAULT_SENDER"),
extra_headers={"X-SES-CONFIGURATION-SET": "cmn-delphi-atlas"},
cc=[test_cc],
)
]
assert mocked_message.return_value.attach.call_args_list == [
mocker.call(
att_filename,
att_filetype,
base64.b64decode(att_base64_data),
)
]
assert mocked_mail.call_args_list == [
mocker.call(mocked_message.return_value)
]
def test_send_email_task_smtp_exception(mocker, faker, app):
mocker.patch(
"core_notifications.tasks.send_email_task.retry", side_effect=Retry
)
mocked_mail = mocker.patch("core_notifications.tasks.mail.send")
mocked_mail.side_effect = error = SMTPException()
mocker.patch("core_notifications.tasks.Message")
test_subject = faker.pystr()
test_to = faker.email()
test_body = faker.text()
test_body_html = f"{test_body}
"
test_cc = faker.email()
test_analytic_url = faker.pystr()
test_analytics = dict()
with pytest.raises(Retry):
tasks.send_email_task(
test_subject,
test_to,
test_body_html,
test_analytic_url,
test_analytics,
test_cc,
)
tasks.send_email_task.retry.assert_called_with(exc=error)
def test_send_email_task_reaching_sending_limits(mocker, faker, app):
mocker.patch(
"core_notifications.tasks.send_email_task.retry", side_effect=Retry
)
mocked_mail = mocker.patch("core_notifications.tasks.mail.send")
error = SMTPResponseException(code=454, msg="Test")
mocked_mail.side_effect = error
mocker.patch("core_notifications.tasks.Message")
test_subject = faker.pystr()
test_to = faker.email()
test_body = faker.text()
test_body_html = f"{test_body}
"
test_analytic_url = faker.pystr()
test_analytics = dict()
test_cc = faker.email()
with pytest.raises(Retry):
tasks.send_email_task(
test_subject,
test_to,
test_body_html,
test_analytic_url,
test_analytics,
test_cc,
)
tasks.send_email_task.retry.assert_called_with(
exc=error, countdown=Settings.TASK_REACHING_LIMITS_RETRY_DELAY
)