public function top($msgNum, $chars = 0)
{
$uid = $this->options->uidReferencing ? self::UID : self::NO_UID;
if ($this->state != self::STATE_SELECTED && $this->state != self::STATE_SELECTED_READONLY) {
throw new ezcMailTransportException("Can't call top() on the IMAP transport when a mailbox is not selected.");
}
$tag = $this->getNextTag();
if ($chars === 0) {
$command = "{$tag} {$uid}FETCH {$msgNum} (BODY.PEEK[HEADER] BODY.PEEK[TEXT])";
} else {
$command = "{$tag} {$uid}FETCH {$msgNum} (BODY.PEEK[HEADER] BODY.PEEK[TEXT]<0.{$chars}>)";
}
$this->connection->sendData($command);
if ($this->options->uidReferencing) {
// special case (BUG?) where "UID FETCH {$msgNum}" returns nothing
$response = trim($this->connection->getLine());
if ($this->responseType($response) === self::RESPONSE_OK) {
throw new ezcMailTransportException("The IMAP server could not fetch the message '{$msgNum}': {$response}.");
}
} else {
$response = $this->getResponse('FETCH (');
}
$message = "";
if (strpos($response, 'FETCH (') !== false) {
// Added hack for issue #14360: problems with $imap->top() command in gmail.
if ($this->serverType === self::SERVER_GIMAP) {
// Google IMAP servers return the body first, then the headers (!)
$bytesToRead = $this->getMessageSectionSize($response);
$response = "";
while ($bytesToRead >= 0) {
$data = $this->connection->getLine();
$lastResponse = $data;
$bytesToRead -= strlen($data);
// in case reading too much and the string "BODY[HEADER] {size}"
// is at the end of the last line
if ($bytesToRead <= 0) {
if ($bytesToRead < 0) {
$lastResponse = substr($data, $bytesToRead);
$data = substr($data, 0, strlen($data) + $bytesToRead);
}
}
$message .= $data;
}
// Read the headers
$headers = '';
$response = $this->connection->getLine();
$bytesToRead = $this->getMessageSectionSize($lastResponse);
$response = $this->connection->getLine();
while (strpos($response, $tag) === false) {
$headers .= $response;
$response = $this->connection->getLine();
}
$headers = trim($headers, ")\r\n");
// Append the body AFTER the headers as it should be
$message = $headers . "\r\n\r\n" . $message;
} else {
// Other IMAP servers return the headers first, then the body
$response = "";
while (strpos($response, 'BODY[TEXT]') === false) {
$message .= $response;
$response = $this->connection->getLine();
}
$response = $this->connection->getLine();
while (strpos($response, $tag) === false) {
$message .= $response;
$response = $this->connection->getLine();
}
}
}
// skip the OK response ("{$tag} OK Fetch completed.")
$response = trim($this->getResponse($tag, $response));
if ($this->responseType($response) != self::RESPONSE_OK) {
throw new ezcMailTransportException("The IMAP server could not fetch the message '{$msgNum}': {$response}.");
}
return $message;
}