PluginProbe ʕ •ᴥ•ʔ
Check & Log Email – Easy Email Testing & Mail logging / 2.0.12
Check & Log Email – Easy Email Testing & Mail logging v2.0.12
1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 2.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.13 2.0.13.1 2.0.13.2 2.0.14 2.0.2 2.0.3 2.0.4 2.0.5 2.0.5.1 2.0.6 2.0.7 2.0.8 2.0.9 trunk 0.5.7 0.6.0 0.6.1 0.6.2 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.12.1 1.0.13 1.0.13.1 1.0.2 1.0.3
check-email / include / Core / Auth.php
check-email / include / Core Last commit date
DB 4 months ago Request 4 months ago UI 4 months ago Auth.php 4 months ago Check_Email_Admin_Capability_Giver.php 4 months ago Check_Email_Export_Log.php 4 months ago Check_Email_From_Handler.php 4 months ago Check_Email_Log.php 4 months ago Check_Email_Logger.php 4 months ago Check_Email_Multisite.php 4 months ago Check_Email_Review.php 4 months ago Loadie.php 4 months ago
Auth.php
514 lines
1 <?php
2
3
4 namespace CheckEmail\Core;
5 // Exit if accessed directly
6 if( !defined( 'ABSPATH' ) )
7 exit;
8 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
9 $check_email = wpchill_check_email();
10 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
11 $plugin_path = plugin_dir_path($check_email->get_plugin_file());
12 require_once $plugin_path . '/vendor/autoload.php';
13
14 use Exception;
15 use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
16 use League\OAuth2\Client\Provider\GenericProvider;
17 use League\OAuth2\Client\Token\AccessToken;
18 use League\OAuth2\Client\Token\AccessTokenInterface;
19
20 class Auth
21 {
22
23 /**
24 * Scopes that we need to send emails.
25 *
26 * @since 1.5.0
27 */
28 const SCOPES = [
29 'https://graph.microsoft.com/mail.send',
30 'https://graph.microsoft.com/mail.send.shared',
31 'https://graph.microsoft.com/mail.readwrite',
32 'https://graph.microsoft.com/user.read',
33 'offline_access',
34 ];
35 public $mailer = null;
36 public $options = [];
37 public $client = null;
38
39
40 public function __construct($mailer_type = null)
41 {
42 $this->mailer = $mailer_type;
43 $this->options = $this->get_mailer_option();
44 $this->get_client();
45 }
46
47
48 public function get_mailer_option()
49 {
50 $smtp_options = get_site_option('check-email-log-global-smtp');
51 if (isset($smtp_options['enable_global']) && ! empty($smtp_options['enable_global']) && is_multisite()) {
52 return get_site_option('check-email-log-' . $this->mailer . '-options');
53 } else {
54 return get_option('check-email-log-' . $this->mailer . '-options');
55 }
56 }
57 public function update_mailer_option($options_to_update)
58 {
59
60 $smtp_options = get_site_option('check-email-log-global-smtp');
61 if (isset($smtp_options['enable_global']) && ! empty($smtp_options['enable_global']) && is_multisite()) {
62 $site_option = get_site_option('check-email-log-' . $this->mailer . '-options');
63 $mailer_options = array_merge((array)$site_option, (array)$options_to_update);
64 update_site_option('check-email-log-' . $this->mailer . '-options', $mailer_options);
65 } else {
66 $site_option = empty(get_option('check-email-log-' . $this->mailer . '-options')) ? [] : get_option('check-email-log-' . $this->mailer . '-options');
67 $mailer_options = array_merge((array)$site_option, (array)$options_to_update);
68 update_option('check-email-log-' . $this->mailer . '-options', $mailer_options);
69 }
70 $this->options = $this->get_mailer_option();
71 }
72 public function get_client() {
73
74 // Doesn't load client twice + gives ability to overwrite.
75 if (! empty($this->client)) {
76 return $this->client;
77 }
78
79 $authorize_url = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize';
80
81
82 $access_token_url = 'https://login.microsoftonline.com/common/oauth2/v2.0/token';
83
84
85 $resource_owner_details_url = 'https://graph.microsoft.com/v1.0/me';
86 if (! isset($this->options['client_id']) && ! isset($this->options['client_secret'])) {
87 return null;
88 }
89
90 $this->client = new GenericProvider(
91 // $provider = new GenericProvider(
92 [
93 'clientId' => base64_decode($this->options['client_id']),
94 'clientSecret' => base64_decode($this->options['client_secret']),
95 'redirectUri' => self::get_plugin_auth_url(),
96 'urlAuthorize' => $authorize_url,
97 'urlAccessToken' => $access_token_url,
98 'urlResourceOwnerDetails' => $resource_owner_details_url,
99 'scopes' => 'openid profile User.Read Mail.Read Mail.Send',
100 ]
101 );
102
103
104 // Do not process if we don't have both App ID & Password.
105 if (! $this->is_clients_saved()) {
106 return $this->client;
107 }
108
109 if (! empty($this->options['access_token'])) {
110 $access_token = new AccessToken((array) $this->options['access_token']);
111 }
112
113 // We don't have tokens but have auth code.
114 if (
115 $this->is_auth_required() &&
116 ! empty($this->options['auth_code'])
117 ) {
118
119 // Try to get an access token using the authorization code grant.
120 $this->obtain_access_token();
121 } else { // We have tokens.
122
123 // Update the old token if needed.
124 if (! empty($access_token) && $access_token->hasExpired()) {
125 $this->refresh_access_token($access_token);
126 }
127 }
128
129 return $this->client;
130 }
131
132 /**
133 * Try to get an access token using the authorization code grant.
134 *
135 * @since 3.4.0
136 */
137 public function obtain_access_token() {
138
139 if (empty($this->options['auth_code'])) {
140 return;
141 }
142
143 try {
144 $access_token = $this->client->getAccessToken(
145 'authorization_code',
146 ['code' => $this->options['auth_code']]
147 );
148
149 $this->update_access_token($access_token->jsonSerialize());
150 // $this->update_refresh_token( $access_token->getRefreshToken() );
151 $this->update_user_details($access_token);
152 // $this->update_scopes( $this->get_scopes() );
153
154 // Reset Auth code. It's valid for 5 minutes anyway.
155 $this->update_auth_code('');
156
157 // Debug::clear();
158 } catch (IdentityProviderException $e) {
159 $response = $e->getResponseBody();
160
161 // error_log(print_r($response, true));
162
163
164 $this->update_auth_code('');
165 } catch (Exception $e) { // Catch any other general exceptions just in case.
166 // error_log(print_r($e->getMessage(), true));
167 $this->update_auth_code('');
168 }
169 }
170
171 private function refresh_access_token($access_token)
172 {
173 try {
174 $new_access_token = $this->client->getAccessToken(
175 'refresh_token',
176 ['refresh_token' => $access_token->getRefreshToken()]
177 );
178
179 $this->update_access_token($new_access_token->jsonSerialize());
180 $this->update_refresh_token($new_access_token->getRefreshToken());
181 $this->update_user_details($new_access_token);
182 } catch (IdentityProviderException $e) {
183 $response = $e->getResponseBody();
184
185
186 } catch (Exception $e) { // Catch any other general exception just in case.
187
188 // $e->getMessage()
189 }
190 }
191
192
193 public static function get_plugin_auth_url()
194 {
195 $smtp_options = get_site_option('check-email-log-global-smtp');
196 if (isset($smtp_options['enable_global']) && ! empty($smtp_options['enable_global']) && is_multisite()) {
197 return network_admin_url();
198 } else {
199 return admin_url();
200 }
201 }
202
203
204 public function process_auth($code)
205 {
206
207 $this->update_auth_code($code);
208
209 // Remove old errors.
210 Debug::clear();
211
212 // Retrieve the token and user details, save errors if any.
213 $this->get_client();
214 }
215
216
217 public function get_auth_url() {
218 $client = $this->get_client();
219 if (
220 ! empty($client) &&
221 class_exists('\League\OAuth2\Client\Provider\GenericProvider', false) &&
222 $client instanceof GenericProvider
223 ) {
224 $url_options = [
225 'state' => $this->get_state(),
226 'scope' => $this->get_scopes(),
227 ];
228
229 $auth_url = $client->getAuthorizationUrl($url_options);
230
231 return $auth_url;
232 }
233
234 return '#';
235 }
236
237 /**
238 * Get auth scopes.
239 *
240 * @since 2.8.0
241 *
242 * @return array
243 */
244 protected function get_scopes()
245 {
246
247 return self::SCOPES;
248 }
249
250
251 public function update_user_details($access_token)
252 {
253 $user = [
254 'display_name' => '',
255 'email' => '',
256 ];
257
258 try {
259 $resource_owner = $this->get_client()->getResourceOwner($access_token);
260 $resource_data = $resource_owner->toArray();
261
262 $user = [
263 'display_name' => $resource_data['displayName'],
264 'email' => $resource_data['userPrincipalName'],
265 ];
266 } catch (IdentityProviderException $e) {
267 $response = $e->getResponseBody();
268
269
270 // Reset Auth code. It's valid for 5 minutes anyway.
271 $this->update_auth_code( '' );
272 } catch (Exception $e) {
273 return $e->getMessage();
274 // Catch general any other exception just in case.
275 // Debug::set(
276 // 'Mailer: Outlook (requesting user details)' . WP::EOL .
277 // $e->getMessage()
278 // );
279 }
280
281
282 $site_option['user_details'] = $user;
283
284 $this->update_mailer_option($site_option);
285 }
286
287
288 protected function get_state()
289 {
290 return 'check-email-nonce_'.wp_create_nonce('ck_mail_outlook_check_nonce');
291 }
292
293 public function is_clients_saved()
294 {
295 return ! empty($this->options['client_id']) && ! empty($this->options['client_secret']);
296 }
297
298 public function is_auth_required()
299 {
300 return empty($this->options['access_token']);
301 }
302 public function update_access_token($access_token)
303 {
304 $smtp_options = get_site_option('check-email-log-global-smtp');
305 if (isset($smtp_options['enable_global']) && ! empty($smtp_options['enable_global']) && is_multisite()) {
306 $site_option = get_site_option('check-email-log-' . $this->mailer . '-options');
307 $site_option['access_token'] = $access_token;
308 update_site_option('check-email-log-' . $this->mailer . '-options', $site_option);
309 } else {
310 $site_option = get_option('check-email-log-' . $this->mailer . '-options');
311 $site_option['access_token'] = $access_token;
312 update_option('check-email-log-' . $this->mailer . '-options', $site_option);
313 }
314 $this->options = $this->get_mailer_option();
315 }
316
317 public function update_refresh_token($access_token)
318 {
319 $smtp_options = get_site_option('check-email-log-global-smtp');
320 if (isset($smtp_options['enable_global']) && ! empty($smtp_options['enable_global']) && is_multisite()) {
321 $site_option = get_site_option('check-email-log-' . $this->mailer . '-options');
322 $site_option['refresh_token'] = $access_token;
323 update_site_option('check-email-log-' . $this->mailer . '-options', $site_option);
324 } else {
325 $site_option = get_option('check-email-log-' . $this->mailer . '-options');
326 $site_option['refresh_token'] = $access_token;
327 update_option('check-email-log-' . $this->mailer . '-options', $site_option);
328 }
329 $this->options = $this->get_mailer_option();
330 }
331
332 public function update_auth_code($code) {
333 $smtp_options = get_site_option('check-email-log-global-smtp');
334 if (isset($smtp_options['enable_global']) && ! empty($smtp_options['enable_global']) && is_multisite()) {
335 $site_option = get_site_option('check-email-log-' . $this->mailer . '-options');
336 $site_option['auth_code'] = $code;
337 update_site_option('check-email-log-' . $this->mailer . '-options', $site_option);
338 } else {
339 $site_option = get_option('check-email-log-' . $this->mailer . '-options');
340 $site_option['auth_code'] = $code;
341 update_option('check-email-log-' . $this->mailer . '-options', $site_option);
342 }
343 $this->options = $this->get_mailer_option();
344
345 // We don't have tokens but have auth code.
346 if ($this->is_auth_required() && ! empty($this->options['auth_code'])) {
347 // Try to get an access token using the authorization code grant.
348 $this->obtain_access_token();
349 }
350 }
351
352 function sendEmailByMailer($from_email, $to_email, $subject, $body) {
353
354 // Get the access token from options
355 $access_token_array = $this->options['access_token'];
356 $access_token = $access_token_array['access_token'];
357
358 // Graph API URL for sending mail
359 $url = "https://graph.microsoft.com/v1.0/me/sendMail";
360
361 // Email message structure
362 $message = [
363 "message" => [
364 "subject" => $subject,
365 "body" => [
366 "contentType" => "HTML",
367 "content" => $body,
368 ],
369 "toRecipients" => [
370 [
371 "emailAddress" => [
372 "address" => $to_email,
373 ],
374 ],
375 ],
376 ],
377 "saveToSentItems" => "true", // Save a copy to Sent Items folder
378 ];
379
380 // Request arguments
381 $args = [
382 'headers' => [
383 "Authorization" => "Bearer $access_token", // Authorization header
384 'Content-Type' => 'application/json', // JSON content type
385 ],
386 'body' => wp_json_encode($message), // JSON encode the message
387 'timeout' => 45, // Optional timeout, increase if necessary
388 'sslverify' => true, // Verify SSL (set to false only if you're sure)
389 ];
390
391 // Make the API request using wp_remote_post
392 $response = wp_remote_post($url, $args);
393
394 // Check for errors in the response
395 if (is_wp_error($response)) {
396 return [
397 'error' => 1,
398 'message' => $response->get_error_message(), // Return the error message
399 ];
400 }
401
402 // Optional: Check the email log and forward if necessary
403 $setting_options = get_option('check-email-log-core');
404 if (isset($setting_options['forward_email']) && !empty($setting_options['forward_email'])) {
405 $this->forward_email_by_mailer($to_email, $subject, $body);
406 }
407
408 // If everything is fine, return success
409 return [
410 'error' => 0,
411 'message' => "", // Empty message means no errors
412 ];
413 }
414
415
416 function forward_email_by_mailer($to_email, $subject, $body) {
417 // Get the access token
418 $access_token_array = $this->options['access_token'];
419 $access_token = $access_token_array['access_token'];
420
421
422 // Graph API URL
423 $url = "https://graph.microsoft.com/v1.0/me/sendMail";
424 $toRecipients = [];
425 $ccRecipients = [];
426 $bccRecipients = [];
427 if (isset($setting_options['forward_email']) && !empty($setting_options['forward_email'])) {
428 if (isset($setting_options['forward_to']) && !empty($setting_options['forward_to'])) {
429 $to_email = explode(',', $setting_options['forward_to']);
430
431
432 foreach ((array) $to_email as $email) {
433 $toRecipients[] = [
434 "emailAddress" => [
435 "address" => $email,
436 ],
437 ];
438 }
439 }
440
441
442 if (isset($setting_options['forward_cc']) && !empty($setting_options['forward_cc'])) {
443 $copy_to = explode(',', $setting_options['forward_cc']);
444 foreach ((array) $copy_to as $email) {
445 $ccRecipients[] = [
446 "emailAddress" => [
447 "address" => $email,
448 ],
449 ];
450 }
451 }
452
453 if (isset($setting_options['forward_bcc']) && !empty($setting_options['forward_bcc'])) {
454 $bcc_to = explode(',', $setting_options['forward_bcc']);
455 foreach ((array) $bcc_to as $email) {
456 $bccRecipients[] = [
457 "emailAddress" => [
458 "address" => $email,
459 ],
460 ];
461 }
462 }
463 }
464
465 $message = [
466 "message" => [
467 "subject" => $subject,
468 "body" => [
469 "contentType" => "HTML",
470 "content" => $body,
471 ],
472 "toRecipients" => $toRecipients,
473 "ccRecipients" => $ccRecipients,
474 "bccRecipients" => $bccRecipients,
475 ],
476 "saveToSentItems" => "true",
477 ];
478
479 // Arguments for the request
480 $args = [
481 'headers' => [
482 "Authorization" => "Bearer $access_token",
483 'Content-Type' => 'application/json',
484 ],
485 'body' => wp_json_encode($message),
486 ];
487
488 $response = wp_remote_post($url, $args);
489
490 // Check for errors
491 if (is_wp_error($response)) {
492 return [
493 'error' => 1,
494 'message' => $response->get_error_message(),
495 ];
496 }
497
498 return [
499 'error' => 0,
500 'message' => "",
501 ];
502 }
503
504 public function delete_outlook_options() {
505 $smtp_options = get_site_option('check-email-log-global-smtp');
506 if (isset($smtp_options['enable_global']) && ! empty($smtp_options['enable_global']) && is_multisite()) {
507 delete_site_option('check-email-log-' . $this->mailer . '-options');
508 } else {
509 delete_option('check-email-log-' . $this->mailer . '-options');
510 }
511 $this->options = $this->get_mailer_option();
512 }
513 }
514