From 947a0360a08107471c32fa91401ba59a3fbbb340 Mon Sep 17 00:00:00 2001 From: johannes Date: Wed, 2 Apr 2025 11:10:31 +0200 Subject: [PATCH] php-imap has no ability to accept oauth token, and probably won't receive it due to the fact that it has been unbundled as of php 8.4. This is resolved by using the javanile php-imap2 implementation, which has the ability to authenticate via an oauth token. To use OAuth authentication: Fill the password field with the token. Supply the OP_XOAUTH2 constant to the \Mailbox->setConnectionArgs(). P.S.: Also see the following comment by the author of php-imap2, ddeboer/imap#443 (comment) --- README.md | 9 +- composer.json | 1 + psalm.baseline.xml | 4 +- src/PhpImap/DataPartInfo.php | 4 +- src/PhpImap/Imap.php | 217 ++++++++++++------------- src/PhpImap/Mailbox.php | 84 +--------- tests/unit/LiveMailboxIssue501Test.php | 2 +- tests/unit/MailboxTest.php | 2 +- 8 files changed, 122 insertions(+), 201 deletions(-) diff --git a/README.md b/README.md index 71cd761b..16e589ab 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ By default, this library uses random filenames for attachments as identical file $mailbox = new PhpImap\Mailbox( '{imap.gmail.com:993/imap/ssl}INBOX', // IMAP server and mailbox folder 'some@gmail.com', // Username for the before configured mailbox - '*********', // Password for the before configured username + '*********', // Password or token for the before configured username __DIR__, // Directory, where attachments will be saved (optional) 'UTF-8', // Server encoding (optional) true, // Trim leading/ending whitespaces of IMAP path (optional) @@ -94,14 +94,9 @@ $mailbox = new PhpImap\Mailbox( $mailbox->setConnectionArgs( CL_EXPUNGE // expunge deleted mails upon mailbox close | OP_SECURE // don't do non-secure authentication + | OP_XOAUTH2 // set OP_XOAUTH2 connection argument if supplied password is a OAuth token. ); -try { - $mailbox->setOAuthToken('TheOAuthAccessToken'); -} catch (Exception $ex) { - die('Authentication using OAuth failed! Error: '.$ex->getMessage()); -} - try { // Get all emails (messages) // PHP.net imap_search criteria: http://php.net/manual/en/function.imap-search.php diff --git a/composer.json b/composer.json index 9b44d8e2..3c61c058 100644 --- a/composer.json +++ b/composer.json @@ -24,6 +24,7 @@ }, "require": { "php": "^7.4 || ^8.0", + "javanile/php-imap2": "^0.1.10", "ext-fileinfo": "*", "ext-iconv": "*", "ext-imap": "*", diff --git a/psalm.baseline.xml b/psalm.baseline.xml index 0983eba9..12cc8fb8 100644 --- a/psalm.baseline.xml +++ b/psalm.baseline.xml @@ -22,9 +22,7 @@ $element->text $element->text - - setOAuthToken - getOAuthToken + setConnectionRetry setConnectionRetryDelay setExpungeOnDisconnect diff --git a/src/PhpImap/DataPartInfo.php b/src/PhpImap/DataPartInfo.php index 68841016..55a628aa 100644 --- a/src/PhpImap/DataPartInfo.php +++ b/src/PhpImap/DataPartInfo.php @@ -92,10 +92,10 @@ public function decodeAfterFetch(string $data): string { switch ($this->encoding) { case ENC8BIT: - $this->data = \imap_utf8((string) $data); + $this->data = \imap2_utf8((string) $data); break; case ENCBINARY: - $this->data = \imap_binary((string) $data); + $this->data = \imap2_binary((string) $data); break; case ENCBASE64: $this->data = \base64_decode((string) $data, false); diff --git a/src/PhpImap/Imap.php b/src/PhpImap/Imap.php index 655c1dc8..bfaa2ab0 100644 --- a/src/PhpImap/Imap.php +++ b/src/PhpImap/Imap.php @@ -82,12 +82,12 @@ public static function append( string $options = null, string $internal_date = null ): bool { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors $imap_stream = self::EnsureConnection($imap_stream, __METHOD__, 1); if (null !== $options && null !== $internal_date) { - $result = \imap_append( + $result = \imap2_append( $imap_stream, $mailbox, $message, @@ -95,13 +95,13 @@ public static function append( $internal_date ); } elseif (null !== $options) { - $result = \imap_append($imap_stream, $mailbox, $message, $options); + $result = \imap2_append($imap_stream, $mailbox, $message, $options); } else { - $result = \imap_append($imap_stream, $mailbox, $message); + $result = \imap2_append($imap_stream, $mailbox, $message); } if (false === $result) { - throw new UnexpectedValueException('Could not append message to mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_append')); + throw new UnexpectedValueException('Could not append message to mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_append')); } return $result; @@ -115,16 +115,16 @@ public static function body( int $msg_number, int $options = 0 ): string { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_body( + $result = \imap2_body( self::EnsureConnection($imap_stream, __METHOD__, 1), $msg_number, $options ); if (false === $result) { - throw new UnexpectedValueException('Could not fetch message body from mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_body')); + throw new UnexpectedValueException('Could not fetch message body from mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_body')); } return $result; @@ -135,12 +135,12 @@ public static function body( */ public static function check($imap_stream): object { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_check(self::EnsureConnection($imap_stream, __METHOD__, 1)); + $result = \imap2_check(self::EnsureConnection($imap_stream, __METHOD__, 1)); if (false === $result) { - throw new UnexpectedValueException('Could not check imap mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_check')); + throw new UnexpectedValueException('Could not check imap mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_check')); } /** @var object */ @@ -159,9 +159,9 @@ public static function clearflag_full( string $flag, int $options = 0 ): bool { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_clearflag_full( + $result = \imap2_clearflag_full( self::EnsureConnection($imap_stream, __METHOD__, 1), self::encodeStringToUtf7Imap(static::EnsureRange( $sequence, @@ -174,7 +174,7 @@ public static function clearflag_full( ); if (!$result) { - throw new UnexpectedValueException('Could not clear flag on messages!', 0, self::HandleErrors(\imap_errors(), 'imap_clearflag_full')); + throw new UnexpectedValueException('Could not clear flag on messages!', 0, self::HandleErrors(\imap2_errors(), 'imap_clearflag_full')); } return $result; @@ -189,12 +189,12 @@ public static function clearflag_full( */ public static function close($imap_stream, int $flag = 0): bool { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors /** @var int */ $flag = $flag; - $result = \imap_close(self::EnsureConnection($imap_stream, __METHOD__, 1), $flag); + $result = \imap2_close(self::EnsureConnection($imap_stream, __METHOD__, 1), $flag); if (false === $result) { $message = 'Could not close imap connection'; @@ -204,7 +204,7 @@ public static function close($imap_stream, int $flag = 0): bool } $message .= '!'; - throw new UnexpectedValueException($message, 0, self::HandleErrors(\imap_errors(), 'imap_close')); + throw new UnexpectedValueException($message, 0, self::HandleErrors(\imap2_errors(), 'imap_close')); } return $result; @@ -217,15 +217,15 @@ public static function close($imap_stream, int $flag = 0): bool */ public static function createmailbox($imap_stream, string $mailbox): bool { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_createmailbox( + $result = \imap2_createmailbox( self::EnsureConnection($imap_stream, __METHOD__, 1), static::encodeStringToUtf7Imap($mailbox) ); if (false === $result) { - throw new UnexpectedValueException('Could not create mailbox!', 0, self::HandleErrors(\imap_errors(), 'createmailbox')); + throw new UnexpectedValueException('Could not create mailbox!', 0, self::HandleErrors(\imap2_errors(), 'createmailbox')); } return $result; @@ -253,16 +253,16 @@ public static function delete( 1 )); - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_delete( + $result = \imap2_delete( self::EnsureConnection($imap_stream, __METHOD__, 1), $msg_number, $options ); if (false === $result) { - throw new UnexpectedValueException('Could not delete message from mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_delete')); + throw new UnexpectedValueException('Could not delete message from mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_delete')); } return $result; @@ -275,15 +275,15 @@ public static function delete( */ public static function deletemailbox($imap_stream, string $mailbox): bool { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_deletemailbox( + $result = \imap2_deletemailbox( self::EnsureConnection($imap_stream, __METHOD__, 1), static::encodeStringToUtf7Imap($mailbox) ); if (false === $result) { - throw new UnexpectedValueException('Could not delete mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_deletemailbox')); + throw new UnexpectedValueException('Could not delete mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_deletemailbox')); } return $result; @@ -296,14 +296,14 @@ public static function deletemailbox($imap_stream, string $mailbox): bool */ public static function expunge($imap_stream): bool { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_expunge( + $result = \imap2_expunge( self::EnsureConnection($imap_stream, __METHOD__, 1) ); if (false === $result) { - throw new UnexpectedValueException('Could not expunge messages from mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_expunge')); + throw new UnexpectedValueException('Could not expunge messages from mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_expunge')); } return $result; @@ -322,9 +322,9 @@ public static function fetch_overview( $sequence, int $options = 0 ): array { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_fetch_overview( + $result = \imap2_fetch_overview( self::EnsureConnection($imap_stream, __METHOD__, 1), self::encodeStringToUtf7Imap(self::EnsureRange( $sequence, @@ -336,7 +336,7 @@ public static function fetch_overview( ); if (false === $result) { - throw new UnexpectedValueException('Could not fetch overview for message from mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_fetch_overview')); + throw new UnexpectedValueException('Could not fetch overview for message from mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_fetch_overview')); } /** @psalm-var list */ @@ -357,9 +357,9 @@ public static function fetchbody( throw new InvalidArgumentException('Argument 3 passed to '.__METHOD__.'() must be a string or integer, '.\gettype($section).' given!'); } - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_fetchbody( + $result = \imap2_fetchbody( self::EnsureConnection($imap_stream, __METHOD__, 1), $msg_number, self::encodeStringToUtf7Imap((string) $section), @@ -367,7 +367,7 @@ public static function fetchbody( ); if (false === $result) { - throw new UnexpectedValueException('Could not fetch message body from mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_fetchbody')); + throw new UnexpectedValueException('Could not fetch message body from mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_fetchbody')); } return $result; @@ -381,16 +381,16 @@ public static function fetchheader( int $msg_number, int $options = 0 ): string { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_fetchheader( + $result = \imap2_fetchheader( self::EnsureConnection($imap_stream, __METHOD__, 1), $msg_number, $options ); if (false === $result) { - throw new UnexpectedValueException('Could not fetch message header from mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_fetchheader')); + throw new UnexpectedValueException('Could not fetch message header from mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_fetchheader')); } return $result; @@ -406,16 +406,16 @@ public static function fetchstructure( int $msg_number, int $options = 0 ): object { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_fetchstructure( + $result = \imap2_fetchstructure( self::EnsureConnection($imap_stream, __METHOD__, 1), $msg_number, $options ); if (false === $result) { - throw new UnexpectedValueException('Could not fetch message structure from mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_fetchstructure')); + throw new UnexpectedValueException('Could not fetch message structure from mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_fetchstructure')); } /** @psalm-var PARTSTRUCTURE */ @@ -431,15 +431,15 @@ public static function get_quotaroot( $imap_stream, string $quota_root ): array { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_get_quotaroot( + $result = \imap2_get_quotaroot( self::EnsureConnection($imap_stream, __METHOD__, 1), self::encodeStringToUtf7Imap($quota_root) ); if (false === $result) { - throw new UnexpectedValueException('Could not quota for mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_get_quotaroot')); + throw new UnexpectedValueException('Could not quota for mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_get_quotaroot')); } return $result; @@ -457,16 +457,16 @@ public static function getmailboxes( string $ref, string $pattern ): array { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_getmailboxes( + $result = \imap2_getmailboxes( self::EnsureConnection($imap_stream, __METHOD__, 1), $ref, $pattern ); if (false === $result) { - $errors = \imap_errors(); + $errors = \imap2_errors(); if (false === $errors) { /* @@ -476,7 +476,7 @@ public static function getmailboxes( return []; } - throw new UnexpectedValueException('Call to imap_getmailboxes() with supplied arguments returned false, not array!', 0, self::HandleErrors(\imap_errors(), 'imap_getmailboxes')); + throw new UnexpectedValueException('Call to imap_getmailboxes() with supplied arguments returned false, not array!', 0, self::HandleErrors(\imap2_errors(), 'imap_getmailboxes')); } /** @psalm-var list */ @@ -495,16 +495,16 @@ public static function getsubscribed( string $ref, string $pattern ): array { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_getsubscribed( + $result = \imap2_getsubscribed( self::EnsureConnection($imap_stream, __METHOD__, 1), $ref, $pattern ); if (false === $result) { - throw new UnexpectedValueException('Call to imap_getsubscribed() with supplied arguments returned false, not array!', 0, self::HandleErrors(\imap_errors(), 'imap_getsubscribed')); + throw new UnexpectedValueException('Call to imap_getsubscribed() with supplied arguments returned false, not array!', 0, self::HandleErrors(\imap2_errors(), 'imap_getsubscribed')); } /** @psalm-var list */ @@ -516,14 +516,14 @@ public static function getsubscribed( */ public static function headers($imap_stream): array { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_headers( + $result = \imap2_headers( self::EnsureConnection($imap_stream, __METHOD__, 1) ); if (false === $result) { - throw new UnexpectedValueException('Could not fetch headers from mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_headers')); + throw new UnexpectedValueException('Could not fetch headers from mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_headers')); } return $result; @@ -538,16 +538,16 @@ public static function headers($imap_stream): array */ public static function listOfMailboxes($imap_stream, string $ref, string $pattern): array { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_list( + $result = \imap2_list( self::EnsureConnection($imap_stream, __METHOD__, 1), static::encodeStringToUtf7Imap($ref), static::encodeStringToUtf7Imap($pattern) ); if (false === $result) { - throw new UnexpectedValueException('Could not list folders mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_list')); + throw new UnexpectedValueException('Could not list folders mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_list')); } return \array_values(\array_map( @@ -580,7 +580,7 @@ static function (string $folder): string { */ public static function mail_compose(array $envelope, array $body): string { - return \imap_mail_compose($envelope, $body); + return \imap2_mail_compose($envelope, $body); } /** @@ -595,9 +595,9 @@ public static function mail_copy( string $mailbox, int $options = 0 ): bool { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_mail_copy( + $result = \imap2_mail_copy( self::EnsureConnection($imap_stream, __METHOD__, 1), static::encodeStringToUtf7Imap(self::EnsureRange( $msglist, @@ -610,7 +610,7 @@ public static function mail_copy( ); if (false === $result) { - throw new UnexpectedValueException('Could not copy messages!', 0, self::HandleErrors(\imap_errors(), 'imap_mail_copy')); + throw new UnexpectedValueException('Could not copy messages!', 0, self::HandleErrors(\imap2_errors(), 'imap_mail_copy')); } return $result; @@ -628,9 +628,9 @@ public static function mail_move( string $mailbox, int $options = 0 ): bool { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_mail_move( + $result = \imap2_mail_move( self::EnsureConnection($imap_stream, __METHOD__, 1), static::encodeStringToUtf7Imap(self::EnsureRange( $msglist, @@ -643,7 +643,7 @@ public static function mail_move( ); if (false === $result) { - throw new UnexpectedValueException('Could not move messages!', 0, self::HandleErrors(\imap_errors(), 'imap_mail_move')); + throw new UnexpectedValueException('Could not move messages!', 0, self::HandleErrors(\imap2_errors(), 'imap_mail_move')); } return $result; @@ -654,14 +654,14 @@ public static function mail_move( */ public static function mailboxmsginfo($imap_stream): stdClass { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_mailboxmsginfo( + $result = \imap2_mailboxmsginfo( self::EnsureConnection($imap_stream, __METHOD__, 1) ); if (false === $result) { - throw new UnexpectedValueException('Could not fetch mailboxmsginfo from mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_mailboxmsginfo')); + throw new UnexpectedValueException('Could not fetch mailboxmsginfo from mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_mailboxmsginfo')); } return $result; @@ -672,12 +672,12 @@ public static function mailboxmsginfo($imap_stream): stdClass */ public static function num_msg($imap_stream): int { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_num_msg(self::EnsureConnection($imap_stream, __METHOD__, 1)); + $result = \imap2_num_msg(self::EnsureConnection($imap_stream, __METHOD__, 1)); if (false === $result) { - throw new UnexpectedValueException('Could not get the number of messages in the mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_num_msg')); + throw new UnexpectedValueException('Could not get the number of messages in the mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_num_msg')); } return $result; @@ -704,12 +704,11 @@ public static function open( } } - \imap_errors(); // flush errors - - $result = @\imap_open($mailbox, $username, $password, $options, $n_retries, $params); + \imap2_errors(); // flush errors + $result = @\imap2_open($mailbox, $username, $password, $options, $n_retries, $params); if (!$result) { - throw new ConnectionException(\imap_errors() ?: []); + throw new ConnectionException(\imap2_errors() ?: []); } return $result; @@ -722,7 +721,7 @@ public static function open( */ public static function ping($imap_stream): bool { - return (\is_resource($imap_stream) || $imap_stream instanceof \IMAP\Connection) && \imap_ping($imap_stream); + return (\is_resource($imap_stream) || $imap_stream instanceof \Javanile\IMAP2\Connection) && \imap2_ping($imap_stream); } /** @@ -740,12 +739,12 @@ public static function renamemailbox( $old_mbox = static::encodeStringToUtf7Imap($old_mbox); $new_mbox = static::encodeStringToUtf7Imap($new_mbox); - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_renamemailbox($imap_stream, $old_mbox, $new_mbox); + $result = \imap2_renamemailbox($imap_stream, $old_mbox, $new_mbox); if (!$result) { - throw new UnexpectedValueException('Could not rename mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_renamemailbox')); + throw new UnexpectedValueException('Could not rename mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_renamemailbox')); } return $result; @@ -766,12 +765,12 @@ public static function reopen( $mailbox = static::encodeStringToUtf7Imap($mailbox); - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_reopen($imap_stream, $mailbox, $options, $n_retries); + $result = \imap2_reopen($imap_stream, $mailbox, $options, $n_retries); if (!$result) { - throw new UnexpectedValueException('Could not reopen mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_reopen')); + throw new UnexpectedValueException('Could not reopen mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_reopen')); } return $result; @@ -794,12 +793,12 @@ public static function savebody( $file = \is_string($file) ? $file : self::EnsureResource($file, __METHOD__, 2); $part_number = self::encodeStringToUtf7Imap($part_number); - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_savebody($imap_stream, $file, $msg_number, $part_number, $options); + $result = \imap2_savebody($imap_stream, $file, $msg_number, $part_number, $options); if (!$result) { - throw new UnexpectedValueException('Could not reopen mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_savebody')); + throw new UnexpectedValueException('Could not reopen mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_savebody')); } return $result; @@ -819,7 +818,7 @@ public static function search( string $charset = null, bool $encodeCriteriaAsUtf7Imap = false ): array { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors $imap_stream = static::EnsureConnection($imap_stream, __METHOD__, 1); @@ -828,18 +827,18 @@ public static function search( } if (\is_string($charset)) { - $result = \imap_search( + $result = \imap2_search( $imap_stream, $criteria, $options, static::encodeStringToUtf7Imap($charset) ); } else { - $result = \imap_search($imap_stream, $criteria, $options); + $result = \imap2_search($imap_stream, $criteria, $options); } if (!$result) { - $errors = \imap_errors(); + $errors = \imap2_errors(); if (false === $errors) { /* @@ -868,9 +867,9 @@ public static function setflag_full( string $flag, int $options = NIL ): bool { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_setflag_full( + $result = \imap2_setflag_full( self::EnsureConnection($imap_stream, __METHOD__, 1), self::encodeStringToUtf7Imap(static::EnsureRange( $sequence, @@ -883,7 +882,7 @@ public static function setflag_full( ); if (!$result) { - throw new UnexpectedValueException('Could not set flag on messages!', 0, self::HandleErrors(\imap_errors(), 'imap_setflag_full')); + throw new UnexpectedValueException('Could not set flag on messages!', 0, self::HandleErrors(\imap2_errors(), 'imap_setflag_full')); } return $result; @@ -909,7 +908,7 @@ public static function sort( string $search_criteria = null, string $charset = null ): array { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors $imap_stream = self::EnsureConnection($imap_stream, __METHOD__, 1); @@ -925,7 +924,7 @@ public static function sort( } if (null !== $search_criteria && null !== $charset) { - $result = \imap_sort( + $result = \imap2_sort( $imap_stream, $criteria, $reverse, @@ -934,7 +933,7 @@ public static function sort( self::encodeStringToUtf7Imap($charset) ); } elseif (null !== $search_criteria) { - $result = \imap_sort( + $result = \imap2_sort( $imap_stream, $criteria, $reverse, @@ -942,7 +941,7 @@ public static function sort( self::encodeStringToUtf7Imap($search_criteria) ); } else { - $result = \imap_sort( + $result = \imap2_sort( $imap_stream, $criteria, $reverse, @@ -951,7 +950,7 @@ public static function sort( } if (false === $result) { - throw new UnexpectedValueException('Could not sort messages!', 0, self::HandleErrors(\imap_errors(), 'imap_sort')); + throw new UnexpectedValueException('Could not sort messages!', 0, self::HandleErrors(\imap2_errors(), 'imap_sort')); } /** @psalm-var list */ @@ -969,12 +968,12 @@ public static function status($imap_stream, string $mailbox, int $options): stdC $mailbox = static::encodeStringToUtf7Imap($mailbox); - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_status($imap_stream, $mailbox, $options); + $result = \imap2_status($imap_stream, $mailbox, $options); if (!$result) { - throw new UnexpectedValueException('Could not get status of mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_status')); + throw new UnexpectedValueException('Could not get status of mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_status')); } return $result; @@ -989,12 +988,12 @@ public static function subscribe($imap_stream, string $mailbox): void $mailbox = static::encodeStringToUtf7Imap($mailbox); - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_subscribe($imap_stream, $mailbox); + $result = \imap2_subscribe($imap_stream, $mailbox); if (false === $result) { - throw new UnexpectedValueException('Could not subscribe to mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_subscribe')); + throw new UnexpectedValueException('Could not subscribe to mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_subscribe')); } } @@ -1007,18 +1006,18 @@ public static function timeout( int $timeout_type, int $timeout = -1 ) { - \imap_errors(); // flush errors + \imap2_errors(); // flush errors /** @var int */ $timeout_type = $timeout_type; - $result = \imap_timeout( + $result = \imap2_timeout( $timeout_type, $timeout ); if (false === $result) { - throw new UnexpectedValueException('Could not get/set connection timeout!', 0, self::HandleErrors(\imap_errors(), 'imap_timeout')); + throw new UnexpectedValueException('Could not get/set connection timeout!', 0, self::HandleErrors(\imap2_errors(), 'imap_timeout')); } return $result; @@ -1035,12 +1034,12 @@ public static function unsubscribe( $mailbox = static::encodeStringToUtf7Imap($mailbox); - \imap_errors(); // flush errors + \imap2_errors(); // flush errors - $result = \imap_unsubscribe($imap_stream, $mailbox); + $result = \imap2_unsubscribe($imap_stream, $mailbox); if (false === $result) { - throw new UnexpectedValueException('Could not unsubscribe from mailbox!', 0, self::HandleErrors(\imap_errors(), 'imap_unsubscribe')); + throw new UnexpectedValueException('Could not unsubscribe from mailbox!', 0, self::HandleErrors(\imap2_errors(), 'imap_unsubscribe')); } } @@ -1091,7 +1090,7 @@ public static function decodeStringFromUtf7ImapToUtf8(string $str): string */ private static function EnsureResource($maybe, string $method, int $argument) { - if (!$maybe || (!\is_resource($maybe) && !$maybe instanceof \IMAP\Connection)) { + if (!$maybe || (!\is_resource($maybe) && !$maybe instanceof \Javanile\IMAP2\Connection)) { throw new InvalidArgumentException('Argument '.(string) $argument.' passed to '.$method.' must be a valid resource!'); } diff --git a/src/PhpImap/Mailbox.php b/src/PhpImap/Mailbox.php index 936f8ed9..500e75c4 100644 --- a/src/PhpImap/Mailbox.php +++ b/src/PhpImap/Mailbox.php @@ -99,6 +99,7 @@ class Mailbox | OP_SILENT // 16 | OP_PROTOTYPE // 32 | OP_SECURE // 256 + | OP_XOAUTH2 // 512, constant from Javaline\php-imap2 ; /** @var string */ @@ -113,9 +114,6 @@ class Mailbox /** @var string */ protected $imapPassword; - /** @var string|null */ - protected $imapOAuthAccessToken = null; - /** @var int */ protected $imapSearchOption = SE_UID; @@ -190,41 +188,6 @@ public function __destruct() $this->disconnect(); } - /** - * Sets / Changes the OAuth Token for the authentication. - * - * @param string $access_token OAuth token from your application (eg. Google Mail) - * - * @return void - * - * @throws InvalidArgumentException If no access token is provided - * @throws Exception If OAuth authentication was unsuccessful - */ - public function setOAuthToken($access_token) - { - if (empty(\trim($access_token))) { - throw new InvalidParameterException('setOAuthToken() requires an access token as parameter!'); - } - - $this->imapOAuthAccessToken = \trim($access_token); - - try { - $this->_oauthAuthentication(); - } catch (Exception $ex) { - throw new Exception('Invalid OAuth token provided. Error: '.$ex->getMessage()); - } - } - - /** - * Gets the OAuth Token for the authentication. - * - * @return string|null $access_token OAuth Access Token - */ - public function getOAuthToken() - { - return $this->imapOAuthAccessToken; - } - /** * Sets / Changes the path delimiter character (Supported values: '.', '/'). * @@ -515,7 +478,7 @@ public function getImapStream(bool $forceConnection = true) public function hasImapStream(): bool { try { - return (\is_resource($this->imapStream) || $this->imapStream instanceof \IMAP\Connection) && \imap_ping($this->imapStream); + return (\is_object($this->imapStream) || $this->imapStream instanceof \Javanile\IMAP2\Connection) && \imap2_ping($this->imapStream); } catch (\Error $exception) { // From PHP 8.1.10 imap_ping() on a closed stream throws a ValueError. See #680. $valueError = '\ValueError'; @@ -536,7 +499,7 @@ public function hasImapStream(): bool */ public function encodeStringToUtf7Imap(string $str): string { - return imap_utf7_encode($str); + return imap2_utf7_encode($str); } /** @@ -548,7 +511,7 @@ public function encodeStringToUtf7Imap(string $str): string */ public function decodeStringFromUtf7ImapToUtf8(string $str): string { - $out = imap_utf7_decode($str); + $out = imap2_utf7_decode($str); if (!\is_string($out)) { throw new UnexpectedValueException('mb_convert_encoding($str, \'UTF-8\', \'UTF7-IMAP\') could not convert $str'); @@ -1176,7 +1139,7 @@ public function getMailHeader(int $mailId): IncomingMailHeader * sender?:HOSTNAMEANDADDRESS * } */ - $head = \imap_rfc822_parse_headers($headersRaw); + $head = \imap2_rfc822_parse_headers($headersRaw); if (isset($head->date) && !\is_string($head->date)) { throw new UnexpectedValueException('date property of parsed headers corresponding to argument 1 passed to '.__METHOD__.'() was present but not a string!'); @@ -1527,7 +1490,7 @@ public function decodeMimeStr(string $string): string { $newString = ''; /** @var list|false */ - $elements = \imap_mime_header_decode($string); + $elements = \imap2_mime_header_decode($string); if (false === $elements) { return $string; @@ -1714,41 +1677,6 @@ protected function lowercase_mb_list_encodings(): array return $lowercase_encodings; } - - /** - * Builds an OAuth2 authentication string for the given email address and access token. - * - * @return string $access_token Formatted OAuth access token - */ - protected function _constructAuthString() - { - return \base64_encode("user=$this->imapLogin\1auth=Bearer $this->imapOAuthAccessToken\1\1"); - } - - /** - * Authenticates the IMAP client with the OAuth access token. - * - * @return void - * - * @throws Exception If any error occured - */ - protected function _oauthAuthentication() - { - $oauth_command = 'A AUTHENTICATE XOAUTH2 '.$this->_constructAuthString(); - - $oauth_result = \fwrite($this->getImapStream(), $oauth_command); - - if (false === $oauth_result) { - throw new Exception('Could not authenticate using OAuth!'); - } - - try { - $this->checkMailbox(); - } catch (\Throwable $ex) { - throw new Exception('OAuth authentication failed! IMAP Error: '.$ex->getMessage()); - } - } - /** @return resource */ protected function initImapStreamWithRetry() { diff --git a/tests/unit/LiveMailboxIssue501Test.php b/tests/unit/LiveMailboxIssue501Test.php index 34ebc9ec..176d35ac 100644 --- a/tests/unit/LiveMailboxIssue501Test.php +++ b/tests/unit/LiveMailboxIssue501Test.php @@ -31,7 +31,7 @@ class LiveMailboxIssue501Test extends AbstractLiveMailboxTest */ public function testDecodeMimeStrEmpty(): void { - $this->assertSame([], \imap_mime_header_decode('')); + $this->assertSame([], \imap2_mime_header_decode('')); // example credentials nabbed from MailboxTest::testConstructorTrimsPossibleVariables() $imapPath = ' {imap.example.com:993/imap/ssl}INBOX '; diff --git a/tests/unit/MailboxTest.php b/tests/unit/MailboxTest.php index 507ff596..fc0252dc 100644 --- a/tests/unit/MailboxTest.php +++ b/tests/unit/MailboxTest.php @@ -755,7 +755,7 @@ public function Base64DecodeProvider(): array */ public function testBase64Decode(string $input, string $expected): void { - $this->assertSame($expected, \imap_base64(\preg_replace('~[^a-zA-Z0-9+=/]+~s', '', $input))); + $this->assertSame($expected, \imap2_base64(\preg_replace('~[^a-zA-Z0-9+=/]+~s', '', $input))); $this->assertSame($expected, \base64_decode($input, false)); }