FIX Add option MAIN_MAIL_USE_MULTI_PART to include text content into

HTML email and add option MAIN_MAIL_ADD_INLINE_IMAGES_IF_IN_MEDIAS to
restore the inline images feature.
This commit is contained in:
Laurent Destailleur 2017-04-05 01:01:43 +02:00
parent 4f292d1247
commit 7c868888a5
2 changed files with 92 additions and 41 deletions

View File

@ -55,7 +55,6 @@ class CMailFile
var $eol; var $eol;
var $eol2; var $eol2;
var $atleastonefile=0;
var $error=''; var $error='';
var $smtps; // Contains SMTPs object (if this method is used) var $smtps; // Contains SMTPs object (if this method is used)
@ -74,7 +73,7 @@ class CMailFile
// Image // Image
var $html; var $html;
var $image_boundary; var $image_boundary;
var $atleastoneimage=0; var $atleastoneimage=0; // at least one image file with file=xxx.ext into content (TODO Debug this. How can this case be tested. Remove if not used).
var $html_images=array(); var $html_images=array();
var $images_encoded=array(); var $images_encoded=array();
var $image_types = array('gif' => 'image/gif', var $image_types = array('gif' => 'image/gif',
@ -108,7 +107,7 @@ class CMailFile
*/ */
function __construct($subject,$to,$from,$msg,$filename_list=array(),$mimetype_list=array(),$mimefilename_list=array(),$addr_cc="",$addr_bcc="",$deliveryreceipt=0,$msgishtml=0,$errors_to='',$css='',$trackid='',$moreinheader='') function __construct($subject,$to,$from,$msg,$filename_list=array(),$mimetype_list=array(),$mimefilename_list=array(),$addr_cc="",$addr_bcc="",$deliveryreceipt=0,$msgishtml=0,$errors_to='',$css='',$trackid='',$moreinheader='')
{ {
global $conf; global $conf, $dolibarr_main_data_root;
// We define end of line (RFC 821). // We define end of line (RFC 821).
$this->eol="\r\n"; $this->eol="\r\n";
@ -160,8 +159,12 @@ class CMailFile
if ($this->msgishtml) if ($this->msgishtml)
{ {
$this->html = $msg; $this->html = $msg;
$findimg = $this->findHtmlImages($conf->fckeditor->dir_output);
if (! empty($conf->global->MAIN_MAIL_ADD_INLINE_IMAGES_IF_IN_MEDIAS))
{
$findimg = $this->findHtmlImages($dolibarr_main_data_root.'/medias');
}
// Define if there is at least one file // Define if there is at least one file
if ($findimg) if ($findimg)
{ {
@ -231,17 +234,6 @@ class CMailFile
// Define body in text_body // Define body in text_body
$text_body = $this->write_body($msg); $text_body = $this->write_body($msg);
// Encode images
$images_encoded = '';
if ($this->atleastoneimage)
{
$images_encoded.= $this->write_images($this->images_encoded);
// always end related and end alternative after inline images
$images_encoded.= "--" . $this->related_boundary . "--" . $this->eol;
$images_encoded.= $this->eol . "--" . $this->alternative_boundary . "--" . $this->eol;
$images_encoded.= $this->eol;
}
// Add attachments to text_encoded // Add attachments to text_encoded
if ($this->atleastonefile) if ($this->atleastonefile)
{ {
@ -255,8 +247,8 @@ class CMailFile
// comme des injections mail par les serveurs de messagerie. // comme des injections mail par les serveurs de messagerie.
$this->headers = preg_replace("/([\r\n]+)$/i","",$this->headers); $this->headers = preg_replace("/([\r\n]+)$/i","",$this->headers);
$this->message = 'This is a message with multiple parts in MIME format.'.$this->eol; $this->message = $this->eol.'This is a message with multiple parts in MIME format.'.$this->eol;
$this->message.= $text_body . $images_encoded . $files_encoded; $this->message.= $text_body . $files_encoded;
$this->message.= "--" . $this->mixed_boundary . "--" . $this->eol; $this->message.= "--" . $this->mixed_boundary . "--" . $this->eol;
} }
else if ($conf->global->MAIN_MAIL_SENDMODE == 'smtps') else if ($conf->global->MAIN_MAIL_SENDMODE == 'smtps')
@ -917,7 +909,7 @@ class CMailFile
$out.= "Content-Type: multipart/mixed; boundary=\"".$this->mixed_boundary."\"".$this->eol2; $out.= "Content-Type: multipart/mixed; boundary=\"".$this->mixed_boundary."\"".$this->eol2;
$out.= "Content-Transfer-Encoding: 8bit".$this->eol2; $out.= "Content-Transfer-Encoding: 8bit".$this->eol2;
dol_syslog("CMailFile::write_smtpheaders smtp_header=\n".$out); dol_syslog("CMailFile::write_smtpheaders smtp_header=\n".$out);
return $out; return $out;
} }
@ -973,23 +965,23 @@ class CMailFile
$out.= "--" . $this->alternative_boundary . $this->eol; $out.= "--" . $this->alternative_boundary . $this->eol;
} }
if ($this->msgishtml)
{
// Check if html header already in message
$strContent = $this->checkIfHTML($msgtext);
}
else
{
$strContent = $msgtext;
}
// Make RFC821 Compliant, replace bare linefeeds // Make RFC821 Compliant, replace bare linefeeds
$strContent = preg_replace("/(?<!\r)\n/si", "\r\n", $strContent); $strContent = preg_replace("/(?<!\r)\n/si", "\r\n", $msgtext);
if (! empty($conf->global->MAIN_FIX_FOR_BUGGED_MTA)) if (! empty($conf->global->MAIN_FIX_FOR_BUGGED_MTA))
{ {
$strContent = preg_replace("/\r\n/si", "\n", $strContent); $strContent = preg_replace("/\r\n/si", "\n", $strContent);
} }
$strContentAltText = '';
if ($this->msgishtml)
{
$strContentAltText = html_entity_decode(strip_tags($strContent));
$strContentAltText = rtrim(wordwrap($strContentAltText, 75, "\r\n"));
// Check if html header already in message, if not complete the message
$strContent = $this->checkIfHTML($strContent);
}
// Make RFC2045 Compliant, split lines // Make RFC2045 Compliant, split lines
//$strContent = rtrim(chunk_split($strContent)); // Function chunck_split seems ko if not used on a base64 content //$strContent = rtrim(chunk_split($strContent)); // Function chunck_split seems ko if not used on a base64 content
$strContent = rtrim(wordwrap($strContent)); // TODO Using this method creates unexpected line break on text/plain content. $strContent = rtrim(wordwrap($strContent)); // TODO Using this method creates unexpected line break on text/plain content.
@ -999,14 +991,30 @@ class CMailFile
if ($this->atleastoneimage) if ($this->atleastoneimage)
{ {
$out.= "Content-Type: text/plain; charset=".$conf->file->character_set_client.$this->eol; $out.= "Content-Type: text/plain; charset=".$conf->file->character_set_client.$this->eol;
$out.= $this->eol.strip_tags($strContent).$this->eol; // Add plain text message $out.= $this->eol.($strContentAltText?$strContentAltText:strip_tags($strContent)).$this->eol; // Add plain text message
$out.= "--" . $this->alternative_boundary . $this->eol; $out.= "--" . $this->alternative_boundary . $this->eol;
$out.= "Content-Type: multipart/related; boundary=\"".$this->related_boundary."\"".$this->eol; $out.= "Content-Type: multipart/related; boundary=\"".$this->related_boundary."\"".$this->eol;
$out.= $this->eol; $out.= $this->eol;
$out.= "--" . $this->related_boundary . $this->eol; $out.= "--" . $this->related_boundary . $this->eol;
} }
if (! $this->atleastoneimage && $strContentAltText && ! empty($conf->global->MAIN_MAIL_USE_MULTI_PART)) // Add plain text message part before html part
{
$out.= "Content-Type: multipart/alternative; boundary=\"".$this->alternative_boundary."\"".$this->eol;
$out.= $this->eol;
$out.= "--" . $this->alternative_boundary . $this->eol;
$out.= "Content-Type: text/plain; charset=".$conf->file->character_set_client.$this->eol;
$out.= $this->eol.$strContentAltText.$this->eol;
$out.= "--" . $this->alternative_boundary . $this->eol;
}
$out.= "Content-Type: text/html; charset=".$conf->file->character_set_client.$this->eol; $out.= "Content-Type: text/html; charset=".$conf->file->character_set_client.$this->eol;
$out.= $this->eol.$strContent.$this->eol; $out.= $this->eol.$strContent.$this->eol;
if (! $this->atleastoneimage && $strContentAltText && ! empty($conf->global->MAIN_MAIL_USE_MULTI_PART)) // Add plain text message part after html part
{
$out.= "--" . $this->alternative_boundary . "--". $this->eol;
}
} }
else else
{ {
@ -1016,6 +1024,16 @@ class CMailFile
$out.= $this->eol; $out.= $this->eol;
// Encode images
if ($this->atleastoneimage)
{
$out .= $this->write_images($this->images_encoded);
// always end related and end alternative after inline images
$out .= "--" . $this->related_boundary . "--" . $this->eol;
$out .= $this->eol . "--" . $this->alternative_boundary . "--" . $this->eol;
$out .= $this->eol;
}
return $out; return $out;
} }
@ -1184,14 +1202,15 @@ class CMailFile
$extensions = array_keys($this->image_types); $extensions = array_keys($this->image_types);
preg_match_all('/(?:"|\')([^"\']+\.('.implode('|', $extensions).'))(?:"|\')/Ui', $this->html, $matches); preg_match_all('/(?:"|\')([^"\']+\.('.implode('|', $extensions).'))(?:"|\')/Ui', $this->html, $matches); // If "xxx.ext" or 'xxx.ext' found
if ($matches) if ($matches)
{ {
$i=0; $i=0;
foreach ($matches[1] as $full) foreach ($matches[1] as $full)
{ {
if (preg_match('/file=([A-Za-z0-9_\-\/]+[\.]?[A-Za-z0-9]+)?$/i',$full,$regs))
if (preg_match('/file=([A-Za-z0-9_\-\/]+[\.]?[A-Za-z0-9]+)?$/i',$full,$regs)) // If xxx is 'file=aaa'
{ {
$img = $regs[1]; $img = $regs[1];

View File

@ -1283,15 +1283,23 @@ class SMTPs
// Make RFC821 Compliant, replace bare linefeeds // Make RFC821 Compliant, replace bare linefeeds
$strContent = preg_replace("/(?<!\r)\n/si", "\r\n", $strContent); $strContent = preg_replace("/(?<!\r)\n/si", "\r\n", $strContent);
$strContentAltText = '';
if ($strType == 'html')
{
$strContentAltText = html_entity_decode(strip_tags($strContent));
$strContentAltText = rtrim(wordwrap($strContentAltText, 75, "\r\n"));
}
// Make RFC2045 Compliant // Make RFC2045 Compliant
//$strContent = rtrim(chunk_split($strContent)); // Function chunck_split seems ko if not used on a base64 content //$strContent = rtrim(chunk_split($strContent)); // Function chunck_split seems ko if not used on a base64 content
$strContent = rtrim(wordwrap($strContent, 75, "\r\n")); // TODO Using this method creates unexpected line break on text/plain content. $strContent = rtrim(wordwrap($strContent, 75, "\r\n")); // TODO Using this method creates unexpected line break on text/plain content.
$this->_msgContent[$strType] = array(); $this->_msgContent[$strType] = array();
$this->_msgContent[$strType]['mimeType'] = $strMimeType; $this->_msgContent[$strType]['mimeType'] = $strMimeType;
$this->_msgContent[$strType]['data'] = $strContent; $this->_msgContent[$strType]['data'] = $strContent;
$this->_msgContent[$strType]['dataText'] = $strContentAltText;
if ( $this->getMD5flag() ) if ( $this->getMD5flag() )
$this->_msgContent[$strType]['md5'] = dol_hash($strContent, 3); $this->_msgContent[$strType]['md5'] = dol_hash($strContent, 3);
//} //}
@ -1304,6 +1312,8 @@ class SMTPs
*/ */
function getBodyContent() function getBodyContent()
{ {
global $conf;
// Generate a new Boundary string // Generate a new Boundary string
$this->_setBoundary(); $this->_setBoundary();
@ -1318,7 +1328,7 @@ class SMTPs
die ("Sorry, no content"); die ("Sorry, no content");
// If we have ONE, we can use the simple format // If we have ONE, we can use the simple format
else if( $keyCount === 1 ) else if( $keyCount === 1 && empty($conf->global->MAIN_MAIL_USE_MULTI_PART))
{ {
$_msgData = $this->_msgContent; $_msgData = $this->_msgContent;
$_msgData = $_msgData[$_types[0]]; $_msgData = $_msgData[$_types[0]];
@ -1336,7 +1346,7 @@ class SMTPs
} }
// If we have more than ONE, we use the multi-part format // If we have more than ONE, we use the multi-part format
else if( $keyCount > 1 ) else if( $keyCount >= 1 || ! empty($conf->global->MAIN_MAIL_USE_MULTI_PART))
{ {
// Since this is an actual multi-part message // Since this is an actual multi-part message
// We need to define a content message Boundary // We need to define a content message Boundary
@ -1351,14 +1361,18 @@ class SMTPs
$content .= "\r\n"; $content .= "\r\n";
$content .= "--" . $this->_getBoundary('mixed') . "\r\n"; $content .= "--" . $this->_getBoundary('mixed') . "\r\n";
if (key_exists('image', $this->_msgContent)) if (key_exists('image', $this->_msgContent)) // If inline image found
{ {
$content.= 'Content-Type: multipart/alternative; boundary="'.$this->_getBoundary('alternative').'"' . "\r\n"; $content.= 'Content-Type: multipart/alternative; boundary="'.$this->_getBoundary('alternative').'"' . "\r\n";
$content .= "\r\n"; $content .= "\r\n";
$content .= "--" . $this->_getBoundary('alternative') . "\r\n"; $content .= "--" . $this->_getBoundary('alternative') . "\r\n";
} }
// $this->_msgContent must be sorted with key 'text' or 'html' first then 'image' then 'attachment'
// Loop through message content array // Loop through message content array
foreach ($this->_msgContent as $type => $_content ) foreach ($this->_msgContent as $type => $_content )
{ {
@ -1409,13 +1423,24 @@ class SMTPs
if (key_exists('image', $this->_msgContent)) if (key_exists('image', $this->_msgContent))
{ {
$content.= "Content-Type: text/plain; charset=" . $this->getCharSet() . "\r\n"; $content.= "Content-Type: text/plain; charset=" . $this->getCharSet() . "\r\n";
$content.= "\r\n" . strip_tags($_content['data']) . "\r\n"; // Add plain text message $content.= "\r\n" . ($_content['dataText']?$_content['dataText']:strip_tags($_content['data'])) . "\r\n"; // Add plain text message
$content.= "--" . $this->_getBoundary('alternative') . "\r\n"; $content.= "--" . $this->_getBoundary('alternative') . "\r\n";
$content.= 'Content-Type: multipart/related; boundary="' . $this->_getBoundary('related') . '"' . "\r\n"; $content.= 'Content-Type: multipart/related; boundary="' . $this->_getBoundary('related') . '"' . "\r\n";
$content.= "\r\n"; $content.= "\r\n";
$content.= "--" . $this->_getBoundary('related') . "\r\n"; $content.= "--" . $this->_getBoundary('related') . "\r\n";
} }
if (! key_exists('image', $this->_msgContent) && $_content['dataText'] && ! empty($conf->global->MAIN_MAIL_USE_MULTI_PART)) // Add plain text message part before html part
{
$content.= 'Content-Type: multipart/alternative; boundary="'.$this->_getBoundary('alternative').'"' . "\r\n";
$content .= "\r\n";
$content .= "--" . $this->_getBoundary('alternative') . "\r\n";
$content.= "Content-Type: text/plain; charset=" . $this->getCharSet() . "\r\n";
$content.= "\r\n". $_content['dataText'] . "\r\n";
$content.= "--" . $this->_getBoundary('alternative') . "\r\n";
}
$content .= 'Content-Type: ' . $_content['mimeType'] . '; ' $content .= 'Content-Type: ' . $_content['mimeType'] . '; '
// . 'charset="' . $this->getCharSet() . '"'; // . 'charset="' . $this->getCharSet() . '"';
. 'charset=' . $this->getCharSet() . ''; . 'charset=' . $this->getCharSet() . '';
@ -1431,7 +1456,14 @@ class SMTPs
if ( $this->getMD5flag() ) if ( $this->getMD5flag() )
$content .= 'Content-MD5: ' . $_content['md5'] . "\r\n"; $content .= 'Content-MD5: ' . $_content['md5'] . "\r\n";
$content .= "\r\n" . $_content['data'] . "\r\n\r\n"; $content .= "\r\n" . $_content['data'] . "\r\n";
if (! key_exists('image', $this->_msgContent) && $_content['dataText'] && ! empty($conf->global->MAIN_MAIL_USE_MULTI_PART)) // Add plain text message part after html part
{
$content.= "--" . $this->_getBoundary('alternative') . "--". "\r\n";
}
$content .= "\r\n";
} }
} }