diff --git a/generic/models.py b/generic/models.py
index c3a15775..0190fdca 100644
--- a/generic/models.py
+++ b/generic/models.py
@@ -1552,27 +1552,9 @@ class CidUser(models.Model):
if self.login_email_sent and not resend:
return False, "Already sent."
- login_url = reverse("cid_selector")
-
- msg = f"""
- See below for your details for: {self.group}
-
- ---------
- CID: {self.cid}
- Passcode: {self.passcode}
- ---------
-
- You will need these to access to the test system.
-
- Direct link to login:
- {settings.REMOTE_URL}{login_url}?cid={self.cid}&passcode={self.passcode}
-
- The above details are unique to you. Please do not share as otherwise others will be able to access and submit your results.
-
-
-
- Please note this inbox is not monitored. Direct all enquiries to plh-tr.radiology-academy@nhs.net
- """
+ # Build the message payload. Exposed as a separate method so callers
+ # can preview the email without actually sending it.
+ msg = self.generate_email_details_msg()
try:
# send_mail(
@@ -1597,6 +1579,36 @@ class CidUser(models.Model):
self.save()
return True, ""
+ def generate_email_details_msg(self) -> str:
+ """Generate the candidate details email body without sending it.
+
+ Returns:
+ str: The plaintext email body that would be sent.
+ """
+ login_url = reverse("cid_selector")
+
+ msg = f"""
+ See below for your details for: {self.group}
+
+ ---------
+ CID: {self.cid}
+ Passcode: {self.passcode}
+ ---------
+
+ You will need these to access to the test system.
+
+ Direct link to login:
+ {settings.REMOTE_URL}{login_url}?cid={self.cid}&passcode={self.passcode}
+
+ The above details are unique to you. Please do not share as otherwise others will be able to access and submit your results.
+
+
+
+ Please note this inbox is not monitored. Direct all enquiries to plh-tr.radiology-academy@nhs.net
+ """
+
+ return msg
+
def get_email_details_url(self):
return reverse("generic:candidate_email_details", kwargs={"cid": self.cid})
diff --git a/generic/templates/generic/partials/group_users_list.html b/generic/templates/generic/partials/group_users_list.html
index 06a04e6c..765c12bc 100644
--- a/generic/templates/generic/partials/group_users_list.html
+++ b/generic/templates/generic/partials/group_users_list.html
@@ -22,6 +22,7 @@
{% endif %}
{% if user.email %}
+ View
{% else %}
No email
{% endif %}
diff --git a/generic/views.py b/generic/views.py
index d4ce0e5f..118e0949 100644
--- a/generic/views.py
+++ b/generic/views.py
@@ -5043,8 +5043,24 @@ def candidate_email_details(request, cid, resend=False):
except Exception:
resend_flag = False
+ # Allow a preview mode which returns the generated email body without
+ # actually sending the email. Useful for reviewing content in the UI.
+ preview_flag = False
+ try:
+ if request.method == 'POST':
+ preview_flag = str(request.POST.get('preview', '')).lower() in ('1', 'true', 'yes')
+ else:
+ preview_flag = str(request.GET.get('preview', '')).lower() in ('1', 'true', 'yes')
+ except Exception:
+ preview_flag = False
+
+ if preview_flag:
+ # Return plaintext body for preview (opens cleanly in a new tab/window)
+ msg = user.generate_email_details_msg()
+ return HttpResponse(msg, content_type='text/plain')
+
email_sent, comment = user.email_details(resend=resend_flag)
-
+
logger.debug(f"Email details sent to CID {cid}: sent={email_sent}, comment={comment}")
return JsonResponse({"sent": email_sent, "comment": str(comment)})