/** * test conversion to plain text (blockquotes to quotes) / tests linebreaks, too */ public function testGetPlainTextBody() { $message = new Expressomail_Model_Message(array('body' => 'blabla<br/><blockquote class="felamimail-body-blockquote">lalülüüla<br/><br/><div>lala</div><br/><blockquote class="felamimail-body-blockquote">xyz</blockquote></blockquote><br/><br/>jojo<br/>' . 'lkjlhk<div><br></div><div><br><div>jjlöjlö</div><div><font face="arial"><br></font></div></div><div><font face="arial">Pickhuben 2-4, 20457 Hamburg</font></div>')); $result = $message->getPlainTextBody(); //echo $result; $this->assertEquals("blabla\n" . "> lalülüüla\n" . "> \n" . "> lala\n" . "> \n" . "> > xyz\n" . "\n\n" . "jojo\n" . "lkjlhk\n\n\n" . "jjlöjlö\n\n" . "Pickhuben 2-4, 20457 Hamburg\n", $result); }
/** * * @param array $source * @param resource | string $inputStream * @param string $flag * @throws Zend_Mail_Protocol_Exception */ public function parseAndSendMessage($source, $inputStream, $flag = NULL) { $originalMessage = $this->getCompleteMessage($source['itemId'], null, false); $user = Tinebase_Core::getUser(); if (!is_resource($inputStream)) { $stream = fopen("php://temp", 'r+'); fwrite($stream, $inputStream); $inputStream = $stream; rewind($inputStream); } $incomingMessage = new Zend_Mail_Message(array('file' => $inputStream)); $headers = $incomingMessage->getHeaders(); $body = $headers['content-transfer-encoding'] == 'base64' ? base64_decode($incomingMessage->getContent()) : $incomingMessage->getContent(); $isTextPlain = strpos($headers['content-type'], 'text/plain'); $bodyLines = preg_split('/\\r\\n|\\r|\\n/', $body); $body = ''; if ($isTextPlain !== false) { foreach ($bodyLines as &$line) { $body .= htmlentities($line) . '<br>'; } } else { foreach ($bodyLines as &$line) { $body .= $line . '<br>'; } } $body = '<div>' . $body . '</div>'; $bodyOrigin = $originalMessage['body']; preg_match("/<body[^>]*>(.*?)<\\/body>/is", $bodyOrigin, $matches); $bodyOrigin = count($matches) > 1 ? $matches[1] : $bodyOrigin; $body .= '<div>' . $bodyOrigin . '</div>'; $attachments = array(); foreach ($originalMessage['attachments'] as &$att) { try { $att['name'] = $att['filename']; $att['type'] = $att['content-type']; } catch (Exception $e) { } array_push($attachments, $att); } $recordData = array(); $recordData['note'] = ''; $recordData['content_type'] = 'text/html'; $recordData['account_id'] = $originalMessage->account_id; $recordData['to'] = is_array($headers['to']) ? $headers['to'] : array($headers['to']); $recordData['cc'] = array(); $recordData['bcc'] = array(); $recordData['subject'] = $headers['subject']; $recordData['body'] = $body; //$recordData['flags'] = array_merge($incomingMessage->getFlags(), $originalMessage['flags']); $recordData['flags'] = $flag != NULL ? $flag : ''; $recordData['original_id'] = $source['itemId']; $recordData['embedded_images'] = array(); $recordData['attachments'] = $attachments; $recordData['from_email'] = $user->accountEmailAddress; $recordData['from_name'] = $user->accountFullName; $recordData['customfields'] = array(); $message = new Expressomail_Model_Message(); $message->setFromJsonInUsersTimezone($recordData); try { Expressomail_Controller_Message_Send::getInstance()->sendMessage($message); } catch (Zend_Mail_Protocol_Exception $zmpe) { Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' Could not send message: ' . $zmpe->getMessage()); throw $zmpe; } }
/** * 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)); } }
/** * Get multipart report notification message body * * @param Expressomail_Model_Message $_message * @return string Expressomail_Model_MessageDispositionNotificationPart->getHTMLFormatted $_mdnMessage */ private function _getMultipartReportNotificationMessageBody(Expressomail_Model_Message $_message, $_partId, $_contentType, $_account = NULL) { $_structure = $_message->getPartStructure($_partId); $_bodyParts = $_message->getBodyParts($_structure, $_contentType); // test if we have all the parts if (empty($_bodyParts) || count($_bodyParts) < 2 || count($_bodyParts) > 3 || !isset($_bodyParts[2]['contentType']) && $_bodyParts[2]['contentType'] !== Expressomail_Model_Message::CONTENT_TYPE_MESSAGE_DISPOSITION_NOTIFICATION) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Malformed MDN Message.'); return ''; } // MDN message assembly needs 2 original message parts to handle //First is part 2 to get original message send data $_bodyPart = $this->getMessagePart($_message, 2, FALSE, $_structure); //Second is part 1 to get SIEVE automatic message data $_bodyPart2 = $this->getMessagePart($_message, 1, FALSE, $_structure); $_mdnMessage = new Expressomail_Model_MessageDispositionNotificationPart($this->_getDecodedBodyContent($_bodyPart, $_structure)); $_mdnSieve = new Expressomail_Model_MessageDispositionNotificationPart($this->_getDecodedBodyContent($_bodyPart2, $_structure)); $_userMessage = $_mdnSieve->getCustomMessage(); //Put them together to assebly user friendly message return $_mdnMessage->getHTMLFormatted($_userMessage); }
/** * do substitutions in vacation message * * @param Expressomail_Model_Sieve_Vacation $vacation * @param string $message * @return string * * @todo get locale from placeholder (i.e. endDate-_LOCALESTRING_) * @todo get field from placeholder (i.e. representation-_FIELDNAME_) * @todo use html templates? * @todo use ZF templates / phplib tpl files? */ protected function _doMessageSubstitutions(Expressomail_Model_Sieve_Vacation $vacation, $message) { $timezone = Tinebase_Core::get(Tinebase_Core::USERTIMEZONE); $representatives = $vacation->contact_ids ? Addressbook_Controller_Contact::getInstance()->getMultiple($vacation->contact_ids) : array(); if ($vacation->contact_ids && count($representatives) > 0) { // sort representatives $representativesArray = array(); foreach ($vacation->contact_ids as $id) { $representativesArray[] = $representatives->getById($id); } } try { $ownContact = Addressbook_Controller_Contact::getInstance()->getContactByUserId(Tinebase_Core::getUser()->getId()); } catch (Exception $e) { if (Tinebase_Core::isLogLevel(Zend_Log::WARN)) { Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' ' . $e); } $ownContact = NULL; } $search = array('{startDate-en_US}', '{endDate-en_US}', '{startDate-de_DE}', '{endDate-de_DE}', '{representation-n_fn-1}', '{representation-n_fn-2}', '{representation-email-1}', '{representation-email-2}', '{representation-tel_work-1}', '{representation-tel_work-2}', '{owncontact-n_fn}', '{signature}'); $replace = array(Tinebase_Translation::dateToStringInTzAndLocaleFormat($vacation->start_date, $timezone, new Zend_Locale('en_US'), 'date'), Tinebase_Translation::dateToStringInTzAndLocaleFormat($vacation->end_date, $timezone, new Zend_Locale('en_US'), 'date'), Tinebase_Translation::dateToStringInTzAndLocaleFormat($vacation->start_date, $timezone, new Zend_Locale('de_DE'), 'date'), Tinebase_Translation::dateToStringInTzAndLocaleFormat($vacation->end_date, $timezone, new Zend_Locale('de_DE'), 'date'), isset($representativesArray[0]) ? $representativesArray[0]->n_fn : 'unknown person', isset($representativesArray[1]) ? $representativesArray[1]->n_fn : 'unknown person', isset($representativesArray[0]) ? $representativesArray[0]->email : 'unknown email', isset($representativesArray[1]) ? $representativesArray[1]->email : 'unknown email', isset($representativesArray[0]) ? $representativesArray[0]->tel_work : 'unknown phone', isset($representativesArray[1]) ? $representativesArray[1]->tel_work : 'unknown phone', $ownContact ? $ownContact->n_fn : '', $vacation->signature ? Expressomail_Model_Message::convertHTMLToPlainTextWithQuotes(preg_replace("/\\r|\\n/", '', $vacation->signature)) : ''); $result = str_replace($search, $replace, $message); if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . $result); } 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; }
/** * report message(s) as phishing * * @param array $msgIds * @param array $recordData * @return array */ public function reportPhishing($msgIds, $recordData) { $message = new Expressomail_Model_Message(); $message->setFromJsonInUsersTimezone($recordData); $zipFile = Expressomail_Controller_Message::getInstance()->zipMessages($msgIds); $message = Expressomail_Controller_Message::getInstance()->parsePhishingNotification($message, $zipFile); $message = Expressomail_Controller_Message_Send::getInstance()->sendMessage($message); $result = $this->_recordToJson($message); return $result; }
/** * 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; }