php-imap icon indicating copy to clipboard operation
php-imap copied to clipboard

Exception when copy a message - empty response

Open martinkrivda opened this issue 1 year ago • 1 comments

Hi! First of all, thank you very much for this library.

Describe the bug I'm developing a Mail data collector. I'm using IBM HCL Domino server ( version 12.0.2. FP2 ) as a mail server (formerly Lotus Notes) and the IMAP protocol to connect to it. Upon initial observation, it appears to be functioning correctly.

I'm establishing a connection to the mailbox, retrieving the specified folder, analyzing the emails, and so on. But when I have to move the parsed message to another folder, there comes a problem: The Domino server uses an IMAP version that doesn't support the MOVE command. I thought that if I could use the MOVE, I could use copy & delete the same as in #239.

That worked, the message is copied to the correct folder, but for some reason, the library throws an error and I can't understand why.

>> TAG16 EXAMINE "Workarea"

<< * 0 EXISTS
<< * 0 RECENT
<< * OK [UIDVALIDITY 6] UIDs valid
<< * OK [UIDNEXT 1] Predicted next UID
<< * FLAGS (\Flagged \Seen \Answered \Deleted \Draft)
<< * OK [PERMANENTFLAGS ()] No permanent flags permitted
<< TAG16 OK [READ-ONLY] EXAMINE completed
Next UID: 1>> TAG17 LIST "" "*"

<< * LIST (\HasNoChildren) "\\" Backup
<< * LIST (\Noinferiors \HasNoChildren) "\\" Inbox
<< * LIST (\HasNoChildren) "\\" Sent
<< * LIST (\Noinferiors \HasNoChildren) "\\" Trash
<< * LIST (\HasNoChildren) "\\" Workarea
<< TAG17 OK LIST completed
>> TAG18 SELECT "Inbox"

<< * 1 EXISTS
<< * 0 RECENT
<< * OK [UIDVALIDITY 5] UIDs valid
<< * OK [UIDNEXT 39] Predicted next UID
<< * FLAGS (\Flagged \Seen \Answered \Deleted \Draft)
<< * OK [PERMANENTFLAGS (\Flagged \Seen \Answered \Deleted \Draft \*)] Permanent flags
<< TAG18 OK [READ-WRITE] SELECT completed
>> TAG19 UID COPY 38 "Workarea"

<< TAG19 OK [COPYUID 6 38 13] COPY completed
>> TAG20 SELECT "Workarea"

<< * 1 EXISTS
<< * 0 RECENT
<< * OK [UIDVALIDITY 6] UIDs valid
<< * OK [UIDNEXT 14] Predicted next UID
<< * FLAGS (\Flagged \Seen \Answered \Deleted \Draft)
<< * OK [PERMANENTFLAGS (\Flagged \Seen \Answered \Deleted \Draft \*)] Permanent flags
<< TAG20 OK [READ-WRITE] SELECT completed
>> TAG21 UID FETCH 1 (FLAGS)

<< TAG21 OK FETCH completed

Fatal error: Uncaught Webklex\PHPIMAP\Exceptions\ResponseException: Command failed to process:
Causes:
        - Empty response
Commands send:
        TAG21 UID FETCH 1 (FLAGS)\r\n
Responses received:
        TAG21 OK FETCH completed\r\n
Error occurred in C:\ISSIMS\cdc_dev\vendor\webklex\php-imap\src\Exceptions\ResponseException.php on
line 53

Webklex\PHPIMAP\Exceptions\ResponseException: Command failed to process:
Causes:
        - Empty response
Commands send:
        TAG21 UID FETCH 1 (FLAGS)\r\n
Responses received:
        TAG21 OK FETCH completed\r\n
Error occurred in C:\ISSIMS\cdc_dev\vendor\webklex\php-imap\src\Exceptions\ResponseException.php on
line 53

it seems that the $next_uid variable has a value 1 but should have 13, so a message with UID 1 doesn't exist in the folder Workarea

 $status = $this->client->getConnection()->examineFolder($folder_path)->validatedData();

        if (isset($status["uidnext"])) {
            $next_uid = $status["uidnext"];
            echo "Next UID: " . $next_uid;
            if ((int)$next_uid <= 0) {
                return null;
            }

            /** @var Folder $folder */
            $folder = $this->client->getFolderByPath($folder_path);

            $this->client->openFolder($this->folder_path);
            if ($this->client->getConnection()->copyMessage($folder->path, $this->getSequenceId(), null, $this->sequence)->validatedData()) {
                return $this->fetchNewMail($folder, $next_uid, "copied", $expunge);
            }
        }

Used config

    $options = [
        'options' => [
            'soft_fail' => true,
            'rfc822' => true,
            'debug' => true,
        ],
    ];

    $cm = new ClientManager($options);

    $protocol = 'imap';
    if ($encryption === 'notls') {
        //$protocol = 'legacy-imap';
    }

    $client = $cm->make([
        'host'          => $host,
        'port'          => $port,
        'encryption'    => 'false',
        'validate_cert' => 'false',
        'protocol'      => 'imap',
        'username'      => $username,
        'password'      => $password,
        'authentication' => 'plain',
        "extensions" => [] // auto. fetch these extensions 
    ]);

Code to Reproduce The troubling code section that produces the reported bug.

// Select the mailbox/folder
$folder = $imap->getFolderByName("Inbox");
$folderToMoveTo = $imap->getFolderByName('Workarea');

$emails = $folder->messages()->all()->markAsRead()->setFetchBody(false)->setFetchFlags(false)->softFail()->get();
// Loop through each email
foreach ($emails as $email) {
    try {
        $email->move($folderToMoveTo->path, false);
    } catch (ImapServerErrorException $e) {
        echo "MOVE command does not exist";
        // Copy the message to the destination folder
        $email->copy($folderToMoveTo->path, false); - it fails
        $email->delete();
    }
}

Expected behavior I need to move a message from one directory to another.

Server (please complete the following information):

  • OS: Windows Server 2012 R2
  • PHP: PHP 8.1.19 (cli) (built: May 11 2023 12:00:16) (NTS Visual C++ 2019 x64)
  • Version: V5.5.0
  • Provider: HCL Domino

martinkrivda avatar Apr 05 '24 19:04 martinkrivda

Hi @martinkrivda , thank you very much for this well written issue report. This looks indeed odd - but looking at the log:

>> TAG21 UID FETCH 1 (FLAGS)
<< TAG21 OK FETCH completed

There aren't any flag values - this causes the Empty response exception. The reason, it's expected that each message has at least one Flag, but that's clearly not the case.

The question is - is this considered "normal"? If I go ahead and allow an empty flag collection, am I missing perhaps errors I otherwise would have caught?

Best regards & happy coding,

Webklex avatar Jan 17 '25 22:01 Webklex

@Webklex hi. I have the same error when calling move() method using outlook (o365). It happens randomly but I get this error a lot. It happens more with large folders (thousands of mails). it would solve the issue and would be great for performance if move had the option not to do the fetchNewMail. is there a way to prevent this ? what is isset($status["uidnext"]) ?

Error when:

$folder->query()->getMessage($uid)->move($dstFolderName);

Trace:

{
file: "E:\\www\\sls\\vendor\\webklex\\php-imap\\src\\Message.php",
line: 251,
type: "->",
class: "Webklex\\PHPIMAP\\Message",
function: "parseHeader"
},
{
file: "E:\\www\\sls\\vendor\\webklex\\php-imap\\src\\Query\\Query.php",
line: 473,
type: "->",
class: "Webklex\\PHPIMAP\\Message",
function: "__construct"
},
{
file: "E:\\www\\sls\\vendor\\webklex\\php-imap\\src\\Message.php",
line: 1100,
type: "->",
class: "Webklex\\PHPIMAP\\Query\\Query",
function: "getMessage"
},
{
file: "E:\\www\\sls\\vendor\\webklex\\php-imap\\src\\Message.php",
line: 1061,
type: "->",
class: "Webklex\\PHPIMAP\\Message",
function: "fetchNewMail"
},

jupitern avatar Aug 20 '25 09:08 jupitern

I solved this problem by moving emails to a folder that is created dynamically for each month as an archive, e.g.: archive-2025-07, archive-2025-08. Thanks to this, there is a limited number of messages in the folder and the move operation works.

ziggurad avatar Aug 20 '25 10:08 ziggurad