/** * Gets the attached file name * * @return Value */ public function getFileName() { $value = ''; $headers = $this->part->getHeaders(); if ($headers->has('Content-Disposition')) { $contentDisposition = $this->part->getHeader('Content-Disposition'); $value = Decode::splitContentType($contentDisposition->getFieldValue(), 'filename'); $encoding = $contentDisposition->getEncoding(); } if (empty($value) && $headers->has('Content-Type')) { /** @var \Zend\Mail\Header\ContentType $contentType */ $contentType = $this->part->getHeader('Content-Type'); $value = $contentType->getParameter('name'); $encoding = $contentType->getEncoding(); } if (empty($encoding)) { $encoding = 'ASCII'; } // Extract name from quoted text. // zend mail library bug (incorrect header decode). // Zend\Mail\Headers line 82 ($currentLine .= ' ' . trim($line);) // Fixed in zend-mail 2.4 if (preg_match('"([^\\"]+)"', $value, $result)) { $value = $result[0]; } return new Value($value, $encoding); }
/** * Gets the message attachments * * @return Attachment[] */ public function getAttachments() { if (!$this->isMultipart()) { return array(); } $result = array(); foreach ($this as $part) { /** @var Part $part */ $contentType = $this->getPartContentType($part); if ($contentType !== null) { $name = $contentType->getParameter('name'); if ($name !== null) { $contentDisposition = $this->getPartContentDisposition($part); if ($contentDisposition !== null) { if (null !== Decode::splitContentType('attachment')) { $result[] = new Attachment($part); } } else { // The Content-Disposition may be missed, because it is introduced only in RFC 2183 // In this case it is assumed that any part which has ";name=" // in the Content-Type is an attachment $result[] = new Attachment($part); } } } } return $result; }
/** * Decodes a MIME encoded string and returns a Zend\Mime\Message object with * all the MIME parts set according to the given string * * @param string $message * @param string $boundary * @param string $EOL EOL string; defaults to {@link Zend\Mime\Mime::LINEEND} * @throws Exception\RuntimeException * @return \Zend\Mime\Message */ public static function createFromMessage($message, $boundary, $EOL = Mime::LINEEND) { $parts = Decode::splitMessageStruct($message, $boundary, $EOL); $res = new static(); foreach ($parts as $part) { // now we build a new MimePart for the current Message Part: $properties = array(); foreach ($part['header'] as $header) { /** @var \Zend\Mail\Header\HeaderInterface $header */ /** * @todo check for characterset and filename */ $fieldName = $header->getFieldName(); $fieldValue = $header->getFieldValue(); switch (strtolower($fieldName)) { case 'content-type': $properties['type'] = $fieldValue; break; case 'content-transfer-encoding': $properties['encoding'] = $fieldValue; break; case 'content-id': $properties['id'] = trim($fieldValue, '<>'); break; case 'content-disposition': $properties['disposition'] = $fieldValue; break; case 'content-description': $properties['description'] = $fieldValue; break; case 'content-location': $properties['location'] = $fieldValue; break; case 'content-language': $properties['language'] = $fieldValue; break; } } $body = $part['body']; if (isset($properties['encoding'])) { switch ($properties['encoding']) { case 'quoted-printable': $body = quoted_printable_decode($body); break; case 'base64': $body = base64_decode($body); break; } } $newPart = new Part($body); foreach ($properties as $key => $value) { $newPart->{$key} = $value; } $res->addPart($newPart); } return $res; }
/** * Gets the attached file name * * @return Value */ public function getFileName() { $value = ''; $headers = $this->part->getHeaders(); if ($headers->has('Content-Disposition')) { $contentDisposition = $this->part->getHeader('Content-Disposition'); $value = Decode::splitContentType($contentDisposition->getFieldValue(), 'filename'); $encoding = $contentDisposition->getEncoding(); } if (empty($value) && $headers->has('Content-Type')) { /** @var \Zend\Mail\Header\ContentType $contentType */ $contentType = $this->part->getHeader('Content-Type'); $value = $contentType->getParameter('name'); $encoding = $contentType->getEncoding(); } if (empty($encoding)) { $encoding = 'ASCII'; } return new Value($value, $encoding); }
/** * Instantiate from raw message string, Restore body to Mime\Message * * @param string $rawMessage * @return Message */ public static function fromString($rawMessage) { $message = new static(); $headers = null; $content = null; Decode::splitMessage($rawMessage, $headers, $content); if ($headers->has('mime-version')) { $boundary = $headers->get('contenttype')->getParameter('boundary'); if ($boundary) { $content = ZendMimeMessage::createFromMessage($content, $boundary); } } if ($headers->has('content-transfer-encoding')) { if ($headers->get('contenttransferencoding')->getTransferEncoding() == 'base64') { $content = base64_decode($content); } } $message->setHeaders($headers); $message->setBody($content); return $message; }
/** * Instantiate from raw message string * * @todo Restore body to Mime\Message * @param string $rawMessage * @return Message */ public static function fromString($rawMessage) { $message = new static(); $headers = null; $content = null; Mime\Decode::splitMessage($rawMessage, $headers, $content); if ($headers->has('mime-version')) { // todo - restore body to mime\message } $message->setHeaders($headers); $message->setBody($content); return $message; }
public function testSpaceInFieldName() { $header = 'test; foo =bar; baz =42'; $this->assertEquals(Mime\Decode::splitHeaderField($header, 'foo'), 'bar'); $this->assertEquals(Mime\Decode::splitHeaderField($header, 'baz'), 42); }
/** * Get a specific field from a header like content type or all fields as array * * If the header occurs more than once, only the value from the first header * is returned. * * Throws an Exception if the requested header does not exist. If * the specific header field does not exist, returns null. * * @param string $name name of header, like in getHeader() * @param string $wantedPart the wanted part, default is first, if null an array with all parts is returned * @param string $firstName key name for the first part * @return string|array wanted part or all parts as array($firstName => firstPart, partname => value) * @throws \Zend\Mime\Exception\RuntimeException */ public function getHeaderField($name, $wantedPart = '0', $firstName = '0') { return Mime\Decode::splitHeaderField(current($this->getHeader($name, 'array')), $wantedPart, $firstName); }
/** * Public constructor * * This handler supports the following params: * - file filename or open file handler with message content (required) * - startPos start position of message or part in file (default: current position) * - endPos end position of message or part in file (default: end of file) * * @param array $params full message with or without headers * @throws \Zend\Mail\Exception */ public function __construct(array $params) { if (empty($params['file'])) { throw new Mail\Exception('no file given in params'); } if (!is_resource($params['file'])) { $this->_fh = fopen($params['file'], 'r'); } else { $this->_fh = $params['file']; } if (!$this->_fh) { throw new Mail\Exception('could not open file'); } if (isset($params['startPos'])) { fseek($this->_fh, $params['startPos']); } $header = ''; $endPos = isset($params['endPos']) ? $params['endPos'] : null; while (($endPos === null || ftell($this->_fh) < $endPos) && trim($line = fgets($this->_fh))) { $header .= $line; } $body = null; // "Declare" variable since it's passed by reference Mime\Decode::splitMessage($header, $this->_headers, $body); $this->_contentPos[0] = ftell($this->_fh); if ($endPos !== null) { $this->_contentPos[1] = $endPos; } else { fseek($this->_fh, 0, SEEK_END); $this->_contentPos[1] = ftell($this->_fh); } if (!$this->isMultipart()) { return; } $boundary = $this->getHeaderField('content-type', 'boundary'); if (!$boundary) { throw new Mail\Exception('no boundary found in content type to split message'); } $part = array(); $pos = $this->_contentPos[0]; fseek($this->_fh, $pos); while (!feof($this->_fh) && ($endPos === null || $pos < $endPos)) { $line = fgets($this->_fh); if ($line === false) { if (feof($this->_fh)) { break; } throw new Mail\Exception('error reading file'); } $lastPos = $pos; $pos = ftell($this->_fh); $line = trim($line); if ($line == '--' . $boundary) { if ($part) { // not first part $part[1] = $lastPos; $this->_partPos[] = $part; } $part = array($pos); } else { if ($line == '--' . $boundary . '--') { $part[1] = $lastPos; $this->_partPos[] = $part; break; } } } $this->_countParts = count($this->_partPos); }
public function getRawContent($id, $part = null) { if ($part !== null) { // TODO: implement throw new Exception\RuntimeException('not implemented'); } $content = $this->protocol->retrieve($id); // TODO: find a way to avoid decoding the headers $headers = null; // "Declare" variable since it's passed by reference $body = null; // "Declare" variable before first usage. Mime\Decode::splitMessage($content, $headers, $body); return $body; }
protected function processContent(Message &$message, Part $part) { $headers = $part->getHeaders(); $contentType = $headers->has('content-type') ? strtolower($part->getHeaderField('content-type')) : NULL; if ($this->isMultipartType($contentType)) { $boundary = $part->getHeaderField('content-type', 'boundary'); if ($boundary) { $subStructs = Decode::splitMessageStruct($part->getContent(), $boundary); $subPartNum = 1; foreach ($subStructs as $subStruct) { $subPart = new Part(['content' => $subStruct['body'], 'headers' => $subStruct['header']]); // Recursive call $subPart->partNum = $part->partNum . "." . $subPartNum++; $this->processContent($message, $subPart); } } else { $wrappedPart = new Part(['raw' => $part->getContent()]); $wrappedPart->partNum = $part->partNum; $this->processContent($message, $wrappedPart); } } elseif ($this->isTextType($contentType) || !$contentType) { $this->processTextContent($message, $contentType, self::convertContent($part->getContent(), $part->getHeaders()), $contentType ? $part->getHeaderField('content-type', 'charset') : 'US-ASCII'); } else { $this->processAttachment($message, $part); } }
/** * Retrieves Message Attachments * * @param \Zend\Mail\Storage\Message $zendMailMessage * @return array */ private function processAttachments($zendMailMessage) { $attachments = array(); if ($zendMailMessage->getBody()) { $parts = $zendMailMessage->getBody()->getParts(); foreach ($parts as $part) { if ($part->disposition) { $disposition = \Zend\Mime\Decode::splitHeaderField($part->disposition); if ($disposition[0] == \Zend\Mime\Mime::DISPOSITION_ATTACHMENT && isset($disposition['filename'])) { $fileName = $disposition['filename']; $fileContent = $part->getContent(); $attachments[] = new Attachment($fileName, base64_decode($fileContent)); } } } } return $attachments; }
/** * @return string|null */ public function getEmbeddedContentId() { $contentIdValue = $this->getContentIdValue(); if ($contentIdValue !== null) { $contentDisposition = $this->getContentDispositionValue(); if (!$contentDisposition || Decode::splitContentType($contentDisposition, 'type') === 'inline') { return substr($contentIdValue, 1, strlen($contentIdValue) - 2); } } return null; }
/** * Retrieves Message Attachments * * @param \Zend\Mail\Storage\Message $imapMessage * @return array */ private function processAttachments($imapMessage) { $attachments = array(); if ($imapMessage->isMultipart()) { foreach (new \RecursiveIteratorIterator($imapMessage) as $part) { $headers = $part->getHeaders(); if ($headers->get('contentdisposition')) { $contentDisposition = $headers->get('contentdisposition'); $disposition = \Zend\Mime\Decode::splitHeaderField($contentDisposition->getFieldValue()); if ($disposition[0] == (\Zend\Mime\Mime::DISPOSITION_ATTACHMENT || \Zend\Mime\Mime::DISPOSITION_INLINE) && isset($disposition['filename'])) { $fileName = $disposition['filename']; $fileContent = $part->getContent(); $attachments[] = new Attachment($fileName, base64_decode($fileContent)); } } } } return $attachments; }
/** * Decodes a MIME encoded string and returns a Zend_Mime_Message object with * all the MIME parts set according to the given string * * @param string $message * @param string $boundary * @param string $EOL EOL string; defaults to {@link Zend_Mime::LINEEND} * @return \Zend\Mime\Message */ public static function createFromMessage($message, $boundary, $EOL = Mime::LINEEND) { $parts = Decode::splitMessageStruct($message, $boundary, $EOL); $res = new self(); foreach ($parts as $part) { // now we build a new MimePart for the current Message Part: $newPart = new Part($part['body']); foreach ($part['header'] as $key => $value) { /** * @todo check for characterset and filename */ switch (strtolower($key)) { case 'content-type': $newPart->type = $value; break; case 'content-transfer-encoding': $newPart->encoding = $value; break; case 'content-id': $newPart->id = trim($value, '<>'); break; case 'content-disposition': $newPart->disposition = $value; break; case 'content-description': $newPart->description = $value; break; case 'content-location': $newPart->location = $value; break; case 'content-language': $newPart->language = $value; break; default: throw new Zend\Exception('Unknown header ignored for MimePart:' . $key); } } $res->addPart($newPart); } return $res; }