Dave Wize's avatar

Preview emails in browser not on full page

I want to add for my app users a way to preview the email they are sending out.

So I rneder the email on a page in the browser. But I have dificulties sizing it. Because email odesn't understand modern CSS and therefore everything is created with tables and is inline styles.

Is there any easy fix to contain the full email in its container?

Here is my code. (I'm using some extra php to remove the full html structure from it, since it is loaded within another view)

@php
$markdown = new \Illuminate\Mail\Markdown(view(), config('mail.markdown'));
$content = $markdown->render('mail.send-receipt', ['template' => $getRecord()]);
$dom = new \DOMDocument();

// Load the HTML content
@$dom->loadHTML($content);

// Get the BODY element
$body = $dom->getElementsByTagName('body')->item(0);

// Create a new DIV element
$div = $dom->createElement('div');

// Move all children of the BODY to the DIV
while ($body->childNodes->length > 0) {
    $div->appendChild($body->childNodes->item(0));
}

// Replace the BODY with the DIV
$body->parentNode->replaceChild($div, $body);

// Get the HTML content of the DIV element
$content = $dom->saveHTML($div);
@endphp
<div>
    {!! $content !!}
</div>
0 likes
1 reply
LaryAI's avatar
Level 58

To contain the full email within its container and ensure it's sized appropriately, you can use an iframe to encapsulate the email content. This will allow you to treat the email preview as a separate document, which can be styled independently of the parent page.

Here's how you can modify your code to use an iframe:

@php
$markdown = new \Illuminate\Mail\Markdown(view(), config('mail.markdown'));
$content = $markdown->render('mail.send-receipt', ['template' => $getRecord()]);
@endphp

<!-- Create an iframe to contain the email preview -->
<iframe id="emailPreview" style="width: 100%; border: none;" onload="resizeIframe(this)"></iframe>

<script>
// Function to resize the iframe to fit the content
function resizeIframe(iframe) {
    iframe.style.height = iframe.contentWindow.document.body.scrollHeight + 'px';
}

// Write the email content to the iframe
document.addEventListener("DOMContentLoaded", function() {
    var iframe = document.getElementById('emailPreview');
    var doc = iframe.contentDocument || iframe.contentWindow.document;
    doc.open();
    doc.write(`{!! $content !!}`);
    doc.close();
});
</script>

In this solution, we create an iframe with an id of emailPreview. We set the width to 100% to make it responsive and remove the border for aesthetics. The onload attribute calls the resizeIframe function, which adjusts the height of the iframe to fit the content.

The resizeIframe function takes the iframe as an argument and sets its height based on the scroll height of the body within the iframe. This ensures that the iframe will be tall enough to display the entire email without needing a scrollbar.

The script at the bottom waits for the DOM to be fully loaded before writing the email content into the iframe. It accesses the iframe's document and writes the email content into it, which is then displayed as a preview.

This approach isolates the email content from the rest of the page, allowing you to use whatever styles you need for the email without affecting the parent document. It also ensures that the email preview is contained within the bounds of the iframe, making it easier to manage the sizing and presentation of the email content.

1 like

Please or to participate in this conversation.