stages/email: allow overriding of destination email in plan context
closes #2445 Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
0c0b9ca84a
commit
9ad4c736f1
|
@ -23,6 +23,7 @@ from authentik.stages.email.utils import TemplateEmailMessage
|
|||
|
||||
LOGGER = get_logger()
|
||||
PLAN_CONTEXT_EMAIL_SENT = "email_sent"
|
||||
PLAN_CONTEXT_EMAIL_OVERRIDE = "email"
|
||||
|
||||
|
||||
class EmailChallenge(Challenge):
|
||||
|
@ -83,13 +84,16 @@ class EmailStageView(ChallengeStageView):
|
|||
"""Helper function that sends the actual email. Implies that you've
|
||||
already checked that there is a pending user."""
|
||||
pending_user = self.executor.plan.context[PLAN_CONTEXT_PENDING_USER]
|
||||
email = self.executor.plan.context.get(PLAN_CONTEXT_EMAIL_OVERRIDE, None)
|
||||
if not email:
|
||||
email = pending_user.email
|
||||
current_stage: EmailStage = self.executor.current_stage
|
||||
token = self.get_token()
|
||||
# Send mail to user
|
||||
message = TemplateEmailMessage(
|
||||
subject=_(current_stage.subject),
|
||||
template_name=current_stage.template,
|
||||
to=[pending_user.email],
|
||||
to=[email],
|
||||
template_context={
|
||||
"url": self.get_full_url(**{QS_KEY_TOKEN: token.key}),
|
||||
"user": pending_user,
|
||||
|
|
|
@ -14,7 +14,7 @@ from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan
|
|||
from authentik.flows.tests import FlowTestCase
|
||||
from authentik.flows.views.executor import SESSION_KEY_PLAN
|
||||
from authentik.stages.email.models import EmailStage
|
||||
from authentik.stages.email.stage import QS_KEY_TOKEN
|
||||
from authentik.stages.email.stage import PLAN_CONTEXT_EMAIL_OVERRIDE, QS_KEY_TOKEN
|
||||
|
||||
|
||||
class TestEmailStage(FlowTestCase):
|
||||
|
@ -75,6 +75,27 @@ class TestEmailStage(FlowTestCase):
|
|||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(len(mail.outbox), 1)
|
||||
self.assertEqual(mail.outbox[0].subject, "authentik")
|
||||
self.assertEqual(mail.outbox[0].to, ["test@beryju.org"])
|
||||
|
||||
def test_pending_user_override(self):
|
||||
"""Test with pending user (override to)"""
|
||||
plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()])
|
||||
plan.context[PLAN_CONTEXT_PENDING_USER] = self.user
|
||||
plan.context[PLAN_CONTEXT_EMAIL_OVERRIDE] = "foo@bar.baz"
|
||||
session = self.client.session
|
||||
session[SESSION_KEY_PLAN] = plan
|
||||
session.save()
|
||||
|
||||
url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug})
|
||||
with patch(
|
||||
"authentik.stages.email.models.EmailStage.backend_class",
|
||||
PropertyMock(return_value=EmailBackend),
|
||||
):
|
||||
response = self.client.post(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(len(mail.outbox), 1)
|
||||
self.assertEqual(mail.outbox[0].subject, "authentik")
|
||||
self.assertEqual(mail.outbox[0].to, ["foo@bar.baz"])
|
||||
|
||||
def test_use_global_settings(self):
|
||||
"""Test use_global_settings"""
|
||||
|
|
|
@ -6,6 +6,21 @@ This stage can be used for email verification. authentik's background worker wil
|
|||
|
||||
![](email_recovery.png)
|
||||
|
||||
## Behaviour
|
||||
|
||||
By default, the email is sent to the currently pending user. To override this, you can set `email` in the plan's context to another email address, which will override the user's email address (the user won't be changed).
|
||||
|
||||
For example, create this expression policy and bind it to the email stage:
|
||||
|
||||
```python
|
||||
request.context["email"] = "foo@bar.baz"
|
||||
# Or get it from a prompt
|
||||
# request.context["email"] = request.context["prompt_data"]["email"]
|
||||
# Or another user attribute
|
||||
# request.context["email"] = request.context["pending_user"].attributes.get("otherEmail")
|
||||
return True
|
||||
```
|
||||
|
||||
## Custom Templates
|
||||
|
||||
You can also use custom email templates, to use your own design or layout.
|
||||
|
|
Reference in New Issue