/** * get formatted gmt date and time * * @return String */ private function getFormattedGmtDateTime() { // calculate timezone in "GMT-HH:MM" format $dtz = new DateTimeZone(Tinebase_Core::get(Tinebase_Core::USERTIMEZONE)); $time = new DateTime('now', $dtz); $offset = $dtz->getOffset($time); $sign = $offset < 0 ? "-" : "+"; $offset = abs($offset); $hours = floor($offset / 3600); $hours = $hours < 10 ? '0' . $hours : $hours; $minutes = offset % 60; $minutes = $minutes < 10 ? '0' . $minutes : $minutes; $gmt = '(GMT' . $sign . $hours . ":" . $minutes . ')'; $dateTime = date('Y-m-d H:i:s'); $formattedDateTime = Tinebase_Translation::dateToStringInTzAndLocaleFormat(Expressomail_Message::convertDate($dateTime)); return $formattedDateTime . ' ' . $gmt; }
/** * parse headers and set 'date', 'from', 'to', 'cc', 'bcc', 'subject', 'sender' fields * * @param array $_headers * @return void */ public function parseHeaders(array $_headers) { // remove duplicate headers (which can't be set twice in real life) foreach (array('date', 'from', 'to', 'cc', 'bcc', 'subject', 'sender') as $field) { if (isset($_headers[$field]) && is_array($_headers[$field])) { $_headers[$field] = $_headers[$field][0]; } } $this->importance = isset($_headers['importance']) && strtolower($_headers['importance']) === 'high' ? true : false; $this->subject = isset($_headers['subject']) ? Expressomail_Message::convertText($_headers['subject']) : null; $this->reading_conf = array_key_exists('disposition-notification-to', $_headers) && $_headers['disposition-notification-to'] ? true : false; if (array_key_exists('date', $_headers)) { $this->sent = Expressomail_Message::convertDate($_headers['date']); } elseif (array_key_exists('resent-date', $_headers)) { $this->sent = Expressomail_Message::convertDate($_headers['resent-date']); } $punycodeConverter = Expressomail_Controller_Message::getInstance()->getPunycodeConverter(); foreach (array('to', 'cc', 'bcc', 'from', 'sender') as $field) { if (isset($_headers[$field])) { $value = Expressomail_Message::convertAddresses($_headers[$field], $punycodeConverter); switch ($field) { case 'from': $this->from_email = isset($value[0]) && array_key_exists('email', $value[0]) ? $value[0]['email'] : ''; $this->from_name = isset($value[0]) && array_key_exists('name', $value[0]) && !empty($value[0]['name']) ? $value[0]['name'] : $this->from_email; break; case 'sender': $this->sender = isset($value[0]) && array_key_exists('email', $value[0]) ? '<' . $value[0]['email'] . '>' : ''; if (isset($value[0]) && array_key_exists('name', $value[0]) && !empty($value[0]['name'])) { $this->sender = '"' . $value[0]['name'] . '" ' . $this->sender; } break; default: $this->{$field} = $value; } } } }
/** * convert signature to text to remove all html tags and spaces/linebreaks, if the remains are empty -> set empty signature * * @param Expressomail_Model_Account $account */ protected function _checkSignature($account) { if (empty($account->signature)) { return; } $plainTextSignature = Expressomail_Message::convertFromHTMLToText($account->signature, "\n"); if (!preg_match('/[^\\s^\\n]/', $plainTextSignature, $matches) && !preg_match('/<img id="?user-signature-image-?[0-9]*"? alt="?([^\\"]+)"? src="data:image\\/jpeg;base64,([^"]+)">/i', $account->signature, $imgmatches)) { $account->signature = ''; } }
/** * set mail body * * @param Expressomail_mail $_mail * @param Expressomail_Model_Message $_message */ protected function _setMailBody(Expressomail_mail $_mail, Expressomail_Model_Message $_message) { if ($_message->content_type == Expressomail_Model_Message::CONTENT_TYPE_HTML) { // checking embedded images $embeddedImages = $this->processEmbeddedImagesInHtmlBody($_message->body); // now checking embedded signature base64 image $base64Images = $this->processEmbeddedImageSignatureInHtmlBody($_message->body); //now checking embed images for reply/forward $embeddedImagesReply = $this->processEmbeddedImagesInHtmlBodyForReply($_message->body); $cid = array(); if (count($embeddedImagesReply) > 0) { foreach ($embeddedImagesReply as $index => $embeddedImage) { $cid[$index] = $_mail->createCid($embeddedImage['messageId']); $_message->body = str_replace($embeddedImage['match'], 'src="cid:' . $cid[$index] . '"', $_message->body); } } if (count($embeddedImages) > 0) { $_message->body = str_ireplace('src="index.php?method=Expressomail.showTempImage&tempImageId=', 'src="cid:', $_message->body); } if (count($base64Images) > 0) { // there should be only one image in the signature $signature_cid = $_mail->createCid($base64Images[0][1]); $_message->body = preg_replace('/<img id="?user-signature-image-?[0-9]*"? alt="?[^\\"]+"? src="data:image\\/jpeg;base64,[^"]+">/', '<img id="user-signature-image" src="cid:' . $signature_cid . '"/>', $_message->body); } $_mail->setBodyHtml(Expressomail_Message::addHtmlMarkup($_message->body)); if (count($embeddedImages) > 0) { foreach ($embeddedImages as $embeddedImage) { $file = Tinebase_Core::getTempDir() . '/' . $embeddedImage[1]; $image = file_get_contents($file); $_mail->createHtmlRelatedAttachment($image, $embeddedImage[1], 'image/jpg', Zend_Mime::DISPOSITION_INLINE, Zend_Mime::ENCODING_BASE64, $embeddedImage[0]); } } if (count($base64Images) > 0) { // again, there should be only one image in the signature $image = base64_decode($base64Images[0][1]); $_mail->createHtmlRelatedAttachment($image, $signature_cid, 'image/jpg', Zend_Mime::DISPOSITION_INLINE, Zend_Mime::ENCODING_BASE64, $base64Images[0][0]); } if (count($embeddedImagesReply) > 0) { foreach ($embeddedImagesReply as $index => $embeddedImage) { try { $part = Expressomail_Controller_Message::getInstance()->getMessagePart($embeddedImage['messageId'], $embeddedImage['messagePart']); $image = base64_decode(stream_get_contents($part->getRawStream())); $_mail->createHtmlRelatedAttachment($image, $cid[$index], $part->type, Zend_Mime::DISPOSITION_INLINE, Zend_Mime::ENCODING_BASE64, $part->filename); } catch (Exception $exc) { } } } if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . $_mail->getBodyHtml(TRUE)); } } $plainBodyText = $_message->getPlainTextBody(); $_mail->setBodyText($plainBodyText); if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . $_mail->getBodyText(TRUE)); } }
/** * convert to plaintext * * @param string $_string */ protected function _getPlaintext($_string) { return Expressomail_Message::convertContentType(Zend_Mime::TYPE_HTML, Zend_Mime::TYPE_TEXT, $_string); }
/** * create Tinebase_Mail from Zend_Mail_Message * * @param Zend_Mail_Message $_zmm * @param string $_replyBody * @return Tinebase_Mail */ public static function createFromZMM(Zend_Mail_Message $_zmm, $_replyBody = null) { $contentStream = fopen("php://temp", 'r+'); if (preg_match('/application\\/(x\\-){0,1}pkcs7-mime/i', $_zmm->getHeader('content-type')) > 0) { $mp = new Zend_Mime_Part($_zmm->getContent()); } else { fputs($contentStream, $_zmm->getContent()); rewind($contentStream); $mp = new Zend_Mime_Part($contentStream); } if ($_zmm->headerExists('content-transfer-encoding')) { $mp->encoding = $_zmm->getHeader('content-transfer-encoding'); $mp->decodeContent(); } else { $mp->encoding = Zend_Mime::ENCODING_7BIT; } // append old body when no multipart/mixed if ($_replyBody !== null && $_zmm->headerExists('content-transfer-encoding')) { $mp = self::_appendReplyBody($mp, $_replyBody); $mp->encoding = $_zmm->getHeader('content-transfer-encoding'); } if ($_zmm->headerExists('content-type')) { $contentTypeHeader = Zend_Mime_Decode::splitHeaderField($_zmm->getHeader('content-type')); if ($mp->type = strtolower($contentTypeHeader[0]) === 'application/pkcs7-mime') { $mp->type = $_zmm->getHeader('content-type'); } else { $mp->type = $contentTypeHeader[0]; } if (isset($contentTypeHeader['boundary'])) { $mp->boundary = $contentTypeHeader['boundary']; } if (isset($contentTypeHeader['charset'])) { $mp->charset = $contentTypeHeader['charset']; } } else { $mp->type = Zend_Mime::TYPE_TEXT; } $result = new Expressomail_Mail('utf-8'); $result->setBodyText($mp); foreach ($_zmm->getHeaders() as $header => $values) { foreach ((array) $values as $value) { switch ($header) { case 'content-transfer-encoding': // these are implicitly set by Zend_Mail_Transport_Abstract::_getHeaders() // these are implicitly set by Zend_Mail_Transport_Abstract::_getHeaders() case 'content-type': case 'mime-version': // do nothing break; case 'bcc': $addresses = Expressomail_Message::parseAdresslist($value); foreach ($addresses as $address) { $result->addBcc($address['address'], $address['name']); } break; case 'cc': $addresses = Expressomail_Message::parseAdresslist($value); foreach ($addresses as $address) { $result->addCc($address['address'], $address['name']); } break; case 'date': try { $result->setDate($value); } catch (Zend_Mail_Exception $zme) { if (Tinebase_Core::isLogLevel(Zend_Log::NOTICE)) { Tinebase_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . " Could not set date: " . $value); } if (Tinebase_Core::isLogLevel(Zend_Log::NOTICE)) { Tinebase_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . " " . $zme); } $result->setDate(); } break; case 'from': $addresses = Expressomail_Message::parseAdresslist($value); foreach ($addresses as $address) { $result->setFrom($address['address'], $address['name']); } break; case 'message-id': $result->setMessageId($value); break; case 'return-path': $result->setReturnPath($value); break; case 'subject': $result->setSubject($value); break; case 'to': $addresses = Expressomail_Message::parseAdresslist($value); foreach ($addresses as $address) { $result->addTo($address['address'], $address['name']); } break; default: $result->addHeader($header, $value); break; } } } return $result; }
/** * create new message for the cache * * @param array $_message * @param Expressomail_Model_Folder $_folder * @return Expressomail_Model_Message */ protected function _createModelMessage(array $_message, Expressomail_Model_Folder $_folder = NULL) { // Optimization!!! if ($_folder == NULL) { if (isset($_message['folder_id'])) { $_folder = array_key_exists($_message['folder_id'], $this->_folderMap) ? $this->_folderMap[$_message['folder_id']] : ($this->_folderMap[$_message['folder_id']] = Expressomail_Controller_Folder::getInstance()->get($_message['folder_id'])); } else { return NULL; } } $message = new Expressomail_Model_Message(array('id' => self::createMessageId($_folder->account_id, $_folder->getId(), $_message['uid']), 'account_id' => $_folder->account_id, 'messageuid' => $_message['uid'], 'folder_id' => $_folder->getId(), 'timestamp' => Tinebase_DateTime::now(), 'received' => Expressomail_Message::convertDate($_message['received']), 'size' => $_message['size'], 'flags' => $_message['flags']), true); $message->parseStructure($_message['structure']); $message->parseHeaders($_message['header']); $message->fixToListModel(); $message->parseBodyParts(); $message->parseSmime($_message['structure']); $attachments = Expressomail_Controller_Message::getInstance()->getAttachments($message); $message->has_attachment = count($attachments) > 0 ? true : false; if ($message->content_type === Expressomail_Model_Message::CONTENT_TYPE_MULTIPART_REPORT) { $bodyParts = $message->getBodyParts($message->structure); foreach ($bodyParts as $partId => $partStructure) { if ($partStructure['contentType'] === Expressomail_Model_Message::CONTENT_TYPE_MESSAGE_RFC822) { $translate = Tinebase_Translation::getTranslation('Expressomail'); $partHeaders = Expressomail_Controller_Message::getInstance()->getMessageHeaders($message, $partId, true); $message->subject = $partHeaders['subject'] . ' - ' . $translate->_($message->subject); $message->from_name = $translate->_($message->from_name); } } } return $message; }
/** * Compare order of Expressomail_Model_Message acording to Tinebase_Model_Pagination * @param Expressomail_Model_Message $msg1 * @param Expressomail_Model_Message $msg2 * @return int * * @todo Convert int security value in Expressomail_Smime to corresponding string type */ public function compare($msg1, $msg2) { switch ($this->_pagination->sort) { case 'received': // Integer $value1 = $msg1[$this->_pagination->sort]; $value2 = $msg2[$this->_pagination->sort]; case 'sent': // Integer $value1 = isset($value1) ? $value1 : $msg1['header']['date']; $value2 = isset($value2) ? $value2 : $msg2['header']['date']; $value1 = intval(Expressomail_Message::convertDate($value1)->format("U")); $value2 = intval(Expressomail_Message::convertDate($value2)->format("U")); case 'size': // Integer $value1 = isset($value1) ? $value1 : intval($msg1[$this->_pagination->sort]); $value2 = isset($value2) ? $value2 : intval($msg2[$this->_pagination->sort]); return $this->compareIntegers($value1, $value2); case 'folder_id': // Strings $folders = array(); $translate = Tinebase_Translation::getTranslation('Expressomail'); foreach (array($msg1, $msg2) as $msg) { $folder = Expressomail_Backend_Folder::decodeFolderUid($msg[$this->_pagination->sort]); // Optimization! Only create the account object once for every sort operation. $account = array_key_exists($folder['accountId'], $this->_accountMap) ? $this->_accountMap[$folder['accountId']] : ($this->_accountMap[$folder['accountId']] = Expressomail_Controller_Account::getInstance()->get($folder['accountId'])); $aux1 = explode('/', $folder['globalName']); $aux2 = ''; foreach ($aux1 as $value) { $aux2 .= $translate->_($value) . '/'; } $folders[] = $account->name . '/' . substr($aux2, 0, strlen($aux2) - 1); } list($value1, $value2) = $folders; //TODO: Should use a static method implemented on Model_Message or Expressomail_Smime //TODO: Should use a static method implemented on Model_Message or Expressomail_Smime case 'smime': $value1 = isset($value1) ? $value1 : $this->processSmimeValue($msg1['structure']); $value2 = isset($value2) ? $value2 : $this->processSmimeValue($msg2['structure']); case 'flags': // Strings if (!isset($value1)) { sort($msg1['flags']); $value1 = implode(',', $msg1['flags']); } if (!isset($value2)) { sort($msg2['flags']); $value2 = implode(',', $msg2['flags']); } case 'subject': // Strings $value1 = isset($value1) ? $value1 : $msg1['header'][$this->_pagination->sort]; $value2 = isset($value2) ? $value2 : $msg2['header'][$this->_pagination->sort]; case 'id': // Strings $value1 = isset($value1) ? $value1 : $msg1[$this->_pagination->sort]; $value2 = isset($value2) ? $value2 : $msg2[$this->_pagination->sort]; return $this->compareStrings($value1, $value2); case 'sender': case 'to': case 'from_name': case 'from_email': // Strings list($header, $field) = explode('_', $this->_pagination->sort); $field = empty($field) ? 'email' : $field; $address1 = Expressomail_Message::convertAddresses($msg1['header'][$header]); $address2 = Expressomail_Message::convertAddresses($msg2['header'][$header]); return $this->compareStrings(isset($address1[0]) && array_key_exists($field, $address1[0]) ? $address1[0][$field] : '', isset($address2[0]) && array_key_exists($field, $address2[0]) ? $address2[0][$field] : ''); } }
/** * testReplaceUris * * @see 0008020: link did not get an anchor in html mail */ public function testReplaceUris() { $message = new Expressomail_Model_Message(array('body' => 'http://www.facebook.com/media/set/?set=a.164136103742229.1073741825.100004375207149&type=1&l=692e495b17')); $result = Expressomail_Message::replaceUris($message->body); $this->assertContains('a href=', $result); }
/** * returns message prepared for json transport * - overwriten to convert recipients to array * * @param Tinebase_Record_Interface $_record * @return array record data */ protected function _recordToJson($_record) { if ($_record instanceof Expressomail_Model_Message) { foreach (array('to', 'cc', 'bcc') as $type) { if (!is_array($_record->{$type})) { if (!empty($_record->{$type})) { $exploded = explode(',', $_record->{$type}); $_record->{$type} = $exploded; } else { $_record->{$type} = array(); } } } if ($_record->preparedParts instanceof Tinebase_Record_RecordSet) { foreach ($_record->preparedParts as $preparedPart) { if ($preparedPart->preparedData instanceof Calendar_Model_iMIP) { try { $iMIPFrontend = new Calendar_Frontend_iMIP(); $iMIPFrontend->prepareComponent($preparedPart->preparedData); } catch (Exception $e) { Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' Could not prepare calendar iMIP component: ' . $e->getMessage()); if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . $e->getTraceAsString()); } } } } } } else { if ($_record instanceof Expressomail_Model_Account) { // add usernames (imap + smtp) $_record->resolveCredentials(); $_record->resolveCredentials(TRUE, FALSE, TRUE); } else { if ($_record instanceof Expressomail_Model_Sieve_Vacation) { if (!$_record->mime) { $_record->reason = Expressomail_Message::convertFromTextToHTML($_record->reason); } } } } return parent::_recordToJson($_record); }
/** * search message by header (X-Tine20TestMessage) and add it to cache * * @param string $_testHeaderValue * @param Expressomail_Model_Folder $_folder * @param boolean $assert * @param string $testHeader * @return Expressomail_Model_Message|NULL */ public function searchAndCacheMessage($_testHeaderValue, $_folder = NULL, $assert = TRUE, $testHeader = 'X-Tine20TestMessage') { $folder = $_folder !== NULL ? $_folder : $this->_folder; $message = $this->_searchMessage($_testHeaderValue, $folder, $assert, $testHeader); if ($message === NULL && !$assert) { return NULL; } // $cachedMessage = $this->_cache->addMessage($message, $folder); // if ($cachedMessage === FALSE) { // // try to add message again (it had a duplicate) // $this->_cache->clear($folder); // $cachedMessage = $this->_cache->addMessage($message, $folder); // } // // if ($assert) { // $this->assertTrue($cachedMessage instanceof Expressomail_Model_Message, 'could not add message to cache'); // } // // $this->_createdMessages->addRecord($cachedMessage); // // return $cachedMessage; $expressoMessage = new Expressomail_Model_Message(array('account_id' => $_folder->account_id, 'messageuid' => $message['uid'], 'folder_id' => $_folder->getId(), 'timestamp' => Tinebase_DateTime::now(), 'received' => Expressomail_Message::convertDate($message['received']), 'size' => $message['size'], 'flags' => $message['flags'])); $expressoMessage->parseStructure($message['structure']); $expressoMessage->parseHeaders($message['header']); $expressoMessage->parseBodyParts(); $attachments = Expressomail_Controller_Message::getInstance()->getAttachments($expressoMessage); $expressoMessage->has_attachment = count($attachments) > 0 ? true : false; return $expressoMessage; }