Skip to content

fix(ticketing): render email templates without a permission check - #369

Merged
harshtandiya merged 2 commits into
developfrom
fix/guest-ticket-email-permission
Aug 20, 2026
Merged

fix(ticketing): render email templates without a permission check#369
harshtandiya merged 2 commits into
developfrom
fix/guest-ticket-email-permission

Conversation

@harshtandiya

Copy link
Copy Markdown
Collaborator

What changed

Ticket, booking-confirmation and sponsor pitch-deck emails all rendered their
Email Template through frappe.email...get_email_template(), which is
whitelisted and reads the template as the session user. Read on Email Template
is granted to Desk User and System Manager only, so every attendee-facing
send raised PermissionError — guests booking publicly, logged-in Website
Users booking for themselves, and Buzz Users raising a sponsorship enquiry.
Both on_submit handlers swallow the exception, so the booking succeeded and
the email silently never went out; str(PermissionError) is empty, which is
why the Error Log entry had no message.

All three call sites now go through buzz.utils.render_email_template(), which
formats the template off the doc directly.

Only shows up on a frappe carrying the check_permission("read") inside
get_email_template() — our local bench (develop @ 80d9c31) predates it,
so this reproduces on CI and production, not necessarily on your machine.

Not touched: the blanket except Exception + log_error(str(e)) in
EventTicket.on_submit that hid this. Worth narrowing separately.

Demo

No UI change. skip-demo.

Testing

  • TestRenderEmailTemplate — a Website User with no read access on Email
    Template still gets a rendered subject and message. Goes red on any frappe
    with the permission check if the whitelisted helper comes back.
  • TestGuestTicketEmail — guest ticket submit renders from the event template.
  • bench run-tests: event_ticket 12, event_booking 40, booking API 33,
    sponsorship_enquiry 4 — all pass.

harshtandiya and others added 2 commits August 20, 2026 14:42
Frappe's get_email_template() is whitelisted and reads the Email Template as
the session user. Public bookings and sponsorship enquiries submit as Guest,
who has no read permission on Email Template, so the render raised
PermissionError. On tickets that error was swallowed by on_submit, leaving the
attendee with a confirmed booking and no email.

Route all three call sites through render_email_template(), which formats the
template directly off the doc.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The guest ticket test leaned on a mock of frappe's whitelisted helper, which
only bit because that import was function-local — the same mock is a no-op for
the module-level imports in Event Booking and Sponsorship Enquiry.

Assert the invariant on render_email_template() instead: a Website User with no
read access on Email Template still gets a rendered subject and message.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR replaces Frappe’s permission-checked email-template helper with an internal renderer so guest and Website User workflows can send configured emails.

  • Adds a shared render_email_template utility that formats an Email Template document directly.
  • Migrates ticket, booking-confirmation, and sponsorship pitch-deck emails to the utility.
  • Adds coverage for rendering without Email Template read permission and sending a guest ticket email.

Confidence Score: 5/5

The PR appears safe to merge, with no concrete blocking or independently actionable non-blocking issue identified.

The changed call sites retain their existing server-controlled template selection and email behavior while avoiding the permission-checked rendering path that prevented guest-facing emails.

Important Files Changed

Filename Overview
buzz/utils.py Adds the permission-independent template renderer used by guest-facing email flows; no concrete defect was identified.
buzz/ticketing/doctype/event_ticket/event_ticket.py Routes ticket-template rendering through the new helper while preserving template selection, message construction, and attachments.
buzz/ticketing/doctype/event_booking/event_booking.py Routes booking-confirmation rendering through the new helper without changing fallback precedence or recipient handling.
buzz/proposals/doctype/sponsorship_enquiry/sponsorship_enquiry.py Routes configured sponsorship pitch-deck templates through the new helper while retaining existing send behavior.
buzz/ticketing/doctype/event_ticket/test_event_ticket.py Adds regression coverage for unprivileged template rendering and guest ticket-email delivery.

Reviews (1): Last reviewed commit: "test(ticketing): pin email rendering to ..." | Re-trigger Greptile

@harshtandiya harshtandiya added the backport main backport to main branch label Aug 20, 2026
@harshtandiya
harshtandiya merged commit b724d91 into develop Aug 20, 2026
11 checks passed
@harshtandiya
harshtandiya deleted the fix/guest-ticket-email-permission branch August 20, 2026 09:32
@github-actions

Copy link
Copy Markdown
Contributor

Backport failed for main, because it was unable to cherry-pick the commit(s).

Please cherry-pick the changes locally and resolve any conflicts.

git fetch origin main
git worktree add -d .worktree/backport-369-to-main origin/main
cd .worktree/backport-369-to-main
git switch --create backport-369-to-main
git cherry-pick -x b724d9158102db2ce9301bf13ff465d2a158fa4e

harshtandiya added a commit that referenced this pull request Aug 20, 2026
…ckport #369) (#370)

fix(ticketing): render email templates without a permission check (#369)

* fix(ticketing): render email templates without a permission check

Frappe's get_email_template() is whitelisted and reads the Email Template as
the session user. Public bookings and sponsorship enquiries submit as Guest,
who has no read permission on Email Template, so the render raised
PermissionError. On tickets that error was swallowed by on_submit, leaving the
attendee with a confirmed booking and no email.

Route all three call sites through render_email_template(), which formats the
template directly off the doc.



* test(ticketing): pin email rendering to run without Desk permissions

The guest ticket test leaned on a mock of frappe's whitelisted helper, which
only bit because that import was function-local — the same mock is a no-op for
the module-level imports in Event Booking and Sponsorship Enquiry.

Assert the invariant on render_email_template() instead: a Website User with no
read access on Email Template still gets a rendered subject and message.



---------


(cherry picked from commit b724d91)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport main backport to main branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant