| | |
| | | |
| | | // part body not fetched yet... save in memory if it's small enough |
| | | if ($part->body === null && is_numeric($mime_id) && $part->size < self::BODY_MAX_SIZE) { |
| | | $this->storage->set_folder($this->folder); |
| | | // Warning: body here should be always unformatted |
| | | $part->body = $this->storage->get_message_part($this->uid, $mime_id, $part, |
| | | null, null, true, 0, false); |
| | |
| | | $this->storage->set_folder($this->folder); |
| | | |
| | | $body = $this->storage->get_message_part($this->uid, $mime_id, $part, |
| | | $mode === -1, is_resource($mode) ? $mode : null, !$formatted, $max_bytes, $formatted); |
| | | |
| | | if (!$mode && $body && $formatted) { |
| | | $body = self::format_part_body($body, $part, $this->headers->charset); |
| | | } |
| | | $mode === -1, is_resource($mode) ? $mode : null, |
| | | !($mode && $formatted), $max_bytes, $mode && $formatted); |
| | | |
| | | if (is_resource($mode)) { |
| | | rewind($mode); |
| | | return $body !== false; |
| | | } |
| | | |
| | | if (!$mode && $body && $formatted) { |
| | | $body = self::format_part_body($body, $part, $this->headers->charset); |
| | | } |
| | | |
| | | return $body; |
| | |
| | | else if ($mimetype == 'multipart/alternative' |
| | | && is_array($structure->parts) && count($structure->parts) > 1 |
| | | ) { |
| | | $plain_part = null; |
| | | $html_part = null; |
| | | $print_part = null; |
| | | $related_part = null; |
| | | $attach_part = null; |
| | | |
| | | // get html/plaintext parts, other add to attachments list |
| | | foreach ($structure->parts as $p => $sub_part) { |
| | | $sub_mimetype = $sub_part->mimetype; |
| | |
| | | $related_part = $p; |
| | | else if ($sub_mimetype == 'text/plain' && !$plain_part) |
| | | $plain_part = $p; |
| | | else if ($sub_mimetype == 'text/html' && !$html_part) |
| | | else if ($sub_mimetype == 'text/html' && !$html_part) { |
| | | $html_part = $p; |
| | | $this->got_html_part = true; |
| | | } |
| | | else if ($sub_mimetype == 'text/enriched' && !$enriched_part) |
| | | $enriched_part = $p; |
| | | else { |
| | |
| | | $p->ctype_secondary = 'plain'; |
| | | $p->mimetype = 'text/plain'; |
| | | $p->realtype = 'multipart/encrypted'; |
| | | $p->mime_id = $structure->mime_id; |
| | | |
| | | $this->parts[] = $p; |
| | | |
| | | // add encrypted payload part as attachment |
| | | if (is_array($structure->parts)) { |
| | | for ($i=0; $i < count($structure->parts); $i++) { |
| | | $subpart = $structure->parts[$i]; |
| | | if ($subpart->mimetype == 'application/octet-stream' || !empty($subpart->filename)) { |
| | | $this->attachments[] = $subpart; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | // this is an S/MIME ecrypted message -> create a plaintext body with the according message |
| | | else if ($mimetype == 'application/pkcs7-mime') { |
| | |
| | | $p->ctype_secondary = 'plain'; |
| | | $p->mimetype = 'text/plain'; |
| | | $p->realtype = 'application/pkcs7-mime'; |
| | | $p->mime_id = $structure->mime_id; |
| | | |
| | | $this->parts[] = $p; |
| | | |
| | | if (!empty($structure->filename)) { |
| | | $this->attachments[] = $structure; |
| | | } |
| | | } |
| | | // message contains multiple parts |
| | | else if (is_array($structure->parts) && !empty($structure->parts)) { |
| | |
| | | continue; |
| | | |
| | | if ($part_mimetype == 'text/html' && $mail_part->size) { |
| | | $got_html_part = true; |
| | | $this->got_html_part = true; |
| | | } |
| | | |
| | | $mail_part = $plugin['structure']; |
| | |
| | | else if ($mail_part->mimetype == 'message/rfc822') { |
| | | $this->parse_structure($mail_part); |
| | | } |
| | | // calendar part not marked as attachment (#1490325) |
| | | else if ($part_mimetype == 'text/calendar') { |
| | | if (!$mail_part->filename) { |
| | | $mail_part->filename = 'calendar.ics'; |
| | | } |
| | | |
| | | $this->attachments[] = $mail_part; |
| | | } |
| | | } |
| | | |
| | | // if this was a related part try to resolve references |
| | |
| | | // MS Outlook sends sometimes non-related attachments as related |
| | | // In this case multipart/related message has only one text part |
| | | // We'll add all such attachments to the attachments list |
| | | if (!isset($got_html_part) && empty($inline_object->content_id)) { |
| | | if (!isset($this->got_html_part)) { |
| | | $this->attachments[] = $inline_object; |
| | | } |
| | | // MS Outlook sometimes also adds non-image attachments as related |
| | |
| | | { |
| | | // @TODO: attachment may be huge, handle body via file |
| | | $body = $this->get_part_body($part->mime_id); |
| | | $tnef = new tnef_decoder; |
| | | $tnef = new rcube_tnef_decoder; |
| | | $tnef_arr = $tnef->decompress($body); |
| | | $parts = array(); |
| | | |
| | |
| | | foreach ($tnef_arr as $pid => $winatt) { |
| | | $tpart = new rcube_message_part; |
| | | |
| | | $tpart->filename = trim($winatt['name']); |
| | | $tpart->filename = $this->fix_attachment_name(trim($winatt['name']), $part); |
| | | $tpart->encoding = 'stream'; |
| | | $tpart->ctype_primary = trim(strtolower($winatt['type'])); |
| | | $tpart->ctype_secondary = trim(strtolower($winatt['subtype'])); |
| | |
| | | break; |
| | | } |
| | | |
| | | // update message content-type |
| | | if ($part->mimetype != 'multipart/mixed') { |
| | | $part->ctype_primary = 'multipart'; |
| | | $part->ctype_secondary = 'mixed'; |
| | | $part->mimetype = $part->ctype_primary . '/' . $part->ctype_secondary; |
| | | } |
| | | |
| | | $endpos = $m[0][1]; |
| | | $begin_len = strlen($matches[0][0]); |
| | | $end_len = strlen($m[0][0]); |
| | |
| | | |
| | | // remove attachment body from the message body |
| | | $part->body = substr_replace($part->body, '', $startpos, $endpos + $end_len - $startpos); |
| | | // mark body as modified so it will not be cached by rcube_imap_cache |
| | | $part->body_modified = true; |
| | | |
| | | // add attachments to the structure |
| | | $uupart = new rcube_message_part; |
| | |
| | | return $parts; |
| | | } |
| | | |
| | | /** |
| | | * Fix attachment name encoding if needed/possible |
| | | */ |
| | | protected function fix_attachment_name($name, $part) |
| | | { |
| | | if ($name == rcube_charset::clean($name)) { |
| | | return $name; |
| | | } |
| | | |
| | | // find charset from part or its parent(s) |
| | | if ($part->charset) { |
| | | $charsets[] = $part->charset; |
| | | } |
| | | else { |
| | | // check first part (common case) |
| | | $n = strpos($part->mime_id, '.') ? preg_replace('/\.[0-9]+$/', '', $part->mime_id) . '.1' : 1; |
| | | if (($_part = $this->mime_parts[$n]) && $_part->charset) { |
| | | $charsets[] = $_part->charset; |
| | | } |
| | | |
| | | // check parents' charset |
| | | $items = explode('.', $part->mime_id); |
| | | for ($i = count($items)-1; $i > 0; $i--) { |
| | | $last = array_pop($items); |
| | | $parent = $this->mime_parts[join('.', $items)]; |
| | | |
| | | if ($parent && $parent->charset) { |
| | | $charsets[] = $parent->charset; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if ($this->headers->charset) { |
| | | $charsets[] = $this->headers->charset; |
| | | } |
| | | |
| | | if (empty($charsets)) { |
| | | $rcube = rcube::get_instance(); |
| | | $charsets[] = rcube_charset::detect($name, $rcube->config->get('default_charset', RCUBE_CHARSET)); |
| | | } |
| | | |
| | | foreach (array_unique($charsets) as $charset) { |
| | | $_name = rcube_charset::convert($name, $charset); |
| | | |
| | | if ($_name == rcube_charset::clean($_name)) { |
| | | if (!$part->charset) { |
| | | $part->charset = $charset; |
| | | } |
| | | |
| | | return $_name; |
| | | } |
| | | } |
| | | |
| | | return $name; |
| | | } |
| | | |
| | | /** |
| | | * Deprecated methods (to be removed) |