public function testStreamEncoding() { $testfile = realpath(__FILE__); $original = file_get_contents($testfile); // Test Base64 $fp = fopen($testfile, 'rb'); $this->assertTrue(is_resource($fp)); $part = new Zend_Mime_Part($fp); $part->encoding = Zend_Mime::ENCODING_BASE64; $fp2 = $part->getEncodedStream(); $this->assertTrue(is_resource($fp2)); $encoded = stream_get_contents($fp2); fclose($fp); $this->assertEquals(base64_decode($encoded), $original); // test QuotedPrintable $fp = fopen($testfile, 'rb'); $this->assertTrue(is_resource($fp)); $part = new Zend_Mime_Part($fp); $part->encoding = Zend_Mime::ENCODING_QUOTEDPRINTABLE; $fp2 = $part->getEncodedStream(); $this->assertTrue(is_resource($fp2)); $encoded = stream_get_contents($fp2); fclose($fp); $this->assertEquals(quoted_printable_decode($encoded), $original); }
/** * Create and return the array of headers for this MIME part * * @access public * @return array */ public function getHeadersArray($EOL = Zend_Mime::LINEEND) { $headers = parent::getHeadersArray($EOL); if ($this->location) { $headers[] = array('Content-Location', $this->location); } return $headers; }
public function testShouldSendEmail() { if (!$this->_testsEnabled) { return; } $pwless = new Garp_Auth_Adapter_Passwordless(); $pwless->requestToken(array('email' => self::TEST_EMAIL)); $userModel = new Model_User(); $theUser = $userModel->fetchRow(); $authModel = new Model_AuthPasswordless(); $authRecord = $authModel->fetchRow(); $tokenUrl = new Garp_Util_FullUrl(array(array('method' => 'passwordless'), 'auth_submit')) . '?uid=' . $theUser->id . '&token=' . $authRecord->token; $storedMessage = file_get_contents(GARP_APPLICATION_PATH . '/../tests/tmp/' . self::TEST_EMAIL . '.tmp'); $expectedMessage = Garp_Util_String::interpolate($this->_getMockEmailMessage(), array('LOGIN_URL' => $tokenUrl)); // Pass thru actual Mime part, otherwise the two wil never be the same $mp = new Zend_Mime_Part($expectedMessage); $mp->encoding = Zend_Mime::ENCODING_QUOTEDPRINTABLE; $mp->type = Zend_Mime::TYPE_TEXT; $mp->disposition = Zend_Mime::DISPOSITION_INLINE; $mp->charset = 'iso-8859-1'; // Just check for the token url. Message is encoded so checking for entire message to be // correct is overly complex (and not the responsibility of this unit test). $this->assertTrue(strpos($storedMessage, $mp->getContent("\r\n")) !== false); }
/** * Generate MIME compliant message from the current configuration * * If both a text and HTML body are present, generates a * multipart/alternative Zend_Mime_Part containing the headers and contents * of each. Otherwise, uses whichever of the text or HTML parts present. * * The content part is then prepended to the list of Zend_Mime_Parts for * this message. * * @return void */ protected function _buildBody() { $text = $this->_mail->getBodyText(); $html = $this->_mail->getBodyHtml(); $htmlAttachments = $this->_mail->getHtmlRelatedAttachments(); $htmlAttachmentParts = $htmlAttachments->getParts(); $hasHtmlRelatedParts = count($htmlAttachmentParts); if ($text && $html || $html && $hasHtmlRelatedParts && count($this->_parts)) { // Generate unique boundary for multipart/alternative $mime = new Zend_Mime(null); $boundaryLine = $mime->boundaryLine($this->EOL); $boundaryEnd = $mime->mimeEnd($this->EOL); $html->disposition = false; if ($hasHtmlRelatedParts) { $message = new Zend_Mime_Message(); array_unshift($htmlAttachmentParts, $html); $message->setParts($htmlAttachmentParts); $htmlMime = $htmlAttachments->getMime(); $message->setMime($htmlMime); $html = new Zend_Mime_Part($message->generateMessage($this->EOL, false)); $html->boundary = $htmlMime->boundary(); $html->type = Zend_Mime::MULTIPART_RELATED; $html->encoding = null; } $body = $boundaryLine; if ($text) { $text->disposition = false; $body .= $text->getHeaders($this->EOL) . $this->EOL . $text->getContent($this->EOL) . $this->EOL . $boundaryLine; } $body .= $html->getHeaders($this->EOL) . $this->EOL . $html->getContent($this->EOL) . $this->EOL . $boundaryEnd; $mp = new Zend_Mime_Part($body); $mp->type = Zend_Mime::MULTIPART_ALTERNATIVE; $mp->boundary = $mime->boundary(); $this->_isMultipart = true; // Ensure first part contains text alternatives array_unshift($this->_parts, $mp); // Get headers $this->_headers = $this->_mail->getHeaders(); return; } // If not multipart, then get the body if (false !== ($body = $this->_mail->getBodyHtml())) { array_unshift($this->_parts, $body); if ($hasHtmlRelatedParts) { $this->_mail->setType(Zend_Mime::MULTIPART_RELATED); foreach ($htmlAttachmentParts as $part) { $this->_parts[] = $part; } } } elseif (false !== ($body = $this->_mail->getBodyText())) { array_unshift($this->_parts, $body); } if (!$body) { /** * @see Zend_Mail_Transport_Exception */ require_once 'Zend/Mail/Transport/Exception.php'; throw new Zend_Mail_Transport_Exception('No body specified'); } // Get headers $this->_headers = $this->_mail->getHeaders(); $headers = $body->getHeadersArray($this->EOL); foreach ($headers as $header) { // Headers in Zend_Mime_Part are kept as arrays with two elements, a // key and a value $this->_headers[$header[0]] = array($header[1]); } }
/** * convert charset (and return charset) * * @param Zend_Mime_Part $_part * @param string $charset * @return string */ protected static function _appendCharsetFilter(Zend_Mime_Part $_part, $charset) { if ($charset == 'utf8') { $charset = 'utf-8'; } else { if ($charset == 'us-ascii') { // us-ascii caused problems with iconv encoding to utf-8 $charset = self::DEFAULT_FALLBACK_CHARSET; } else { if (strpos($charset, '.') !== false) { // the stream filter does not like charsets with a dot in its name // stream_filter_append(): unable to create or locate filter "convert.iconv.ansi_x3.4-1968/utf-8//IGNORE" $charset = self::DEFAULT_FALLBACK_CHARSET; } else { if (iconv($charset, 'utf-8', '') === false) { // check if charset is supported by iconv $charset = self::DEFAULT_FALLBACK_CHARSET; } } } } $_part->appendDecodeFilter(self::_getDecodeFilter($charset)); return $charset; }
/** * @group ZF-1491 */ public function testGetRawContentFromPart() { $this->assertEquals($this->testText, $this->part->getRawContent()); }
/** * convert charset (and return charset) * * @param Zend_Mime_Part $_part * @param array $_structure * @param string $_contentType * @return string */ protected function _appendCharsetFilter(Zend_Mime_Part $_part, $_structure) { if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . print_r($_structure, TRUE)); } $charset = isset($_structure['parameters']['charset']) ? $_structure['parameters']['charset'] : self::DEFAULT_FALLBACK_CHARSET; if ($charset == 'utf8') { $charset = 'utf-8'; } else { if ($charset == 'us-ascii' || stripos($charset, 'iso646') !== FALSE) { // us-ascii caused problems with iconv encoding to utf-8 $charset = self::DEFAULT_FALLBACK_CHARSET; } else { if (strpos($charset, '.') !== false) { // the stream filter does not like charsets with a dot in its name // stream_filter_append(): unable to create or locate filter "convert.iconv.ansi_x3.4-1968/utf-8//IGNORE" $charset = self::DEFAULT_FALLBACK_CHARSET; } else { if (iconv($charset, 'utf-8', '') === false) { // check if charset is supported by iconv $charset = self::DEFAULT_FALLBACK_CHARSET; } } } } $_part->appendDecodeFilter($this->_getDecodeFilter($charset)); return $charset; }
/** * add attachments to mail * * @param Tinebase_Mail $_mail * @param Felamimail_Model_Message $_message * @throws Felamimail_Exception_IMAP */ protected function _addAttachments(Tinebase_Mail $_mail, Felamimail_Model_Message $_message) { if (!isset($_message->attachments) || empty($_message->attachments)) { return; } $maxAttachmentSize = $this->_getMaxAttachmentSize(); $size = 0; $tempFileBackend = Tinebase_TempFile::getInstance(); foreach ($_message->attachments as $attachment) { if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Adding attachment: ' . (is_object($attachment) ? print_r($attachment->toArray(), TRUE) : print_r($attachment, TRUE))); } if (isset($attachment['type']) && $attachment['type'] == Felamimail_Model_Message::CONTENT_TYPE_MESSAGE_RFC822 && $_message->original_id instanceof Felamimail_Model_Message) { $part = $this->getMessagePart($_message->original_id, $_message->original_part_id ? $_message->original_part_id : NULL); $part->decodeContent(); $name = $attachment['name'] . '.eml'; $type = $attachment['type']; if (!empty($attachment['size'])) { $size += $attachment['size']; } } else { $tempFile = $attachment instanceof Tinebase_Model_TempFile ? $attachment : (isset($attachment['tempFile']) || array_key_exists('tempFile', $attachment) ? $tempFileBackend->get($attachment['tempFile']['id']) : NULL); if ($tempFile === NULL) { continue; } if (!$tempFile->path) { Tinebase_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . ' Could not find attachment.'); continue; } // get contents from uploaded file $stream = fopen($tempFile->path, 'r'); $part = new Zend_Mime_Part($stream); // RFC822 attachments are not encoded, set all others to ENCODING_BASE64 $part->encoding = $tempFile->type == Felamimail_Model_Message::CONTENT_TYPE_MESSAGE_RFC822 ? null : Zend_Mime::ENCODING_BASE64; $name = $tempFile->name; $type = $tempFile->type; if (!empty($tempFile->size)) { $size += $tempFile->size; } } $part->setTypeAndDispositionForAttachment($type, $name); if ($size > $maxAttachmentSize) { if (Tinebase_Core::isLogLevel(Zend_Log::NOTICE)) { Tinebase_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . ' Current attachment size: ' . Tinebase_Helper::convertToMegabytes($size) . ' MB / allowed size: ' . Tinebase_Helper::convertToMegabytes($maxAttachmentSize) . ' MB'); } throw new Felamimail_Exception_IMAP('Maximum attachment size exceeded. Please remove one or more attachments.'); } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Adding attachment ' . $part->type); } $_mail->addAttachment($part); } }
/** * checks if mail for persona got send * * @param string $_personas * @param string $_assertString * @return void * * @see #6800: add message-id to notification mails */ protected function _assertMail($_personas, $_assertString = NULL, $_location = 'subject') { $messages = self::getMessages(); foreach (explode(',', $_personas) as $personaName) { $mailsForPersona = array(); $otherRecipients = array(); $personaEmail = strstr($personaName, '@') ? $personaName : $this->_getPersona(trim($personaName))->accountEmailAddress; foreach ($messages as $message) { if (Tinebase_Helper::array_value(0, $message->getRecipients()) == $personaEmail) { array_push($mailsForPersona, $message); } else { array_push($otherRecipients, $message->getRecipients()); } } if (!$_assertString) { $this->assertEquals(0, count($mailsForPersona), 'No mail should be send for ' . $personaName); } else { $this->assertEquals(1, count($mailsForPersona), 'One mail should be send for ' . $personaName . ' other recipients: ' . print_r($otherRecipients, true)); $this->assertEquals('UTF-8', $mailsForPersona[0]->getCharset()); switch ($_location) { case 'subject': $subject = $mailsForPersona[0]->getSubject(); $this->assertTrue(FALSE !== strpos($subject, $_assertString), 'Mail subject for ' . $personaName . ' should contain "' . $_assertString . '" but ' . $subject . ' is given'); break; case 'body': $bodyPart = $mailsForPersona[0]->getBodyText(FALSE); // so odd! $s = fopen('php://temp', 'r+'); fputs($s, $bodyPart->getContent()); rewind($s); $bodyPartStream = new Zend_Mime_Part($s); $bodyPartStream->encoding = $bodyPart->encoding; $bodyText = $bodyPartStream->getDecodedContent(); if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' body text: ' . $bodyText); } $this->assertContains($_assertString, $bodyText); break; default: throw new Exception('no such location ' . $_location); break; } $headers = $mailsForPersona[0]->getHeaders(); $this->assertTrue(isset($headers['Message-Id']), 'message-id header not found'); $this->assertContains('@' . php_uname('n'), $headers['Message-Id'][0], 'hostname not in message-id'); } } }
/** * get event attachments * * @param Calendar_Model_Event $_event * @return array of Zend_Mime_Part */ protected function _getEventAttachments($_event) { $attachments = array(); foreach ($_event->attachments as $attachment) { if ($attachment->size < self::INVITATION_ATTACHMENT_MAX_FILESIZE) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Adding attachment " . $attachment->name . ' to invitation mail'); } $path = Tinebase_Model_Tree_Node_Path::STREAMWRAPPERPREFIX . Tinebase_FileSystem_RecordAttachments::getInstance()->getRecordAttachmentPath($_event) . '/' . $attachment->name; $handle = fopen($path, 'r'); $stream = fopen("php://temp", 'r+'); stream_copy_to_stream($handle, $stream); rewind($stream); $part = new Zend_Mime_Part($stream); $part->encoding = Zend_Mime::ENCODING_BASE64; // ? $part->filename = $attachment->name; $part->setTypeAndDispositionForAttachment($attachment->contenttype, $attachment->name); fclose($handle); $attachments[] = $part; } else { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Not adding attachment " . $attachment->name . ' to invitation mail (size: ' . Tinebase_Helper::convertToMegabytes($attachment - size) . ')'); } } } return $attachments; }
/** * Get the Content of the current Mime Part. This class assumes the * content is already encoded when $this->alreadyEncoded is set to true. * * @return String */ public function getContent($EOL = Zend_Mime::LINEEND) { if ($this->_isStream) { return parent::getContent($EOL); } else { if ($this->_alreadyEncoded) { return $this->_content; } else { return parent::getContent($EOL); } } }
/** * 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; }