| | |
| | | * Handler for IMAP APPEND command |
| | | * |
| | | * @param string $mailbox Mailbox name |
| | | * @param string $message Message content |
| | | * @param string|array $message The message source string or array (of strings and file pointers) |
| | | * @param array $flags Message flags |
| | | * @param string $date Message internal date |
| | | * @param bool $binary Enable BINARY append (RFC3516) |
| | |
| | | |
| | | $binary = $binary && $this->getCapability('BINARY'); |
| | | $literal_plus = !$binary && $this->prefs['literal+']; |
| | | $len = 0; |
| | | $msg = is_array($message) ? $message : array(&$message); |
| | | $chunk_size = 512000; |
| | | |
| | | for ($i=0, $cnt=count($msg); $i<$cnt; $i++) { |
| | | if (is_resource($msg[$i])) { |
| | | $stat = fstat($msg[$i]); |
| | | if ($stat === false) { |
| | | return false; |
| | | } |
| | | $len += $stat['size']; |
| | | } |
| | | else { |
| | | if (!$binary) { |
| | | $message = str_replace("\r", '', $message); |
| | | $message = str_replace("\n", "\r\n", $message); |
| | | $msg[$i] = str_replace("\r", '', $msg[$i]); |
| | | $msg[$i] = str_replace("\n", "\r\n", $msg[$i]); |
| | | } |
| | | |
| | | $len = strlen($message); |
| | | $len += strlen($msg[$i]); |
| | | } |
| | | } |
| | | |
| | | if (!$len) { |
| | | return false; |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | if (!$this->putLine($message)) { |
| | | foreach ($msg as $msg_part) { |
| | | // file pointer |
| | | if (is_resource($msg_part)) { |
| | | rewind($msg_part); |
| | | while (!feof($msg_part) && $this->fp) { |
| | | $buffer = fread($msg_part, $chunk_size); |
| | | $this->putLine($buffer, false); |
| | | } |
| | | fclose($msg_part); |
| | | } |
| | | // string |
| | | else { |
| | | $size = strlen($msg_part); |
| | | |
| | | // Break up the data by sending one chunk (up to 512k) at a time. |
| | | // This approach reduces our peak memory usage |
| | | for ($offset = 0; $offset < $size; $offset += $chunk_size) { |
| | | $chunk = substr($msg_part, $offset, $chunk_size); |
| | | if (!$this->putLine($chunk, false)) { |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!$this->putLine('')) { // \r\n |
| | | return false; |
| | | } |
| | | |
| | |
| | | */ |
| | | function appendFromFile($mailbox, $path, $headers=null, $flags = array(), $date = null, $binary = false) |
| | | { |
| | | unset($this->data['APPENDUID']); |
| | | |
| | | if ($mailbox === null || $mailbox === '') { |
| | | return false; |
| | | } |
| | | |
| | | // open message file |
| | | $in_fp = false; |
| | | if (file_exists(realpath($path))) { |
| | | $in_fp = fopen($path, 'r'); |
| | | $fp = fopen($path, 'r'); |
| | | } |
| | | |
| | | if (!$in_fp) { |
| | | if (!$fp) { |
| | | $this->setError(self::ERROR_UNKNOWN, "Couldn't open $path for reading"); |
| | | return false; |
| | | } |
| | | |
| | | $body_separator = "\r\n\r\n"; |
| | | $len = filesize($path); |
| | | |
| | | if (!$len) { |
| | | return false; |
| | | } |
| | | |
| | | $message = array(); |
| | | if ($headers) { |
| | | $headers = preg_replace('/[\r\n]+$/', '', $headers); |
| | | $len += strlen($headers) + strlen($body_separator); |
| | | $message[] = trim($headers, "\r\n") . "\r\n\r\n"; |
| | | } |
| | | $message[] = $fp; |
| | | |
| | | $binary = $binary && $this->getCapability('BINARY'); |
| | | $literal_plus = !$binary && $this->prefs['literal+']; |
| | | |
| | | // build APPEND command |
| | | $key = $this->nextTag(); |
| | | $request = "$key APPEND " . $this->escape($mailbox) . ' (' . $this->flagsToStr($flags) . ')'; |
| | | if (!empty($date)) { |
| | | $request .= ' ' . $this->escape($date); |
| | | } |
| | | $request .= ' ' . ($binary ? '~' : '') . '{' . $len . ($literal_plus ? '+' : '') . '}'; |
| | | |
| | | // send APPEND command |
| | | if ($this->putLine($request)) { |
| | | // Don't wait when LITERAL+ is supported |
| | | if (!$literal_plus) { |
| | | $line = $this->readReply(); |
| | | |
| | | if ($line[0] != '+') { |
| | | $this->parseResult($line, 'APPEND: '); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // send headers with body separator |
| | | if ($headers) { |
| | | $this->putLine($headers . $body_separator, false); |
| | | } |
| | | |
| | | // send file |
| | | while (!feof($in_fp) && $this->fp) { |
| | | $buffer = fgets($in_fp, 4096); |
| | | $this->putLine($buffer, false); |
| | | } |
| | | fclose($in_fp); |
| | | |
| | | if (!$this->putLine('')) { // \r\n |
| | | return false; |
| | | } |
| | | |
| | | // read response |
| | | do { |
| | | $line = $this->readLine(); |
| | | } while (!$this->startsWith($line, $key, true, true)); |
| | | |
| | | // Clear internal status cache |
| | | unset($this->data['STATUS:'.$mailbox]); |
| | | |
| | | if ($this->parseResult($line, 'APPEND: ') != self::ERROR_OK) |
| | | return false; |
| | | else if (!empty($this->data['APPENDUID'])) |
| | | return $this->data['APPENDUID']; |
| | | else |
| | | return true; |
| | | } |
| | | else { |
| | | $this->setError(self::ERROR_COMMAND, "Unable to send command: $request"); |
| | | } |
| | | |
| | | return false; |
| | | return $this->append($mailbox, $message, $flags, $date, $binary); |
| | | } |
| | | |
| | | /** |