| 1 |
<?php |
| 2 |
|
| 3 |
/** |
| 4 |
* PHPMailer - PHP email creation and transport class. |
| 5 |
* PHP Version 5.5. |
| 6 |
* |
| 7 |
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project |
| 8 |
* |
| 9 |
* @author Marcus Bointon (Synchro/coolbru) <[email protected]> |
| 10 |
* @author Jim Jagielski (jimjag) <[email protected]> |
| 11 |
* @author Andy Prevost (codeworxtech) <[email protected]> |
| 12 |
* @author Brent R. Matzelle (original founder) |
| 13 |
* @copyright 2012 - 2020 Marcus Bointon |
| 14 |
* @copyright 2010 - 2012 Jim Jagielski |
| 15 |
* @copyright 2004 - 2009 Andy Prevost |
| 16 |
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License |
| 17 |
* @note This program is distributed in the hope that it will be useful - WITHOUT |
| 18 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 19 |
* FITNESS FOR A PARTICULAR PURPOSE. |
| 20 |
*/ |
| 21 |
|
| 22 |
namespace AcyMailerPhp; |
| 23 |
|
| 24 |
/** |
| 25 |
* OAuth - OAuth2 authentication wrapper class. |
| 26 |
* Uses the oauth2-client package from the League of Extraordinary Packages. |
| 27 |
* |
| 28 |
* @see https://oauth2-client.thephpleague.com |
| 29 |
* |
| 30 |
* @author Marcus Bointon (Synchro/coolbru) <[email protected]> |
| 31 |
*/ |
| 32 |
class OAuth implements OAuthTokenProvider |
| 33 |
{ |
| 34 |
/** |
| 35 |
* The sending method used. |
| 36 |
*/ |
| 37 |
protected string $sendingMethod; |
| 38 |
|
| 39 |
/** |
| 40 |
* The URL called to generate an access token from a refresh token. |
| 41 |
*/ |
| 42 |
protected string $tokenGenerationUrl; |
| 43 |
|
| 44 |
/** |
| 45 |
* The current OAuth access token, prefixed with "Bearer ". |
| 46 |
*/ |
| 47 |
protected string $oauthToken; |
| 48 |
|
| 49 |
/** |
| 50 |
* The user's email address, usually used as the login ID |
| 51 |
* and also the from address when sending email. |
| 52 |
*/ |
| 53 |
protected string $oauthUserEmail; |
| 54 |
|
| 55 |
/** |
| 56 |
* The client secret, generated in the app definition of the service you're connecting to. |
| 57 |
*/ |
| 58 |
protected string $oauthClientSecret; |
| 59 |
|
| 60 |
/** |
| 61 |
* The client ID, generated in the app definition of the service you're connecting to. |
| 62 |
*/ |
| 63 |
protected string $oauthClientId; |
| 64 |
|
| 65 |
/** |
| 66 |
* The refresh token, used to obtain new AccessTokens. |
| 67 |
*/ |
| 68 |
protected string $oauthRefreshToken; |
| 69 |
|
| 70 |
/** |
| 71 |
* The timestamp at which the current token expires. |
| 72 |
*/ |
| 73 |
protected int $oauthTokenExpiration; |
| 74 |
|
| 75 |
public function __construct(array $options) |
| 76 |
{ |
| 77 |
$this->sendingMethod = $options['sendingMethod'] ?? ''; |
| 78 |
$this->tokenGenerationUrl = $options['tokenGenerationUrl'] ?? ''; |
| 79 |
|
| 80 |
$this->oauthUserEmail = $options['userName'] ?? ''; |
| 81 |
$this->oauthClientId = $options['clientId'] ?? ''; |
| 82 |
$this->oauthClientSecret = $options['clientSecret'] ?? ''; |
| 83 |
$this->oauthRefreshToken = $options['refreshToken'] ?? ''; |
| 84 |
$this->oauthToken = $options['oauthToken'] ?? ''; |
| 85 |
$this->oauthTokenExpiration = $options['oauthTokenExpiration'] ? (int)$options['oauthTokenExpiration'] : 0; |
| 86 |
} |
| 87 |
|
| 88 |
/** |
| 89 |
* Generate a base64-encoded OAuth token. |
| 90 |
*/ |
| 91 |
public function getOauth64(): string |
| 92 |
{ |
| 93 |
$this->oauthToken = $this->getToken(); |
| 94 |
|
| 95 |
if (empty($this->oauthToken)) { |
| 96 |
return ''; |
| 97 |
} |
| 98 |
|
| 99 |
return base64_encode('user='.$this->oauthUserEmail."\001auth=Bearer ".$this->oauthToken."\001\001"); |
| 100 |
} |
| 101 |
|
| 102 |
/** |
| 103 |
* Custom method to avoid having a million vendors in the extension zip file. |
| 104 |
*/ |
| 105 |
public function getToken(): string |
| 106 |
{ |
| 107 |
// Get a new token only if it's not available or has expired |
| 108 |
if (!empty($this->oauthToken) && $this->oauthTokenExpiration > time()) { |
| 109 |
return $this->oauthToken; |
| 110 |
} |
| 111 |
|
| 112 |
$response = acym_makeCurlCall( |
| 113 |
$this->tokenGenerationUrl, |
| 114 |
[ |
| 115 |
'data' => [ |
| 116 |
'client_id' => $this->oauthClientId, |
| 117 |
'client_secret' => $this->oauthClientSecret, |
| 118 |
'refresh_token' => $this->oauthRefreshToken, |
| 119 |
'grant_type' => 'refresh_token', |
| 120 |
], |
| 121 |
'method' => 'POST', |
| 122 |
] |
| 123 |
); |
| 124 |
|
| 125 |
if (!empty($response['token_type']) && !empty($response['access_token'])) { |
| 126 |
$config = acym_config(); |
| 127 |
$config->saveConfig( |
| 128 |
[ |
| 129 |
$this->sendingMethod.'_access_token' => $response['access_token'], |
| 130 |
$this->sendingMethod.'_access_token_expiration' => time() + (int)$response['expires_in'], |
| 131 |
] |
| 132 |
); |
| 133 |
} else { |
| 134 |
acym_logError('Response from OAuth refresh token call: '.json_encode($response), 'oauth', 100); |
| 135 |
|
| 136 |
$notification = [ |
| 137 |
'name' => 'oauth_refresh_token_error', |
| 138 |
'removable' => 1, |
| 139 |
]; |
| 140 |
acym_enqueueMessage(acym_translationSprintf('ACYM_OAUTH_REFRESH_TOKEN_ERROR', $response['error'] ?? ''), 'error', true, [$notification]); |
| 141 |
} |
| 142 |
|
| 143 |
return $response['access_token'] ?? ''; |
| 144 |
} |
| 145 |
} |
| 146 |
|