Fit wide images in user email notifications
This commit is contained in:
@@ -1448,6 +1448,51 @@ class Mail
|
||||
return $separator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make images fit into the email container so that wide images
|
||||
* do not stretch the layout.
|
||||
* - Scale down width/height attributes (Outlook ignores CSS max-width).
|
||||
* - Add "max-width:100%; height:auto" inline styles.
|
||||
*/
|
||||
public static function fitImages($html, $max_width = 0)
|
||||
{
|
||||
if (!$html || stripos($html, '<img') === false) {
|
||||
return $html;
|
||||
}
|
||||
|
||||
return preg_replace_callback('#<img\b[^>]*>#i', function ($m) use ($max_width) {
|
||||
$tag = $m[0];
|
||||
|
||||
// Scale down dimensions preserving aspect ratio.
|
||||
if ($max_width
|
||||
&& preg_match('#\swidth\s*=\s*["\']?(\d+)#i', $tag, $w)
|
||||
&& (int)$w[1] > $max_width
|
||||
) {
|
||||
$width = (int)$w[1];
|
||||
$tag = preg_replace('#(\swidth\s*=\s*["\']?)\d+#i', '${1}'.$max_width, $tag, 1);
|
||||
if (preg_match('#\sheight\s*=\s*["\']?(\d+)#i', $tag, $h)) {
|
||||
$height = (int)round((int)$h[1] * $max_width / $width);
|
||||
$tag = preg_replace('#(\sheight\s*=\s*["\']?)\d+#i', '${1}'.$height, $tag, 1);
|
||||
}
|
||||
}
|
||||
|
||||
$fit_style = 'max-width:100%;height:auto;';
|
||||
|
||||
if (preg_match('#\sstyle\s*=\s*(["\'])(.*?)\1#is', $tag, $s)) {
|
||||
// Remove existing max-width and height declarations.
|
||||
$style = preg_replace('#(^|;)\s*(max-width|height)\s*:[^;]*#i', '$1', $s[2]);
|
||||
$style = trim(preg_replace('#;(\s*;)+#', ';', $style), " \t\r\n;");
|
||||
$style = ($style !== '' ? $style.';' : '').$fit_style;
|
||||
$tag = str_replace($s[0], ' style='.$s[1].$style.$s[1], $tag);
|
||||
} else {
|
||||
$self_closing = preg_match('#/\s*>$#', $tag);
|
||||
$tag = preg_replace('#\s*/?\s*>$#', '', $tag).' style="'.$fit_style.'"'.($self_closing ? ' />' : '>');
|
||||
}
|
||||
|
||||
return $tag;
|
||||
}, $html) ?: $html;
|
||||
}
|
||||
|
||||
// Sanitize status message - remove SMTP username and password.
|
||||
public static function sanitizeSmtpStatusMessage($status_message)
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<meta name="viewport" content="width=350px, user-scalable=yes">
|
||||
<style>
|
||||
#wrapper * { max-width: 650px !important; }
|
||||
#wrapper img { max-width: 100% !important; height: auto !important; }
|
||||
p { margin:0 0 1.5em 0; }
|
||||
pre { font-family: Menlo, Monaco, monospace, sans-serif; padding: 0 0 1.6em 0; color:#333333; line-height:15px; }
|
||||
a { color:#3f8abf; text-decoration:none; }
|
||||
@@ -227,7 +228,7 @@
|
||||
@endif
|
||||
@action('email_notification.before_body', $thread, $user, $conversation)
|
||||
<div style="font-family:Arial, 'Helvetica Neue', Helvetica, Tahoma, sans-serif; color:#444; font-size:14px; line-height:20px; margin:0; @if ($is_rtl) text-align: right; direction: rtl; unicode-bidi: plaintext; @endif">
|
||||
{!! safe_raw_html($thread->getCleanBody() ?? '') !!}
|
||||
{!! safe_raw_html(\MailHelper::fitImages($thread->getCleanBody() ?? '', 580)) !!}
|
||||
</div>
|
||||
|
||||
@if ($thread->has_attachments)
|
||||
|
||||
@@ -18,4 +18,26 @@ class MailTest extends TestCase
|
||||
// self::assertSame('multipart/alternative;
|
||||
// boundary="------------c141PQyZlgOaY0xUqE0ydJUA"', \MailHelper::getHeader($message, 'Content-Type'));
|
||||
}
|
||||
|
||||
public function testFitImages(): void
|
||||
{
|
||||
// Wide image is scaled down preserving aspect ratio.
|
||||
self::assertSame(
|
||||
'<img src="a.png" alt="" width="580" height="326" style="max-width:100%;height:auto;">',
|
||||
\MailHelper::fitImages('<img src="a.png" alt="" width="765" height="430">', 580)
|
||||
);
|
||||
// Narrow image keeps its dimensions.
|
||||
self::assertSame(
|
||||
'<p><img src="a.png" width="300" height="200" style="max-width:100%;height:auto;" /></p>',
|
||||
\MailHelper::fitImages('<p><img src="a.png" width="300" height="200" /></p>', 580)
|
||||
);
|
||||
// Existing max-width and height are replaced, other styles are kept.
|
||||
self::assertSame(
|
||||
'<img src="a.png" style="width:765px; line-height:1; border:0;max-width:100%;height:auto;">',
|
||||
\MailHelper::fitImages('<img src="a.png" style="width:765px; max-width:800px; line-height:1; height:430px; border:0">', 580)
|
||||
);
|
||||
// No images.
|
||||
self::assertSame('<p>text</p>', \MailHelper::fitImages('<p>text</p>', 580));
|
||||
self::assertSame('', \MailHelper::fitImages('', 580));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user