From 7c65127e644bbbea1fde4ff50e10f4345cc0ec67 Mon Sep 17 00:00:00 2001 From: nathangray Date: Wed, 8 Nov 2017 13:09:31 -0700 Subject: [PATCH] Mail - Also include HTML version of email in integration data (for apps that can handle it) --- api/src/Mail.php | 21 +++++++++-- mail/inc/class.mail_integration.inc.php | 50 ++++++++++++++++++++++++- mail/inc/class.mail_ui.inc.php | 33 +++++++++++----- 3 files changed, 89 insertions(+), 15 deletions(-) diff --git a/api/src/Mail.php b/api/src/Mail.php index 040d1682b5..350e408d6c 100644 --- a/api/src/Mail.php +++ b/api/src/Mail.php @@ -6203,7 +6203,7 @@ class Mail * @param uid the uid of the email to be processed * @param partid the partid of the email * @param mailbox the mailbox, that holds the message - * @param preserveHTML flag to pass through to getdisplayableBody + * @param preserveHTML flag to pass through to getdisplayableBody, null for both text and HTML * @param addHeaderSection flag to be able to supress headersection * @param includeAttachments flag to be able to supress possible attachments * @return array/bool with 'mailaddress'=>$mailaddress, @@ -6219,6 +6219,15 @@ class Mail if (empty($headers)) return false; // dont force retrieval of the textpart, let mailClass preferences decide $bodyParts = $mailClass->getMessageBody($uid,($preserveHTML?'always_display':'only_if_no_text'),$partid,null,false,$mailbox); + if(is_null($preserveHTML)) + { + $html = static::getdisplayablebody( + $mailClass, + $mailClass->getMessageBody($uid,'always_display',$partid,null,false,$mailbox), + true + ); + + } // if we do not want HTML but there is no TextRepresentation with the message itself, try converting if ( !$preserveHTML && $bodyParts[0]['mimeType']=='text/html') { @@ -6316,13 +6325,19 @@ class Mail } if (is_array($attachedMessages)) $attachments = array_merge($attachments,$attachedMessages); } - return array( + $return = array( 'mailaddress'=>$mailaddress, 'subject'=>$subject, 'message'=>$message, 'attachments'=>$attachments, 'headers'=>$headers, - ); + ); + if($html) + { + $return['html_message'] = $html; + } + + return $return; } /** diff --git a/mail/inc/class.mail_integration.inc.php b/mail/inc/class.mail_integration.inc.php index 979f46b122..0c82de3251 100644 --- a/mail/inc/class.mail_integration.inc.php +++ b/mail/inc/class.mail_integration.inc.php @@ -36,6 +36,12 @@ class mail_integration { */ const MAX_LINE_CHARS = 40; + /** + * Used to flag inline images so they can be found & urls fixed when in their + * final destination. + */ + const INLINE_PREFIX = 'mail-'; + /** * Gets requested mail information and sets them as data link * -Execute registered hook method from the requested app for integration @@ -100,7 +106,7 @@ class mail_integration { // Execute import mail with provided content ExecMethod($hook['menuaction'],$data); } - + /** * Gets requested mail information and sets them as data link * -with provided content from mail: @@ -287,7 +293,7 @@ class mail_integration { $mo = mail_bo::getInstance(true,$icServerID); $mo->openConnection(); $mo->reopen($mailbox); - $mailcontent = mail_bo::get_mailcontent($mo,$uid,'',$mailbox,false,true,(!($GLOBALS['egw_info']['user']['preferences'][$sessionLocation]['saveAsOptions']==='text_only'))); + $mailcontent = mail_bo::get_mailcontent($mo,$uid,'',$mailbox,null,true,(!($GLOBALS['egw_info']['user']['preferences'][$sessionLocation]['saveAsOptions']==='text_only'))); // this one adds the mail itself (as message/rfc822 (.eml) file) to the app as additional attachment // this is done to have a simple archive functionality (ToDo: opening .eml in email module) if ($GLOBALS['egw_info']['user']['preferences'][$sessionLocation]['saveAsOptions']==='add_raw') @@ -350,6 +356,26 @@ class mail_integration { 'EGroupware\\Api\\Mail::getAttachmentAccount',array($icServerID, $mailbox, $uid, $attachment['partID'], $is_winmail, true),true); } unset($mailcontent['attachments'][$key]['add_raw']); + + // Fix inline images + if($mailcontent['html_message'] && $attachment['cid'] && $data_attachments[$key]['egw_data']) + { + $link_callback = function($cid) use($data_attachments, $key) + { + return self::INLINE_PREFIX.$data_attachments[$key]['egw_data'].'" title="['.$data_attachments[$key]['name'].']'; + }; + foreach(array('src','url','background') as $type) + { + $mailcontent['html_message'] = mail_ui::resolve_inline_image_byType( + $mailcontent['html_message'], + $mailbox, + $attachment['uid'], + $attachment['partID'], + $type, + $link_callback + ); + } + } } } @@ -357,10 +383,30 @@ class mail_integration { 'addresses' => $data_addresses, 'attachments' => $data_attachments, 'message' => $data_message, + 'html_message' => $mailcontent['html_message'], 'date' => $mailcontent['date'], 'subject' => $mailcontent['subject'], 'entry_id' => $app_entry_id ); } + + public static function fix_inline_images($app, $id, array $links, &$html) + { + $replace = array(); + foreach($links as $link) + { + $matches = null; + if (is_array($link) && $link['id']['egw_data'] && strpos($html, self::INLINE_PREFIX . $link['id']['egw_data']) !== false) + { + $replace[self::INLINE_PREFIX. $link['id']['egw_data']] = + Api\Egw::link(Api\Vfs::download_url(Api\Link::vfs_path($app, $id, Api\Vfs::basename($link['id']['name'])))); + } + } + if ($replace) + { + $html = strtr($old = $html, $replace); + } + return isset($old) && $old != $html; + } } diff --git a/mail/inc/class.mail_ui.inc.php b/mail/inc/class.mail_ui.inc.php index cc483c4159..bca7aa042c 100644 --- a/mail/inc/class.mail_ui.inc.php +++ b/mail/inc/class.mail_ui.inc.php @@ -3477,10 +3477,30 @@ $filter['before']= date("d-M-Y", $cutoffdate2); * @param type $_partID part id * @param type $_type = 'src' type of inline image that needs to be resolved and replaced * - types: {plain|src|url|background} + * @param callback $_link_callback Function to generate the link to the image. If + * not provided, a default (using mail) will be used. * @return string returns body content including all CID replacements */ - public static function resolve_inline_image_byType ($_body,$_mailbox, $_uid, $_partID, $_type ='src') + public static function resolve_inline_image_byType ($_body,$_mailbox, $_uid, $_partID, $_type ='src', callable $_link_callback = null) { + /** + * Callback to generate the link + */ + if(is_null($_link_callback)) + { + $_link_callback = function($_cid) use ($_mailbox, $_uid, $_partID) + { + $linkData = array ( + 'menuaction' => 'mail.mail_ui.displayImage', + 'uid' => $_uid, + 'mailbox' => base64_encode($_mailbox), + 'cid' => base64_encode($CID), + 'partID' => $_partID, + ); + return Egw::link('/index.php', $linkData); + }; + } + /** * Callback for preg_replace_callback function * returns matched CID replacement string based on given type @@ -3491,7 +3511,7 @@ $filter['before']= date("d-M-Y", $cutoffdate2); * @param string $_type * @return string|boolean returns the replace */ - $replace_callback = function ($matches) use ($_mailbox,$_uid, $_partID, $_type) + $replace_callback = function ($matches) use ($_mailbox,$_uid, $_partID, $_type, $_link_callback) { if (!$_type) return false; $CID = ''; @@ -3517,14 +3537,7 @@ $filter['before']= date("d-M-Y", $cutoffdate2); if (is_array($matches) && $CID) { - $linkData = array ( - 'menuaction' => 'mail.mail_ui.displayImage', - 'uid' => $_uid, - 'mailbox' => base64_encode($_mailbox), - 'cid' => base64_encode($CID), - 'partID' => $_partID, - ); - $imageURL = Egw::link('/index.php', $linkData); + $imageURL = call_user_func($_link_callback, $CID); // to test without data uris, comment the if close incl. it's body if (Api\Header\UserAgent::type() != 'msie' || Api\Header\UserAgent::version() >= 8) {