PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 11.1.0
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v11.1.0
11.1.1 11.1.0 11.0.5 11.0.4 11.0.3 11.0.2 11.0.1 11.0.0 10.11.1 10.11.0 10.10.2 10.10.1 10.10.0 10.9.1 trunk 10.0.0 10.0.1 10.1.0 10.1.1 10.1.2 10.1.3 10.1.4 10.2.0 10.2.1 10.2.2 All 62 releases
← All changes | back/Libraries/Mailer/OAuth.php +66 -99 10.1.4 → 11.1.0 View file →
@@ -12,9 +12,9 @@
12 12 * @author Brent R. Matzelle (original founder)
13 13 * @copyright 2012 - 2020 Marcus Bointon
14 14 * @copyright 2010 - 2012 Jim Jagielski
15 15 * @copyright 2004 - 2009 Andy Prevost
16 - * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
16 + * @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
17 17 * @note This program is distributed in the hope that it will be useful - WITHOUT
18 18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 19 * FITNESS FOR A PARTICULAR PURPOSE.
20 20 */
@@ -20,159 +20,126 @@
20 20 */
21 21
22 22 namespace AcyMailerPhp;
23 23
24 -
25 24 /**
26 25 * OAuth - OAuth2 authentication wrapper class.
27 26 * Uses the oauth2-client package from the League of Extraordinary Packages.
28 27 *
29 - * @see http://oauth2-client.thephpleague.com
28 + * @see https://oauth2-client.thephpleague.com
30 29 *
31 30 * @author Marcus Bointon (Synchro/coolbru) <[email protected]>
32 31 */
33 32 class OAuth implements OAuthTokenProvider
34 33 {
35 - const HOST_AUTH_2 = ['smtp.gmail.com', 'smtp-mail.outlook.com', 'smtp.office365.com'];
34 + /**
35 + * The sending method used.
36 + */
37 + protected string $sendingMethod;
36 38
37 39 /**
38 - * An instance of the League OAuth Client Provider.
39 - *
40 - * @var AbstractProvider
40 + * The URL called to generate an access token from a refresh token.
41 41 */
42 - protected $provider;
42 + protected string $tokenGenerationUrl;
43 43
44 44 /**
45 - * The current OAuth access token.
46 - *
47 - * @var AccessToken
45 + * The current OAuth access token, prefixed with "Bearer ".
48 46 */
49 - protected $oauthToken;
47 + protected string $oauthToken;
50 48
51 49 /**
52 50 * The user's email address, usually used as the login ID
53 51 * and also the from address when sending email.
54 - *
55 - * @var string
56 52 */
57 - protected $oauthUserEmail = '';
53 + protected string $oauthUserEmail;
58 54
59 55 /**
60 56 * The client secret, generated in the app definition of the service you're connecting to.
61 - *
62 - * @var string
63 57 */
64 - protected $oauthClientSecret = '';
58 + protected string $oauthClientSecret;
65 59
66 60 /**
67 61 * The client ID, generated in the app definition of the service you're connecting to.
68 - *
69 - * @var string
70 62 */
71 - protected $oauthClientId = '';
63 + protected string $oauthClientId;
72 64
73 65 /**
74 66 * The refresh token, used to obtain new AccessTokens.
75 - *
76 - * @var string
77 67 */
78 - protected $oauthRefreshToken = '';
68 + protected string $oauthRefreshToken;
79 69
80 - protected $expiredIn = '';
81 -
82 - protected $host = '';
83 -
84 70 /**
85 - * OAuth constructor.
86 - *
87 - * @param array $options Associative array containing
88 - * `provider`, `userName`, `clientSecret`, `clientId` and `refreshToken` elements
71 + * The timestamp at which the current token expires.
89 72 */
90 - public function __construct($options)
73 + protected int $oauthTokenExpiration;
74 +
75 + public function __construct(array $options)
91 76 {
92 - $this->oauthUserEmail = $options['userName'];
93 - $this->oauthClientSecret = $options['clientSecret'];
94 - $this->oauthClientId = $options['clientId'];
95 - $this->oauthToken = $options['oauthToken'];
96 - $this->oauthRefreshToken = $options['refreshToken'];
97 - $this->expiredIn = $options['expiredIn'];
98 - $this->host = strtolower($options['host']);
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;
99 86 }
100 87
101 88 /**
102 - * Get a new AccessToken.
103 - *
104 - * @return AccessToken
89 + * Generate a base64-encoded OAuth token.
105 90 */
106 - protected function getToken()
91 + public function getOauth64(): string
107 92 {
108 - $config = acym_config();
109 - if ($this->host === 'smtp.gmail.com') {
110 - $url = 'https://oauth2.googleapis.com/token';
111 - } else {
112 - $tenant = $config->get('smtp_tenant');
113 - if (empty($tenant)) {
114 - acym_enqueueMessage(acym_translation('ACYM_TENANT_FIELD_IS_MISSING'), 'error');
115 - }
116 - $url = 'https://login.microsoftonline.com/'.$tenant.'/oauth2/v2.0/token';
93 + $this->oauthToken = $this->getToken();
94 +
95 + if (empty($this->oauthToken)) {
96 + return '';
117 97 }
118 98
119 - $data = ['client_id' => $this->oauthClientId, 'grant_type' => 'refresh_token', 'refresh_token' => $this->oauthRefreshToken, 'client_secret' => $this->oauthClientSecret];
120 -
121 - $response = acym_makeCurlCall(
122 - $url,
123 - ['data' => $data, 'method' => 'POST']
124 - );
125 -
126 - if (empty($response['error'])) {
127 - $token = $response['token_type'].' '.$response['access_token'];
128 - $expireIn = time() + (int)$response['expires_in'];
129 - $config->save(['smtp_token' => $token, 'smtp_token_expireIn' => $expireIn]);
130 -
131 - return $token;
132 - } else {
133 - acym_enqueueMessage(acym_translationSprintf('ACYM_OAUTH_REFRESH_TOKEN_ERROR', $response['error']), 'error');
134 - }
99 + return base64_encode('user='.$this->oauthUserEmail."\001auth=Bearer ".$this->oauthToken."\001\001");
135 100 }
136 101
137 102 /**
138 - * Generate a base64-encoded OAuth token.
139 - *
140 - * @return string
103 + * Custom method to avoid having a million vendors in the extension zip file.
141 104 */
142 - public function getOauth64()
105 + public function getToken(): string
143 106 {
144 - //Get a new token if it's not available or has expired
145 - if ($this->tokenHasExpired() || empty($this->oauthToken)) {
146 - $this->oauthToken = $this->getToken();
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;
147 110 }
148 111
149 - return base64_encode(
150 - 'user='.
151 - $this->oauthUserEmail.
152 - "\001auth=".
153 - $this->oauthToken.
154 - "\001\001"
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 + ]
155 123 );
156 - }
157 124
158 - private function tokenHasExpired()
159 - {
160 - $expired = false;
161 - if ($this->expiredIn < time()) {
162 - $expired = true;
163 - }
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);
164 135
165 - return $expired;
166 - }
167 -
168 - static function hostRequireOauth($host, $connectionType)
169 - {
170 - $host = strtolower($host);
171 -
172 - if (!in_array($host, self::HOST_AUTH_2)) {
173 - return false;
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]);
174 141 }
175 142
176 - return $connectionType !== 'password';
143 + return $response['access_token'] ?? '';
177 144 }
178 145 }