Skip to content

Commit

Permalink
✨ [#4650] Using variable value as email recipient
Browse files Browse the repository at this point in the history
The variable chosen in the email registration (`to_email_from_variable`) will now actually be used for the mailing. `to_emails` is used as fallback, in case that the variable doesn't return a valid email address.

The variable will also be used for the payment status update mailing. If `payment_emails` is defined, these will be used as recipients. Otherwise it will use `to_email_from_variable`, and as a last resort the `to_emails`
  • Loading branch information
robinmolen committed Dec 24, 2024
1 parent 897cb65 commit 82c9584
Show file tree
Hide file tree
Showing 2 changed files with 222 additions and 2 deletions.
41 changes: 39 additions & 2 deletions src/openforms/registrations/contrib/email/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from typing import Any

from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
from django.urls import reverse
from django.utils import timezone
from django.utils.translation import get_language_info, gettext_lazy as _
Expand Down Expand Up @@ -46,7 +48,26 @@ def register_submission(self, submission: Submission, options: Options) -> None:
config = EmailConfig.get_solo()
config.apply_defaults_to(options)

self.send_registration_email(options["to_emails"], submission, options)
state = submission.load_submission_value_variables_state()
variable_key = options["to_email_from_variable"]

Check failure on line 52 in src/openforms/registrations/contrib/email/plugin.py

View workflow job for this annotation

GitHub Actions / Type checking (Pyright)

Could not access item in TypedDict   "to_email_from_variable" is not a required key in "Options", so access may result in runtime exception (reportTypedDictNotRequiredAccess)
recipients = []

if (
variable_key
and variable_key in state.variables
and state.variables[variable_key].value
):
try:
validate_email(state.variables[variable_key].value)
except ValidationError:
pass
else:
recipients.append(state.variables[variable_key].value)

if not recipients and "to_emails" in options:
recipients = options["to_emails"]

self.send_registration_email(recipients, submission, options)

# ensure that the payment email is also sent if registration is deferred until
# payment is completed
Expand Down Expand Up @@ -186,8 +207,24 @@ def send_registration_email(
)

def update_payment_status(self, submission: "Submission", options: Options):
state = submission.load_submission_value_variables_state()
variable_key = options["to_email_from_variable"]

Check failure on line 211 in src/openforms/registrations/contrib/email/plugin.py

View workflow job for this annotation

GitHub Actions / Type checking (Pyright)

Could not access item in TypedDict   "to_email_from_variable" is not a required key in "Options", so access may result in runtime exception (reportTypedDictNotRequiredAccess)
recipients = options.get("payment_emails")
if not recipients:

if (
not recipients
and variable_key
and variable_key in state.variables
and state.variables[variable_key].value
):
try:
validate_email(state.variables[variable_key].value)
except ValidationError:
pass
else:
recipients = [state.variables[variable_key].value]

if not recipients and "to_emails" in options:
recipients = options["to_emails"]

order_ids = submission.payments.get_completed_public_order_ids()
Expand Down
183 changes: 183 additions & 0 deletions src/openforms/registrations/contrib/email/tests/test_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,124 @@ def test_submission_with_email_backend(self):
self.assertIn(f"{expected_download_url_1} (my-foo.bin)", message_text)
self.assertIn(f"{expected_download_url_2} (my-bar.txt)", message_text)

def test_submission_with_email_backend_using_to_email_from_variable(self):
submission = SubmissionFactory.from_components(
completed=True,
components_list=[
{"key": "foo", "type": "textfield", "label": "foo"},
],
submitted_data={"foo": "bar"},
form__registration_backend="email",
)
SubmissionValueVariableFactory.create(
form_variable__source=FormVariableSources.user_defined,
form_variable__name="User defined var 1",
submission=submission,
key="email_recipient_variable",
value="[email protected]",
)
email_form_options = dict(
to_email_from_variable="email_recipient_variable",
)
email_submission = EmailRegistration("email")

set_submission_reference(submission)

with patch("openforms.registrations.contrib.email.utils.EmailConfig.get_solo"):
email_submission.register_submission(submission, email_form_options)

# Verify that email was sent
self.assertEqual(len(mail.outbox), 1)

message = mail.outbox[0]
self.assertEqual(message.to, ["[email protected]"])

def test_submission_with_email_backend_unknown_to_email_from_variable(self):
submission = SubmissionFactory.from_components(
completed=True,
components_list=[
{"key": "foo", "type": "textfield", "label": "foo"},
],
submitted_data={"foo": "bar"},
form__registration_backend="email",
)
email_form_options = dict(
to_email_from_variable="email_recipient_variable",
)
email_submission = EmailRegistration("email")

set_submission_reference(submission)

with patch("openforms.registrations.contrib.email.utils.EmailConfig.get_solo"):
email_submission.register_submission(submission, email_form_options)

# Verify that email wasn't sent
self.assertEqual(len(mail.outbox), 0)

def test_submission_with_email_backend_invalid_to_email_from_variable(self):
submission = SubmissionFactory.from_components(
completed=True,
components_list=[
{"key": "foo", "type": "textfield", "label": "foo"},
],
submitted_data={"foo": "bar"},
form__registration_backend="email",
)
SubmissionValueVariableFactory.create(
form_variable__source=FormVariableSources.user_defined,
form_variable__name="User defined var 1",
submission=submission,
key="email_recipient_variable",
value="foo.com",
)
email_form_options = dict(
to_email_from_variable="email_recipient_variable",
)
email_submission = EmailRegistration("email")

set_submission_reference(submission)

with patch("openforms.registrations.contrib.email.utils.EmailConfig.get_solo"):
email_submission.register_submission(submission, email_form_options)

# Verify that email wasn't sent
self.assertEqual(len(mail.outbox), 0)

def test_submission_with_email_backend_invalid_to_email_from_variable_with_fallback(
self,
):
submission = SubmissionFactory.from_components(
completed=True,
components_list=[
{"key": "foo", "type": "textfield", "label": "foo"},
],
submitted_data={"foo": "bar"},
form__registration_backend="email",
)
SubmissionValueVariableFactory.create(
form_variable__source=FormVariableSources.user_defined,
form_variable__name="User defined var 1",
submission=submission,
key="email_recipient_variable",
value="foo.com",
)
email_form_options = dict(
to_email_from_variable="email_recipient_variable",
to_emails=["[email protected]"],
)
email_submission = EmailRegistration("email")

set_submission_reference(submission)

with patch("openforms.registrations.contrib.email.utils.EmailConfig.get_solo"):
email_submission.register_submission(submission, email_form_options)

# Verify that email was sent
self.assertEqual(len(mail.outbox), 1)

message = mail.outbox[0]
self.assertEqual(message.to, ["[email protected]"])

def test_submission_with_email_backend_strip_out_urls(self):
config = GlobalConfiguration.get_solo()
config.email_template_netloc_allowlist = []
Expand Down Expand Up @@ -477,6 +595,71 @@ def test_register_and_update_paid_product_with_payment_email_recipient(self):
# check we used the payment_emails
self.assertEqual(message.to, ["[email protected]", "[email protected]"])

def test_register_and_update_paid_product_with_payment_email_recipient_and_variable_email_recipient(
self,
):
submission = SubmissionFactory.from_data(
{"voornaam": "Foo"},
form__product__price=Decimal("11.35"),
form__payment_backend="demo",
registration_success=True,
public_registration_reference="XYZ",
)
SubmissionValueVariableFactory.create(
form_variable__source=FormVariableSources.user_defined,
form_variable__name="User defined var 1",
submission=submission,
key="email_recipient_variable",
value="[email protected]",
)

email_form_options = dict(
to_emails=["[email protected]", "[email protected]"],
to_email_from_variable="email_recipient_variable",
# payment_emails would override to_emails and to_email_from_variable
payment_emails=["[email protected]", "[email protected]"],
)
email_submission = EmailRegistration("email")
email_submission.update_payment_status(submission, email_form_options)

self.assertEqual(len(mail.outbox), 1)

message = mail.outbox[0]
# check we used the payment_emails
self.assertEqual(message.to, ["[email protected]", "[email protected]"])

def test_register_and_update_paid_product_with_variable_email_recipient(
self,
):
submission = SubmissionFactory.from_data(
{"voornaam": "Foo"},
form__product__price=Decimal("11.35"),
form__payment_backend="demo",
registration_success=True,
public_registration_reference="XYZ",
)
SubmissionValueVariableFactory.create(
form_variable__source=FormVariableSources.user_defined,
form_variable__name="User defined var 1",
submission=submission,
key="email_recipient_variable",
value="[email protected]",
)

email_form_options = dict(
to_emails=["[email protected]", "[email protected]"],
# to_email_from_variable would override to_emails
to_email_from_variable="email_recipient_variable",
)
email_submission = EmailRegistration("email")
email_submission.update_payment_status(submission, email_form_options)

self.assertEqual(len(mail.outbox), 1)

message = mail.outbox[0]
# check we used the payment_emails
self.assertEqual(message.to, ["[email protected]"])

@override_settings(DEFAULT_FROM_EMAIL="[email protected]")
def test_submission_with_email_backend_export_csv_xlsx(self):
email_form_options = dict(
Expand Down

0 comments on commit 82c9584

Please sign in to comment.