From a41896f802b6ce5ad8208074bcc4dce4219c71eb Mon Sep 17 00:00:00 2001 From: leithoff Date: Fri, 5 Aug 2016 15:12:21 +0200 Subject: [PATCH] fix charset/transfer encoding issue when sending plain ascii mails but adding utf-8 signature --- api/src/Mail.php | 9 ++++- mail/inc/class.mail_ui.inc.php | 6 +++ mail/inc/class.mail_zpush.inc.php | 64 +++++++++++++++++-------------- 3 files changed, 49 insertions(+), 30 deletions(-) diff --git a/api/src/Mail.php b/api/src/Mail.php index f87df5a069..868f516fb3 100644 --- a/api/src/Mail.php +++ b/api/src/Mail.php @@ -6959,13 +6959,20 @@ class Mail * * @param Mailer $mailer instance of SMTP Mailer object * @param string|ressource|Horde_Mime_Part $message string or resource containing the RawMessage / object Mail_mimeDecoded message (part)) + * @param boolean $force8bitOnPrimaryPart (default false. force transferEncoding and charset to 8bit/utf8 if we have a textpart as primaryPart) * @throws Exception\WrongParameter when the required Horde_Mail_Part not found */ - function parseRawMessageIntoMailObject(Mailer $mailer, $message) + function parseRawMessageIntoMailObject(Mailer $mailer, $message, $force8bitOnPrimaryPart=false) { if (is_string($message) || is_resource($message)) { $structure = Horde_Mime_Part::parseMessage($message); + //error_log(__METHOD__.__LINE__.'#'.$structure->getPrimaryType().'#'); + if ($force8bitOnPrimaryPart&&$structure->getPrimaryType()=='text') + { + $structure->setTransferEncoding('8bit'); + $structure->setCharset('utf-8'); + } $mailer->setBasePart($structure); //error_log(__METHOD__.__LINE__.':'.array2string($structure)); diff --git a/mail/inc/class.mail_ui.inc.php b/mail/inc/class.mail_ui.inc.php index e09ffa38d9..95a838f0fa 100644 --- a/mail/inc/class.mail_ui.inc.php +++ b/mail/inc/class.mail_ui.inc.php @@ -2977,6 +2977,12 @@ $filter['before']= date("d-M-Y", $cutoffdate2); $singleBodyPart['body'] = preg_replace($sar,$rar,$singleBodyPart['body']); } //error_log(__METHOD__.__LINE__.'reports:'.$singleBodyPart['charSet']); + if ($singleBodyPart['charSet']=='us-ascii') + { + $orgCharSet=$singleBodyPart['charSet']; + $singleBodyPart['charSet'] = Api\Translation::detect_encoding($singleBodyPart['body']); + error_log(__METHOD__.__LINE__.'reports:'.$orgCharSet.' but seems to be:'.$singleBodyPart['charSet']); + } $singleBodyPart['body'] = Api\Translation::convert_jsonsafe($singleBodyPart['body'],$singleBodyPart['charSet']); //error_log(__METHOD__.__LINE__.array2string($singleBodyPart)); if($singleBodyPart['mimeType'] == 'text/plain') diff --git a/mail/inc/class.mail_zpush.inc.php b/mail/inc/class.mail_zpush.inc.php index 14be73e644..0a58feebfd 100644 --- a/mail/inc/class.mail_zpush.inc.php +++ b/mail/inc/class.mail_zpush.inc.php @@ -406,10 +406,38 @@ class mail_zpush implements activesync_plugin_write, activesync_plugin_sendmail, $activeMailProfile = Mail::getStandardIdentityForProfile($activeMailProfiles,self::$profileID); ZLog::Write(LOGLEVEL_DEBUG,__METHOD__."(".__LINE__.")".' ProfileID:'.self::$profileID.' ActiveMailProfile:'.array2string($activeMailProfile)); + // collect identity / signature for later usage, and to determine if we may have to manipulate TransferEncoding and Charset + try + { + $acc = Mail\Account::read($this->mail->icServer->ImapServerId); + //error_log(__METHOD__.__LINE__.array2string($acc)); + $_signature = Mail\Account::read_identity($acc['ident_id'],true); + } + catch (Exception $e) + { + $_signature=array(); + } + $signature = $_signature['ident_signature']; + if ((isset($preferencesArray['disableRulerForSignatureSeparation']) && + $preferencesArray['disableRulerForSignatureSeparation']) || + empty($signature) || trim(Api\Mail\Html::convertHTMLToText($signature)) =='') + { + $disableRuler = true; + } + $beforePlain = $beforeHtml = ""; + $beforeHtml = ($disableRuler ?' 
':' 

'); + $beforePlain = ($disableRuler ?"\r\n\r\n":"\r\n\r\n-- \r\n"); + $sigText = Mail::merge($signature,array($GLOBALS['egw']->accounts->id2name($GLOBALS['egw_info']['user']['account_id'],'person_id'))); + if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' Signature to use:'.$sigText); + $sigTextHtml = $beforeHtml.$sigText; + $sigTextPlain = $beforePlain.Api\Mail\Html::convertHTMLToText($sigText); + $force8bit=false; + if (Api\Translation::detect_encoding($sigTextPlain)!='ascii') $force8bit=true; // initialize the new Api\Mailer object for sending $mailObject = new Api\Mailer(self::$profileID); - $this->mail->parseRawMessageIntoMailObject($mailObject,$smartdata->mime); + + $this->mail->parseRawMessageIntoMailObject($mailObject,$smartdata->mime,$force8bit); // Horde SMTP Class uses utf-8 by default. as we set charset always to utf-8 $mailObject->Sender = $activeMailProfile['ident_email']; $mailObject->setFrom($activeMailProfile['ident_email'],Mail::generateIdentityString($activeMailProfile,false)); @@ -560,32 +588,7 @@ class mail_zpush implements activesync_plugin_write, activesync_plugin_sendmail, $body = str_replace("\r",((preg_match("^text/html^i", $ContentType))?'
':""),$body); // what is this for? if ($this->debugLevel>2) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' retrieved Body (modified):'.$body); */ - // add signature!! ----------------------------------------------------------------- - ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' ActiveMailProfile:'.array2string($activeMailProfile)); - try - { - $acc = Mail\Account::read($this->mail->icServer->ImapServerId); - //error_log(__METHOD__.__LINE__.array2string($acc)); - $_signature = Mail\Account::read_identity($acc['ident_id'],true); - } - catch (Exception $e) - { - $_signature=array(); - } - $signature = $_signature['ident_signature']; - if ((isset($preferencesArray['disableRulerForSignatureSeparation']) && - $preferencesArray['disableRulerForSignatureSeparation']) || - empty($signature) || trim(Api\Mail\Html::convertHTMLToText($signature)) =='') - { - $disableRuler = true; - } - $beforePlain = $beforeHtml = ""; - $beforeHtml = ($disableRuler ?' 
':' 

'); - $beforePlain = ($disableRuler ?"\r\n\r\n":"\r\n\r\n-- \r\n"); - $sigText = Mail::merge($signature,array($GLOBALS['egw']->accounts->id2name($GLOBALS['egw_info']['user']['account_id'],'person_id'))); - if ($this->debugLevel>0) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' Signature to use:'.$sigText); - $sigTextHtml = $beforeHtml.$sigText; - $sigTextPlain = $beforePlain.Api\Mail\Html::convertHTMLToText($sigText); + // actually use prepared signature --------------------collected earlier-------------------------- $isreply = $isforward = false; // reply --------------------------------------------------------------------------- if ($smartdata_task == 'reply' && isset($smartdata->source->itemid) && @@ -717,18 +720,21 @@ class mail_zpush implements activesync_plugin_write, activesync_plugin_sendmail, // add signature, in case its not already added in forward or reply if (!$isreply && !$isforward) { - $Body = $Body.$sigTextPlain; - $AltBody = $AltBody.$sigTextHtml; + //error_log(__METHOD__.__LINE__.'adding Signature'); + $Body = $Body.$sigTextPlain; + $AltBody = $AltBody.$sigTextHtml; } // now set the body if ($AltBody && ($html_body = $mailObject->findBody('html'))) { if ($this->debugLevel>1) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' -> '.$AltBody); + //error_log(__METHOD__.__LINE__.' html:'.$AltBody); $html_body->setContents($AltBody,array('encoding'=>Horde_Mime_Part::DEFAULT_ENCODING)); } if ($Body && ($text_body = $mailObject->findBody('plain'))) { if ($this->debugLevel>1) ZLog::Write(LOGLEVEL_DEBUG,__METHOD__.__LINE__.' -> '.$Body); + //error_log(__METHOD__.__LINE__.' text:'.$Body); $text_body->setContents($Body,array('encoding'=>Horde_Mime_Part::DEFAULT_ENCODING)); } //advanced debugging