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

"Empty response" when calling getFolders() on Webklex\PHPIMAP\Client instance

Open schmidt-travixmedia opened this issue 1 year ago • 0 comments

Describe the bug Since we updated PHP-IMAP to version ~5 in a project, we get an error message when calling getFolders() method on a Webklex\PHPIMAP\Client instance. Before version 5 of PHP-IMAP (4.0, 4.1), everything worked fine. Temporary solution is to give the 'hierarchical' parameter value = false: ->getFolders($hierarchical = false) As I don't know if there may occur any side effects in later mail handling (e.g. move/delete messages), I create this bug report.

Infos from a similar bug report #362 did not help.

Used config I'm using https://oauth2-client.thephpleague.com/ with Microsoft Provider https://github.com/stevenmaguire/oauth2-microsoft in order to be able to use "OAuth2 client credentials flow" (see https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow )

Code to Reproduce Following 2 (simplified) functions are located in a example class 'MyClass':

    private function getAccessToken(): \League\OAuth2\Client\Token\AccessTokenInterface
    {
        $microsoftLoginHost = 'https://login.microsoftonline.com';
        $microsoftRessource = 'https://outlook.office.com';

        $azureTenantId = $this->getAzureTenantId();
        $azureClientId = $this->getAzureClientId();
        $azureClientSecret = $this->getAzureClientSecret();

        $provider = new \Stevenmaguire\OAuth2\Client\Provider\Microsoft([
            // required
            'clientId'                  => $azureClientId,
            'clientSecret'              => $azureClientSecret,
            // optional
            'urlAuthorize'              => $microsoftLoginHost . '/' . $azureTenantId . '/oauth2/v2.0/authorize',
            'urlAccessToken'            => $microsoftLoginHost . '/' . $azureTenantId . '/oauth2/v2.0/token',
            'urlResourceOwnerDetails'   => $microsoftRessource . '/api/v1.0/me',
            'defaultScopes'             => 'openid profile email offline_access ' . $microsoftRessource . '/IMAP.AccessAsUser.All ' . $microsoftRessource . '/User.Read',
        ]);

        // Access via client credentials flow: See https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
        $token = $provider->getAccessToken('client_credentials', [
            'scope' => 'https://outlook.office365.com/.default',
        ]);
        if (!$token) {
            throw new Exception('Error: Could not get a token.');
        }

        /** @var \League\OAuth2\Client\Token\AccessTokenInterface $token */
        return $token;
    }

    public function getPhpImapClient(): \Webklex\PHPIMAP\Client
    {
        $options = [
            'options' => [
                'soft_fail' => false,
                'rfc822' => true,
                'debug' => true,
            ],
        ];

        $cm = new \Webklex\PHPIMAP\ClientManager($options);

        $client = $cm->make([
            'host' => 'outlook.office365.com',
            'port' => '993',
            'encryption' => 'ssl',
            'validate_cert' => false,
            'username' => $this->getOutlook365AccountName(),
            'password' => $this->getAccessToken(),
            'protocol' => 'imap',
            'authentication' => "oauth",
        ]);

        $client->connect();

        return $client;
    }
try {
    $myObj = new MyClass();
    $phpImapClient = $myObj->getPhpImapClient();
    if ($phpImapClient->isConnected()) {

        echo "Status: Connected.\r\r";

//        $folders = $phpImapClient->getFolders(); // -> Exception
        $folders = $phpImapClient->getFolders($hierarchical = false); // Temporary solution
        
        echo "Mailboxes:\r\r";
        
        /** @var Folder $folder */
        foreach ($folders as $folder) {
            echo '- ' . $folder->name . "\r";
        }
        
        $phpImapClient->disconnect();
    }
    else {
        echo "Status: Not connected.\r";
    }
}
catch (Exception $exception) {
    if (isset($phpImapClient) && $phpImapClient instanceof Client) {
        $phpImapClient->disconnect();
    }
}

Expected behavior IMAP folders should be echo'ed:

Status: Connected.

Mailboxes:

- Archiv
- Aufgaben
- Entwürfe
- Gelöschte Elemente
- Gesendete Elemente
- Junk-E-Mail
- Kalender
- Kontakte
- Notizen
- a_folder
- another_folder
- Postausgang
- INBOX
- Verlauf der Unterhaltung

Actual behavior Real token values replaced by xxxxxxxxxxx...

<< * OK The Microsoft Exchange IMAP4 service is ready. [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==]
>> TAG1 AUTHENTICATE XOAUTH2 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=

<< TAG1 OK AUTHENTICATE completed.
Status: Connected.
>> TAG2 LIST "" "%"

<< * LIST (\HasNoChildren) "/" Archiv
<< * LIST (\HasNoChildren) "/" Aufgaben
<< * LIST (\HasNoChildren \Drafts) "/" Entw&APw-rfe
<< * LIST (\HasNoChildren \Trash) "/" "Gel&APY-schte Elemente"
<< * LIST (\HasNoChildren \Sent) "/" "Gesendete Elemente"
<< * LIST (\HasNoChildren \Junk) "/" Junk-E-Mail
<< * LIST (\HasNoChildren) "/" Kalender
<< * LIST (\HasChildren) "/" Kontakte
<< * LIST (\HasNoChildren) "/" Notizen
<< * LIST (\HasNoChildren) "/" a_folder
<< * LIST (\HasNoChildren) "/" another_folder
<< * LIST (\HasNoChildren) "/" Postausgang
<< * LIST (\Marked \HasNoChildren) "/" INBOX
<< * LIST (\HasChildren) "/" "Verlauf der Unterhaltung"
<< TAG2 OK LIST completed.
>> TAG3 LIST "" "Kontakte/%%"

<< TAG3 OK LIST completed.
>> TAG4 LOGOUT

<< * BYE Microsoft Exchange Server IMAP4 server signing off.
<< TAG4 OK LOGOUT completed.
Error occurred
Causes:
        - Empty response
Commands send:
        TAG3 LIST "" "Kontakte/%%"\r\n
Responses received:
        TAG3 OK LIST completed.\r\n
Error occurred

schmidt-travixmedia avatar Mar 21 '23 15:03 schmidt-travixmedia