2

我想从 gmails 的 imap 服务器检索电子邮件,但问题是来自服务器的响应是多行(如此处所示并且 fgets 只检索一行。

我试过使用 fgets、fread、socket_read 但它们都不起作用,所以要么我使用了错误的方法,要么错误地使用了这些方法。我也试过这个教程,但也没有用。如果有人可以帮助我,我将不胜感激。

谢谢,如果这是一个业余问题,我真的很抱歉。

代码:

<?php

$stuff = fsockopen('ssl://imap.gmail.com',993);
$reply = fgets($stuff,4096);
echo 'connection: '.$reply.'<br/>';

$request = fputs($stuff,"a1 LOGIN MyUserName Password\r\n");
$receive = socket_read($stuff, 4096);

echo 'login: '.$receive.'<br/>';


$request = fputs($stuff,"a2 EXAMINE INBOX\r\n");
$reply = '';

while(!feof($stuff))
    $reply .= fread($stuff, 4096);

echo $reply;



/*
$request = fputs($stuff,'a3 FETCH 1 BODY[]\r\n');
$reply = fgets($stuff);
echo $reply;
*/
?>

Max在下面的回答有效。这是我的实现。

private function Response($instructionNumber)
{
    $end_of_response = false;

    while (!$end_of_response)
    {
        $line = fgets($this->connection,self::responseSize);
        $response .= $line.'<br/>';

        if(preg_match("/$instructionNumber (OK|NO|BAD)/", $response,$responseCode))
            $end_of_response = true;
    }

    return array('code' => $responseCode[1],
        'response'=>$response);
}
4

2 回答 2

3

自从我写 PHP 以来已经有一段时间了,我对 IMAP 不太了解,但如果它是 NNTP 之类的东西,你的代码看起来有点像这样(在 SO 编辑器中写的,可能有问题):

$buffer = '';
function read_line($socket) {
    global $buffer;
    while (strpos($buffer, "\n") === false)
        $buffer .= fread($socket, 1024);

    $lineEnd = strpos($buffer, "\n");
    $line = substr($buffer, 0, $lineEnd-1);
    $buffer = substr($buffer, $lineEnd);

    return $line;
}

function send_line($socket, $line) {
    fwrite($socket, $line);
}

$socket = fsockopen('ssl://imap.gmail.com',993);
$welcome = read_line($socket);

send_line("a1 LOGIN MyUserName Password\r\n");
$reply = read_line($socket);

send_line("a2 EXAMINE INBOX\r\n");
while (($reply = trim(read_line($socket))) != '.') {
    echo $reply.PHP_EOL;
}

echo "Done";

基本概念是:

  • 始终缓冲所有传入数据。PHP 不能很好地处理行,所以自己进行拆分。
  • 不要随意阅读所有内容,但要知道会发生什么。您期望有一条欢迎行,LOGIN有一条回复,并EXAMINE INBOX一直输出数据,直到出现一个点,因此一旦看到就立即停止阅读。
  • 您很可能需要一个简单的函数来处理阅读。你甚至可以编写另一个函数来简化它:

function read_block($socket) {
    $block = '';
    while ('.' != trim($reply = read_line($socket)) {
        $block .= $reply;
    }
    return $block;
}
于 2013-03-18T11:50:42.403 回答
2

通常,当您收到您发送的标签的 OK/BAD/NO 响应时,您知道停止阅读。如果你发送a1 LOGIN ...你停止当你得到a1 OK/BAD/NO ...

于 2013-03-18T19:26:29.507 回答