Fix blank HTML previews by loading each email from its own view, not srcdoc

The iframe's srcdoc="{{ preview.html }}" relied on Django's autoescaping
to correctly re-encode a document full of its own double-quoted
style="..." attributes, and on browser handling of an escaped, inherited-
CSP srcdoc document that didn't render reliably in practice -- the
panel showed blank. EmailPreviewRenderView now serves each preview's
HTML as an ordinary same-origin response at its own URL, and the
iframe just points `src` at it -- xframe_options_sameorigin overrides
the site-wide X-Frame-Options: DENY (SecurityMiddleware's default,
unset in settings.py) since this response only needs to be framed by
the page linking to it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ECGMEwrc2k4D8VQuwjstj9
This commit is contained in:
2026-08-20 23:06:26 +02:00
parent 413fea59f2
commit b423f0cf12
4 changed files with 92 additions and 10 deletions

View File

@@ -20,7 +20,7 @@
</div>
<div class="bg-subhead p-4" data-view-panel="html">
<iframe class="h-[560px] w-full rounded-lg border border-line bg-white" srcdoc="{{ preview.html }}" title="{{ preview.label }}"></iframe>
<iframe class="h-[560px] w-full rounded-lg border border-line bg-white" src="{% url 'management:email_preview_render' preview.key %}" loading="lazy" title="{{ preview.label }}"></iframe>
</div>
<pre class="hidden overflow-x-auto p-4.5 font-mono text-sm whitespace-pre-wrap text-ink" data-view-panel="text">{{ preview.text }}</pre>
</div>