Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SMTP config validation in UserEmailPlugin #15845

Open
wants to merge 2 commits into
base: 3.14
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
58 changes: 58 additions & 0 deletions saleor/plugins/user_email/plugin.py
Expand Up @@ -2,6 +2,7 @@
from dataclasses import asdict
from typing import TYPE_CHECKING, List, Union

from django.core.exceptions import ValidationError
from promise.promise import Promise

from ...core.notify_events import NotifyEventType, UserNotifyEvent
Expand All @@ -18,6 +19,7 @@
validate_default_email_configuration,
validate_format_of_provided_templates,
)
from ..error_codes import PluginErrorCode
from . import constants
from .constants import TEMPLATE_FIELDS
from .notify_events import (
Expand Down Expand Up @@ -411,6 +413,8 @@ def validate_plugin_configuration(
configuration = plugin_configuration.configuration
configuration = {item["name"]: item["value"] for item in configuration}

cls._validate_smtp_configuration(configuration)

validate_default_email_configuration(plugin_configuration, configuration)
email_templates_data = kwargs.get("email_templates_data", [])
validate_format_of_provided_templates(
Expand Down Expand Up @@ -457,3 +461,57 @@ def save_plugin_configuration(
# Let's add a translated descriptions and labels
cls._append_config_structure(plugin_configuration.configuration)
return plugin_configuration

@staticmethod
def _validate_smtp_configuration(configuration):
errors = {}

if not configuration.get("host"):
errors["host"] = ValidationError(
"Missing SMTP host value.",
code=PluginErrorCode.PLUGIN_MISCONFIGURED.value,
)

if not configuration.get("port"):
errors["port"] = ValidationError(
"Missing SMTP port value.",
code=PluginErrorCode.PLUGIN_MISCONFIGURED.value,
)

if not configuration.get("username"):
errors["username"] = ValidationError(
"Missing SMTP username value.",
code=PluginErrorCode.PLUGIN_MISCONFIGURED.value,
)

if not configuration.get("password"):
errors["password"] = ValidationError(
"Missing SMTP password value.",
code=PluginErrorCode.PLUGIN_MISCONFIGURED.value,
)

if not configuration.get("sender_name"):
errors["sender_name"] = ValidationError(
"Missing sender name value.",
code=PluginErrorCode.PLUGIN_MISCONFIGURED.value,
)

if (
not configuration.get("use_ssl")
and not configuration.get("use_tls")
or configuration.get("use_ssl")
and configuration.get("use_tls")
):
message = (
"You need to enable at least one of the security options (SSL or TLS)."
)
errors["use_ssl"] = ValidationError(
message, code=PluginErrorCode.PLUGIN_MISCONFIGURED.value
)
errors["use_tls"] = ValidationError(
message,
code=PluginErrorCode.PLUGIN_MISCONFIGURED.value,
)

if errors:
raise ValidationError(errors)
6 changes: 3 additions & 3 deletions saleor/plugins/user_email/tests/conftest.py
Expand Up @@ -69,12 +69,12 @@ def user_email_plugin(settings, channel_USD):
def fun(
host="localhost",
port="1025",
username=None,
password=None,
username="username",
password="password",
sender_name="Admin Name",
sender_address="admin@example.com",
use_tls=False,
use_ssl=False,
use_ssl=True,
active=True,
account_confirmation_template=DEFAULT_EMAIL_VALUE,
account_confirmation_subject=ACCOUNT_CONFIRMATION_DEFAULT_SUBJECT,
Expand Down
66 changes: 65 additions & 1 deletion saleor/plugins/user_email/tests/test_plugin.py
Expand Up @@ -9,6 +9,7 @@
from ....core.notify_events import NotifyEventType
from ....graphql.tests.utils import get_graphql_content
from ...email_common import DEFAULT_EMAIL_VALUE, get_email_template
from ...error_codes import PluginErrorCode
from ...manager import get_plugins_manager
from ...models import PluginConfiguration
from ..constants import (
Expand All @@ -32,7 +33,24 @@
send_order_refund,
send_payment_confirmation,
)
from ..plugin import get_user_event_map
from ..plugin import UserEmailPlugin, get_user_event_map


@pytest.fixture
def validation_errors_dict():
return {
"host": "Missing SMTP host value.",
"port": "Missing SMTP port value.",
"username": "Missing SMTP username value.",
"password": "Missing SMTP password value.",
"sender_name": "Missing sender name value.",
"use_ssl": (
"You need to enable at least one of the security options (SSL or TLS)."
),
"use_tls": (
"You need to enable at least one of the security options (SSL or TLS)."
),
}


def test_event_map():
Expand Down Expand Up @@ -313,3 +331,49 @@ def test_plugin_manager_doesnt_load_email_templates_from_db(
# email template from DB but returns default email value.
assert email_config_item
assert email_config_item["value"] == DEFAULT_EMAIL_VALUE


@pytest.mark.parametrize(
"configuration, keys_to_remove",
[
({}, []),
({"host": "test host"}, ["host"]),
({"port": "test port"}, ["port"]),
({"username": "test username"}, ["username"]),
({"password": "test password"}, ["password"]),
({"sender_name": "test sender name"}, ["sender_name"]),
({"use_tls": True, "use_ssl": True}, []),
({"use_tls": True}, ["use_tls", "use_ssl"]),
({"use_ssl": True}, ["use_tls", "use_ssl"]),
],
)
def test_plugin_validate_smtp_configuration(
validation_errors_dict, configuration, keys_to_remove
):
# when
with pytest.raises(ValidationError) as validation_error:
UserEmailPlugin._validate_smtp_configuration(configuration)

# then
for key in keys_to_remove:
validation_errors_dict.pop(key)

assert len(validation_error.value.error_dict) == len(validation_errors_dict)

for field, message in validation_errors_dict.items():
error = validation_error.value.error_dict[field]
assert len(error) == 1
error = error[0]
assert error.code == PluginErrorCode.PLUGIN_MISCONFIGURED.value
assert error.message == message


@patch("saleor.plugins.user_email.plugin.UserEmailPlugin._validate_smtp_configuration")
def test_plugin_validate_smtp_configuration_called(
mock__validate_smtp_configuration, user_email_plugin
):
# when
user_email_plugin()

# then
mock__validate_smtp_configuration.assert_called_once()