improved render of complex HTML mails.

This commit is contained in:
RainLoop Team 2013-11-16 04:04:07 +04:00
parent 8b09b84e7c
commit ea4262e954
6 changed files with 102 additions and 23 deletions

3
.gitignore vendored
View file

@ -4,5 +4,6 @@
/node_modules /node_modules
/build/dist /build/dist
/build/tmp /build/tmp
/data/ /data/*.*
/data/**
!/data/VERSION !/data/VERSION

View file

@ -17,10 +17,12 @@ class HtmlUtils
/** /**
* @param string $sText * @param string $sText
* @param string $sHtmlAttrs = ''
* @param string $sBodyAttrs = ''
* *
* @return \DOMDocument|bool * @return \DOMDocument|bool
*/ */
public static function GetDomFromText($sText) public static function GetDomFromText($sText, $sHtmlAttrs = '', $sBodyAttrs = '')
{ {
static $bOnce = true; static $bOnce = true;
if ($bOnce) if ($bOnce)
@ -37,7 +39,7 @@ class HtmlUtils
@$oDom->loadHTML( @$oDom->loadHTML(
'<'.'?xml version="1.0" encoding="utf-8"?'.'>'. '<'.'?xml version="1.0" encoding="utf-8"?'.'>'.
'<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body>'.$sText.'</body></html>' '<html '.$sHtmlAttrs.'><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body '.$sBodyAttrs.'>'.$sText.'</body></html>'
); );
return $oDom; return $oDom;
@ -45,16 +47,29 @@ class HtmlUtils
/** /**
* @param string $sHtml * @param string $sHtml
* @param bool $bSetupBody = false * @param string $sHtmlAttrs = '
* @param string $sBodyAttrs = ''
* *
* @return string * @return string
*/ */
public static function ClearBodyAndHtmlTag($sHtml, $bSetupBody = false) public static function ClearBodyAndHtmlTag($sHtml, &$sHtmlAttrs = '', &$sBodyAttrs = '')
{ {
$sHtml = \preg_replace('/<body([^>]*)>/im', '<div'.($bSetupBody ? ' class="mailso-body" ' : '').'\\1>', $sHtml); $aMatch = array();
$sHtml = \preg_replace('/<\/body>/im', '</div>', $sHtml); if (preg_match('/<html([^>]+)>/im', $sHtml, $aMatch) && !empty($aMatch[1]))
$sHtml = \preg_replace('/<html([^>]*)>/im', '<div\\1>', $sHtml); {
$sHtml = \preg_replace('/<\/html>/im', '</div>', $sHtml); $sHtmlAttrs = $aMatch[1];
}
$aMatch = array();
if (preg_match('/<body([^>]+)>/im', $sHtml, $aMatch) && !empty($aMatch[1]))
{
$sBodyAttrs = $aMatch[1];
}
$sHtml = \preg_replace('/<body([^>]*)>/im', '', $sHtml);
$sHtml = \preg_replace('/<\/body>/im', '', $sHtml);
$sHtml = \preg_replace('/<html([^>]*)>/im', '', $sHtml);
$sHtml = \preg_replace('/<\/html>/im', '', $sHtml);
return $sHtml; return $sHtml;
} }
@ -265,10 +280,12 @@ class HtmlUtils
$sHtml = \MailSo\Base\HtmlUtils::ClearTags($sHtml); $sHtml = \MailSo\Base\HtmlUtils::ClearTags($sHtml);
$sHtml = \MailSo\Base\HtmlUtils::ClearOn($sHtml); $sHtml = \MailSo\Base\HtmlUtils::ClearOn($sHtml);
$sHtml = \MailSo\Base\HtmlUtils::ClearBodyAndHtmlTag($sHtml);
$sHtmlAttrs = $sBodyAttrs = '';
$sHtml = \MailSo\Base\HtmlUtils::ClearBodyAndHtmlTag($sHtml, $sHtmlAttrs, $sBodyAttrs);
// Dom Part // Dom Part
$oDom = \MailSo\Base\HtmlUtils::GetDomFromText($sHtml); $oDom = \MailSo\Base\HtmlUtils::GetDomFromText($sHtml, $sHtmlAttrs, $sBodyAttrs);
unset($sHtml); unset($sHtml);
if ($oDom) if ($oDom)
@ -278,6 +295,58 @@ class HtmlUtils
{ {
$sTagNameLower = \strtolower($oElement->tagName); $sTagNameLower = \strtolower($oElement->tagName);
// convert body attributes to styles
if ('body' === $sTagNameLower)
{
$aMargins = array(
$oElement->hasAttribute('topmargin')
? \trim($oElement->getAttribute('topmargin')) : '',
$oElement->hasAttribute('leftmargin')
? \trim($oElement->getAttribute('leftmargin')) : '',
$oElement->hasAttribute('bottommargin')
? \trim($oElement->getAttribute('bottommargin')) : '',
$oElement->hasAttribute('rightmargin')
? \trim($oElement->getAttribute('rightmargin')) : '',
);
$sText = $oElement->hasAttribute('text') ? \trim($oElement->getAttribute('text')) : '';
$aStyles = array();
if (!empty($sText))
{
$aStyles[] = 'color: '.$sText;
$oElement->removeAttribute('text');
}
foreach ($aMargins as $iIndex => $sItem)
{
if ('' !== $sItem)
{
switch ($iIndex) {
case 0:
$aStyles[] = 'margin-top: '.((int) $sItem).'px';
$oElement->removeAttribute('topmargin');
break;
case 1:
$aStyles[] = 'margin-left: '.((int) $sItem).'px';
$oElement->removeAttribute('leftmargin');
break;
case 2:
$aStyles[] = 'margin-bottom: '.((int) $sItem).'px';
$oElement->removeAttribute('bottommargin');
break;
case 3:
$aStyles[] = 'margin-right: '.((int) $sItem).'px';
$oElement->removeAttribute('rightmargin');
break;
}
}
}
$sStyles = $oElement->hasAttribute('style') ? $oElement->getAttribute('style') : '';
$oElement->setAttribute('style', (empty($sStyles) ? '' : $sStyles.'; ').\implode('; ', $aStyles));
}
if ('iframe' === $sTagNameLower || 'frame' === $sTagNameLower) if ('iframe' === $sTagNameLower || 'frame' === $sTagNameLower)
{ {
$oElement->setAttribute('src', 'javascript:false'); $oElement->setAttribute('src', 'javascript:false');
@ -378,7 +447,11 @@ class HtmlUtils
unset($oDom); unset($oDom);
$sResult = \MailSo\Base\HtmlUtils::ClearTags($sResult); $sResult = \MailSo\Base\HtmlUtils::ClearTags($sResult);
$sResult = \MailSo\Base\HtmlUtils::ClearBodyAndHtmlTag($sResult, true);
$sHtmlAttrs = $sBodyAttrs = '';
$sResult = \MailSo\Base\HtmlUtils::ClearBodyAndHtmlTag($sResult, $sHtmlAttrs, $sBodyAttrs);
$sResult = '<div data-x-div-type="body" '.$sBodyAttrs.'>'.$sResult.'</div>';
$sResult = '<div data-x-div-type="html" '.$sHtmlAttrs.'>'.$sResult.'</div>';
return \trim($sResult); return \trim($sResult);
} }
@ -478,6 +551,11 @@ class HtmlUtils
} }
} }
if ($oElement->hasAttribute('data-x-div-type'))
{
$oElement->removeAttribute('data-x-div-type');
}
if ($oElement->hasAttribute('data-x-style-url')) if ($oElement->hasAttribute('data-x-style-url'))
{ {
$sAddStyles = $oElement->getAttribute('data-x-style-url'); $sAddStyles = $oElement->getAttribute('data-x-style-url');

View file

@ -7132,7 +7132,7 @@ html.rl-no-preview-pane .messageView.message-selected {
.messageView .b-content .messageItem .bodyText .b-text-part.rtl-text-part { .messageView .b-content .messageItem .bodyText .b-text-part.rtl-text-part {
direction: rtl; direction: rtl;
} }
.messageView .b-content .messageItem .bodyText .b-text-part.html .mailso-body { .messageView .b-content .messageItem .bodyText .b-text-part.html div[data-x-div-type=body] {
margin: 15px; margin: 15px;
} }
.messageView .b-content .messageItem .bodyText .b-text-part.plain { .messageView .b-content .messageItem .bodyText .b-text-part.plain {

File diff suppressed because one or more lines are too long

View file

@ -4831,7 +4831,7 @@ html.rl-no-preview-pane .messageView.message-selected {
.messageView .b-content .messageItem .bodyText .b-text-part.rtl-text-part { .messageView .b-content .messageItem .bodyText .b-text-part.rtl-text-part {
direction: rtl; direction: rtl;
} }
.messageView .b-content .messageItem .bodyText .b-text-part.html .mailso-body { .messageView .b-content .messageItem .bodyText .b-text-part.html div[data-x-div-type=body] {
margin: 15px; margin: 15px;
} }
.messageView .b-content .messageItem .bodyText .b-text-part.plain { .messageView .b-content .messageItem .bodyText .b-text-part.plain {

File diff suppressed because one or more lines are too long