PluginProbe ʕ •ᴥ•ʔ
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin / 3.3.0
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin v3.3.0
0.9.6 1.0.0 1.0.1 1.0.2 1.1.0 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.2 1.7.0 1.7.1 1.8.0 1.8.1 1.9.0 2.0.0 2.0.1 2.1.1 2.2.1 2.3.1 2.4.0 2.5.0 2.5.1 2.6.0 2.7.0 2.8.0 2.9.0 3.0.1 3.0.2 3.0.3 3.1.0 3.10.0 3.11.0 3.11.1 3.2.0 3.2.1 3.3.0 3.4.0 3.5.0 3.5.1 3.5.2 3.6.1 3.7.0 3.8.0 3.8.2 3.9.0 4.0.1 4.1.0 4.1.1 4.2.0 4.3.0 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.8.0 trunk 0.10.0 0.10.1 0.11.1 0.11.2 0.3.1 0.3.2 0.4 0.4.1 0.4.2 0.5.0 0.5.1 0.5.2 0.6 0.7 0.8 0.8.2 0.8.3 0.8.4 0.8.5 0.8.6 0.8.7 0.9.0 0.9.1 0.9.2 0.9.3 0.9.4 0.9.5
wp-mail-smtp / src / Options.php
wp-mail-smtp / src Last commit date
Admin 4 years ago Compatibility 4 years ago Helpers 4 years ago Providers 4 years ago Reports 4 years ago Tasks 4 years ago UsageTracking 4 years ago Conflicts.php 4 years ago Connect.php 4 years ago Core.php 4 years ago Debug.php 4 years ago Geo.php 4 years ago MailCatcher.php 4 years ago MailCatcherInterface.php 4 years ago MailCatcherV6.php 4 years ago Migration.php 4 years ago MigrationAbstract.php 4 years ago Options.php 4 years ago Processor.php 4 years ago SiteHealth.php 4 years ago Upgrade.php 4 years ago Uploads.php 4 years ago WP.php 4 years ago
Options.php
1358 lines
1 <?php
2
3 namespace WPMailSMTP;
4
5 use WPMailSMTP\Helpers\Crypto;
6 use WPMailSMTP\Reports\Emails\Summary as SummaryReportEmail;
7 use WPMailSMTP\UsageTracking\UsageTracking;
8
9 /**
10 * Class Options to handle all options management.
11 * WordPress does all the heavy work for caching get_option() data,
12 * so we don't have to do that. But we want to minimize cyclomatic complexity
13 * of calling a bunch of WP functions, thus we will cache them in a class as well.
14 *
15 * @since 1.0.0
16 */
17 class Options {
18
19 /**
20 * All the options keys.
21 *
22 * @since 1.3.0
23 * @since 1.4.0 Added Mailgun:region.
24 * @since 1.5.0 Added Outlook/AmazonSES.
25 * @since 1.8.0 Added Pepipost API.
26 * @since 2.0.0 Added SMTP.com API.
27 *
28 * @var array Map of all the default options of the plugin.
29 */
30 private static $map = [
31 'mail' => [
32 'from_name',
33 'from_email',
34 'mailer',
35 'return_path',
36 'from_name_force',
37 'from_email_force',
38 ],
39 'smtp' => [
40 'host',
41 'port',
42 'encryption',
43 'autotls',
44 'auth',
45 'user',
46 'pass',
47 ],
48 'gmail' => [
49 'client_id',
50 'client_secret',
51 ],
52 'outlook' => [
53 'client_id',
54 'client_secret',
55 ],
56 'zoho' => [
57 'domain',
58 'client_id',
59 'client_secret',
60 ],
61 'amazonses' => [
62 'client_id',
63 'client_secret',
64 'region',
65 ],
66 'mailgun' => [
67 'api_key',
68 'domain',
69 'region',
70 ],
71 'sendgrid' => [
72 'api_key',
73 'domain',
74 ],
75 'sparkpost' => [
76 'api_key',
77 'region',
78 ],
79 'postmark' => [
80 'server_api_token',
81 'message_stream',
82 ],
83 'smtpcom' => [
84 'api_key',
85 'channel',
86 ],
87 'sendinblue' => [
88 'api_key',
89 'domain',
90 ],
91 'pepipostapi' => [
92 'api_key',
93 ],
94 'pepipost' => [
95 'host',
96 'port',
97 'encryption',
98 'auth',
99 'user',
100 'pass',
101 ],
102 'license' => [
103 'key',
104 ],
105 ];
106
107 /**
108 * List of all mailers (except PHP default mailer 'mail').
109 *
110 * @since 3.3.0
111 *
112 * @var string[]
113 */
114 public static $mailers = [
115 'smtpcom',
116 'sendinblue',
117 'amazonses',
118 'gmail',
119 'mailgun',
120 'outlook',
121 'postmark',
122 'sendgrid',
123 'sparkpost',
124 'zoho',
125 'smtp',
126 'pepipost',
127 'pepipostapi',
128 ];
129
130 /**
131 * That's where plugin options are saved in wp_options table.
132 *
133 * @since 1.0.0
134 *
135 * @var string
136 */
137 const META_KEY = 'wp_mail_smtp';
138
139 /**
140 * All the plugin options.
141 *
142 * @since 1.0.0
143 *
144 * @var array
145 */
146 private $_options = [];
147
148 /**
149 * Init the Options class.
150 * TODO: add a flag to process without retrieving const values.
151 *
152 * @since 1.0.0
153 * @since 3.3.0 Deprecated instantiation via new keyword. `Options::init()` must be used.
154 */
155 public function __construct() {
156
157 $this->populate_options();
158 }
159
160 /**
161 * Initialize all the options.
162 *
163 * @since 1.0.0
164 *
165 * @return Options
166 */
167 public static function init() {
168
169 static $instance;
170
171 if ( ! $instance ) {
172 $instance = new self();
173 }
174
175 return $instance;
176 }
177
178 /**
179 * Default options that are saved on plugin activation.
180 *
181 * @since 1.3.0
182 * @since 2.1.0 Set the Force from email to "on" by default.
183 *
184 * @return array
185 */
186 public static function get_defaults() {
187
188 return [
189 'mail' => [
190 'from_email' => get_option( 'admin_email' ),
191 'from_name' => get_bloginfo( 'name' ),
192 'mailer' => 'mail',
193 'return_path' => false,
194 'from_email_force' => true,
195 'from_name_force' => false,
196 ],
197 'smtp' => [
198 'autotls' => true,
199 'auth' => true,
200 ],
201 'general' => [
202 SummaryReportEmail::SETTINGS_SLUG => ! is_multisite() ? false : true,
203 ],
204 ];
205 }
206
207 /**
208 * Retrieve all options of the plugin.
209 *
210 * @since 1.0.0
211 * @since 2.2.0 Added the filter.
212 */
213 protected function populate_options() {
214
215 $this->_options = apply_filters( 'wp_mail_smtp_populate_options', get_option( self::META_KEY, [] ) );
216 }
217
218 /**
219 * Get all the options.
220 *
221 * Options::init()->get_all();
222 *
223 * @since 1.0.0
224 *
225 * @return array
226 */
227 public function get_all() {
228
229 $options = $this->_options;
230
231 foreach ( $options as $group => $g_value ) {
232 foreach ( $g_value as $key => $value ) {
233 $options[ $group ][ $key ] = $this->get( $group, $key );
234 }
235 }
236
237 return apply_filters( 'wp_mail_smtp_options_get_all', $options );
238 }
239
240 /**
241 * Get all the options for a group.
242 *
243 * Options::init()->get_group('smtp') - will return the array of options for the group, including defaults and constants.
244 *
245 * @since 1.0.0
246 * @since 1.5.0 Process values through the get() method which is aware of constants.
247 *
248 * @param string $group
249 *
250 * @return array
251 */
252 public function get_group( $group ) {
253
254 // Just to feel safe.
255 $group = sanitize_key( $group );
256
257 /*
258 * Get the values saved in DB.
259 * If plugin is configured with constants right from the start - this will not have all the values.
260 */
261 $options = isset( $this->_options[ $group ] ) ? $this->_options[ $group ] : array();
262
263 // We need to process certain constants-aware options through actual constants.
264 if ( isset( self::$map[ $group ] ) ) {
265 foreach ( self::$map[ $group ] as $key ) {
266 $options[ $key ] = $this->get( $group, $key );
267 }
268 }
269
270 return apply_filters( 'wp_mail_smtp_options_get_group', $options, $group );
271 }
272
273 /**
274 * Get options by a group and a key.
275 *
276 * Options::init()->get( 'smtp', 'host' ) - will return only SMTP 'host' option.
277 *
278 * @since 1.0.0
279 * @since 2.5.0 Added $strip_slashes method parameter.
280 *
281 * @param string $group The option group.
282 * @param string $key The option key.
283 * @param bool $strip_slashes If the slashes should be stripped from string values.
284 *
285 * @return mixed|null Null if value doesn't exist anywhere: in constants, in DB, in a map. So it's completely custom or a typo.
286 */
287 public function get( $group, $key, $strip_slashes = true ) {
288
289 // Just to feel safe.
290 $group = sanitize_key( $group );
291 $key = sanitize_key( $key );
292 $value = null;
293
294 // Get the const value if we have one.
295 $value = $this->get_const_value( $group, $key, $value );
296
297 // We don't have a const value.
298 if ( $value === null ) {
299 // Ordinary database or default values.
300 if ( isset( $this->_options[ $group ] ) ) {
301 // Get the options key of a group.
302 if ( isset( $this->_options[ $group ][ $key ] ) ) {
303 $value = $this->get_existing_option_value( $group, $key );
304 } else {
305 $value = $this->postprocess_key_defaults( $group, $key );
306 }
307 } else {
308 /*
309 * Fallback to default if it doesn't exist in a map.
310 * Allow to retrieve only values from a map.
311 */
312 if (
313 isset( self::$map[ $group ] ) &&
314 in_array( $key, self::$map[ $group ], true )
315 ) {
316 $value = $this->postprocess_key_defaults( $group, $key );
317 }
318 }
319 }
320
321 // Conditionally strip slashes only from values saved in DB. Constants should be processed as is.
322 if ( $strip_slashes && is_string( $value ) && ! $this->is_const_defined( $group, $key ) ) {
323 $value = stripslashes( $value );
324 }
325
326 return apply_filters( 'wp_mail_smtp_options_get', $value, $group, $key );
327 }
328
329 /**
330 * Get the existing cached option value.
331 *
332 * @since 2.5.0
333 *
334 * @param string $group The options group.
335 * @param string $key The options key.
336 *
337 * @return mixed
338 */
339 private function get_existing_option_value( $group, $key ) {
340
341 if ( $group === 'smtp' && $key === 'pass' ) {
342 try {
343 return Crypto::decrypt( $this->_options[ $group ][ $key ] );
344 } catch ( \Exception $e ) {
345 return $this->_options[ $group ][ $key ];
346 }
347 }
348
349 return $this->_options[ $group ][ $key ];
350 }
351
352 /**
353 * Some options may be non-empty by default,
354 * so we need to postprocess them to convert.
355 *
356 * @since 1.0.0
357 * @since 1.4.0 Added Mailgun:region.
358 * @since 1.5.0 Added Outlook/AmazonSES, license key support.
359 *
360 * @param string $group
361 * @param string $key
362 *
363 * @return mixed
364 */
365 protected function postprocess_key_defaults( $group, $key ) {
366
367 $value = '';
368
369 switch ( $key ) {
370 case 'from_email_force':
371 case 'from_name_force':
372 case 'return_path':
373 $value = $group === 'mail' ? false : true;
374 break;
375
376 case 'mailer':
377 $value = 'mail';
378 break;
379
380 case 'encryption':
381 $value = in_array( $group, array( 'smtp', 'pepipost' ), true ) ? 'none' : $value;
382 break;
383
384 case 'region':
385 $value = $group === 'mailgun' || $group === 'sparkpost' ? 'US' : $value;
386 break;
387
388 case 'auth':
389 case 'autotls':
390 $value = in_array( $group, array( 'smtp', 'pepipost' ), true ) ? false : true;
391 break;
392
393 case 'pass':
394 $value = $this->get_const_value( $group, $key, $value );
395 break;
396
397 case 'type':
398 $value = $group === 'license' ? 'lite' : '';
399 break;
400 }
401
402 return apply_filters( 'wp_mail_smtp_options_postprocess_key_defaults', $value, $group, $key );
403 }
404
405 /**
406 * Process the options values through the constants check.
407 * If we have defined associated constant - use it instead of a DB value.
408 * Backward compatibility is hard.
409 * General section of options won't have constants, so we are omitting those checks and just return default value.
410 *
411 * @since 1.0.0
412 * @since 1.4.0 Added WPMS_MAILGUN_REGION.
413 * @since 1.5.0 Added Outlook/AmazonSES, license key support.
414 * @since 1.6.0 Added Sendinblue.
415 * @since 1.7.0 Added Do Not Send.
416 * @since 1.8.0 Added Pepipost API.
417 *
418 * @param string $group
419 * @param string $key
420 * @param mixed $value
421 *
422 * @return mixed
423 */
424 protected function get_const_value( $group, $key, $value ) {
425
426 if ( ! $this->is_const_enabled() ) {
427 return $value;
428 }
429
430 $return = null;
431
432 switch ( $group ) {
433 case 'mail':
434 switch ( $key ) {
435 case 'from_name':
436 /** @noinspection PhpUndefinedConstantInspection */
437 $return = $this->is_const_defined( $group, $key ) ? WPMS_MAIL_FROM_NAME : $value;
438 break;
439 case 'from_email':
440 /** @noinspection PhpUndefinedConstantInspection */
441 $return = $this->is_const_defined( $group, $key ) ? WPMS_MAIL_FROM : $value;
442 break;
443 case 'mailer':
444 /** @noinspection PhpUndefinedConstantInspection */
445 $return = $this->is_const_defined( $group, $key ) ? WPMS_MAILER : $value;
446 break;
447 case 'return_path':
448 /** @noinspection PhpUndefinedConstantInspection */
449 $return = $this->is_const_defined( $group, $key ) ? WPMS_SET_RETURN_PATH : $value;
450 break;
451 case 'from_name_force':
452 /** @noinspection PhpUndefinedConstantInspection */
453 $return = $this->is_const_defined( $group, $key ) ? WPMS_MAIL_FROM_NAME_FORCE : $value;
454 break;
455 case 'from_email_force':
456 /** @noinspection PhpUndefinedConstantInspection */
457 $return = $this->is_const_defined( $group, $key ) ? WPMS_MAIL_FROM_FORCE : $value;
458 break;
459 }
460
461 break;
462
463 case 'smtp':
464 switch ( $key ) {
465 case 'host':
466 /** @noinspection PhpUndefinedConstantInspection */
467 $return = $this->is_const_defined( $group, $key ) ? WPMS_SMTP_HOST : $value;
468 break;
469 case 'port':
470 /** @noinspection PhpUndefinedConstantInspection */
471 $return = $this->is_const_defined( $group, $key ) ? WPMS_SMTP_PORT : $value;
472 break;
473 case 'encryption':
474 /** @noinspection PhpUndefinedConstantInspection */
475 $return = $this->is_const_defined( $group, $key ) ? ( WPMS_SSL === '' ? 'none' : WPMS_SSL ) : $value;
476 break;
477 case 'auth':
478 /** @noinspection PhpUndefinedConstantInspection */
479 $return = $this->is_const_defined( $group, $key ) ? (bool) WPMS_SMTP_AUTH : $value;
480 break;
481 case 'autotls':
482 /** @noinspection PhpUndefinedConstantInspection */
483 $return = $this->is_const_defined( $group, $key ) ? (bool) WPMS_SMTP_AUTOTLS : $value;
484 break;
485 case 'user':
486 /** @noinspection PhpUndefinedConstantInspection */
487 $return = $this->is_const_defined( $group, $key ) ? WPMS_SMTP_USER : $value;
488 break;
489 case 'pass':
490 /** @noinspection PhpUndefinedConstantInspection */
491 $return = $this->is_const_defined( $group, $key ) ? WPMS_SMTP_PASS : $value;
492 break;
493 }
494
495 break;
496
497 case 'gmail':
498 switch ( $key ) {
499 case 'client_id':
500 /** @noinspection PhpUndefinedConstantInspection */
501 $return = $this->is_const_defined( $group, $key ) ? WPMS_GMAIL_CLIENT_ID : $value;
502 break;
503 case 'client_secret':
504 /** @noinspection PhpUndefinedConstantInspection */
505 $return = $this->is_const_defined( $group, $key ) ? WPMS_GMAIL_CLIENT_SECRET : $value;
506 break;
507 }
508
509 break;
510
511 case 'outlook':
512 switch ( $key ) {
513 case 'client_id':
514 /** @noinspection PhpUndefinedConstantInspection */
515 $return = $this->is_const_defined( $group, $key ) ? WPMS_OUTLOOK_CLIENT_ID : $value;
516 break;
517 case 'client_secret':
518 /** @noinspection PhpUndefinedConstantInspection */
519 $return = $this->is_const_defined( $group, $key ) ? WPMS_OUTLOOK_CLIENT_SECRET : $value;
520 break;
521 }
522
523 break;
524
525 case 'zoho':
526 switch ( $key ) {
527 case 'domain':
528 /** No inspection comment @noinspection PhpUndefinedConstantInspection */
529 $return = $this->is_const_defined( $group, $key ) ? WPMS_ZOHO_DOMAIN : $value;
530 break;
531 case 'client_id':
532 /** No inspection comment @noinspection PhpUndefinedConstantInspection */
533 $return = $this->is_const_defined( $group, $key ) ? WPMS_ZOHO_CLIENT_ID : $value;
534 break;
535 case 'client_secret':
536 /** No inspection comment @noinspection PhpUndefinedConstantInspection */
537 $return = $this->is_const_defined( $group, $key ) ? WPMS_ZOHO_CLIENT_SECRET : $value;
538 break;
539 }
540
541 break;
542
543 case 'amazonses':
544 switch ( $key ) {
545 case 'client_id':
546 /** @noinspection PhpUndefinedConstantInspection */
547 $return = $this->is_const_defined( $group, $key ) ? WPMS_AMAZONSES_CLIENT_ID : $value;
548 break;
549 case 'client_secret':
550 /** @noinspection PhpUndefinedConstantInspection */
551 $return = $this->is_const_defined( $group, $key ) ? WPMS_AMAZONSES_CLIENT_SECRET : $value;
552 break;
553 case 'region':
554 /** @noinspection PhpUndefinedConstantInspection */
555 $return = $this->is_const_defined( $group, $key ) ? WPMS_AMAZONSES_REGION : $value;
556 break;
557 }
558
559 break;
560
561 case 'mailgun':
562 switch ( $key ) {
563 case 'api_key':
564 /** @noinspection PhpUndefinedConstantInspection */
565 $return = $this->is_const_defined( $group, $key ) ? WPMS_MAILGUN_API_KEY : $value;
566 break;
567 case 'domain':
568 /** @noinspection PhpUndefinedConstantInspection */
569 $return = $this->is_const_defined( $group, $key ) ? WPMS_MAILGUN_DOMAIN : $value;
570 break;
571 case 'region':
572 /** @noinspection PhpUndefinedConstantInspection */
573 $return = $this->is_const_defined( $group, $key ) ? WPMS_MAILGUN_REGION : $value;
574 break;
575 }
576
577 break;
578
579 case 'sendgrid':
580 switch ( $key ) {
581 case 'api_key':
582 /** @noinspection PhpUndefinedConstantInspection */
583 $return = $this->is_const_defined( $group, $key ) ? WPMS_SENDGRID_API_KEY : $value;
584 break;
585 case 'domain':
586 /** @noinspection PhpUndefinedConstantInspection */
587 $return = $this->is_const_defined( $group, $key ) ? WPMS_SENDGRID_DOMAIN : $value;
588 break;
589 }
590
591 break;
592
593 case 'sparkpost':
594 switch ( $key ) {
595 case 'api_key':
596 /** No inspection comment @noinspection PhpUndefinedConstantInspection */
597 $return = $this->is_const_defined( $group, $key ) ? WPMS_SPARKPOST_API_KEY : $value;
598 break;
599 case 'region':
600 /** No inspection comment @noinspection PhpUndefinedConstantInspection */
601 $return = $this->is_const_defined( $group, $key ) ? WPMS_SPARKPOST_REGION : $value;
602 break;
603 }
604
605 break;
606
607 case 'postmark':
608 switch ( $key ) {
609 case 'server_api_token':
610 /** No inspection comment @noinspection PhpUndefinedConstantInspection */
611 $return = $this->is_const_defined( $group, $key ) ? WPMS_POSTMARK_SERVER_API_TOKEN : $value;
612 break;
613 case 'message_stream':
614 /** No inspection comment @noinspection PhpUndefinedConstantInspection */
615 $return = $this->is_const_defined( $group, $key ) ? WPMS_POSTMARK_MESSAGE_STREAM : $value;
616 break;
617 }
618
619 break;
620
621 case 'smtpcom':
622 switch ( $key ) {
623 case 'api_key':
624 /** @noinspection PhpUndefinedConstantInspection */
625 $return = $this->is_const_defined( $group, $key ) ? WPMS_SMTPCOM_API_KEY : $value;
626 break;
627 case 'channel':
628 /** @noinspection PhpUndefinedConstantInspection */
629 $return = $this->is_const_defined( $group, $key ) ? WPMS_SMTPCOM_CHANNEL : $value;
630 break;
631 }
632
633 break;
634
635 case 'sendinblue':
636 switch ( $key ) {
637 case 'api_key':
638 /** @noinspection PhpUndefinedConstantInspection */
639 $return = $this->is_const_defined( $group, $key ) ? WPMS_SENDINBLUE_API_KEY : $value;
640 break;
641 case 'domain':
642 /** @noinspection PhpUndefinedConstantInspection */
643 $return = $this->is_const_defined( $group, $key ) ? WPMS_SENDINBLUE_DOMAIN : $value;
644 break;
645 }
646
647 break;
648
649 case 'pepipostapi':
650 switch ( $key ) {
651 case 'api_key':
652 /** @noinspection PhpUndefinedConstantInspection */
653 $return = $this->is_const_defined( $group, $key ) ? WPMS_PEPIPOST_API_KEY : $value;
654 break;
655 }
656
657 break;
658
659 case 'license':
660 switch ( $key ) {
661 case 'key':
662 /** @noinspection PhpUndefinedConstantInspection */
663 $return = $this->is_const_defined( $group, $key ) ? WPMS_LICENSE_KEY : $value;
664 break;
665 }
666
667 break;
668
669 case 'general':
670 switch ( $key ) {
671 case 'do_not_send':
672 /** @noinspection PhpUndefinedConstantInspection */
673 $return = $this->is_const_defined( $group, $key ) ? WPMS_DO_NOT_SEND : $value;
674 break;
675 case SummaryReportEmail::SETTINGS_SLUG:
676 /** No inspection comment @noinspection PhpUndefinedConstantInspection */
677 $return = $this->is_const_defined( $group, $key ) ?
678 $this->parse_boolean( WPMS_SUMMARY_REPORT_EMAIL_DISABLED ) :
679 $value;
680 break;
681 }
682
683 break;
684
685 default:
686 // Always return the default value if nothing from above matches the request.
687 $return = $value;
688 }
689
690 return apply_filters( 'wp_mail_smtp_options_get_const_value', $return, $group, $key, $value );
691 }
692
693 /**
694 * Whether constants redefinition is enabled or not.
695 *
696 * @since 1.0.0
697 * @since 1.5.0 Added filter to redefine the value.
698 *
699 * @return bool
700 */
701 public function is_const_enabled() {
702
703 $return = defined( 'WPMS_ON' ) && WPMS_ON === true;
704
705 return apply_filters( 'wp_mail_smtp_options_is_const_enabled', $return );
706 }
707
708 /**
709 * We need this check to reuse later in admin area,
710 * to distinguish settings fields that were redefined,
711 * and display them differently.
712 *
713 * @since 1.0.0
714 * @since 1.5.0 Added a filter, Outlook/AmazonSES, license key support.
715 * @since 1.6.0 Added Sendinblue.
716 * @since 1.7.0 Added Do Not Send.
717 * @since 1.8.0 Added Pepipost API.
718 *
719 * @param string $group
720 * @param string $key
721 *
722 * @return bool
723 */
724 public function is_const_defined( $group, $key ) {
725
726 if ( ! $this->is_const_enabled() ) {
727 return false;
728 }
729
730 // Just to feel safe.
731 $group = sanitize_key( $group );
732 $key = sanitize_key( $key );
733 $return = false;
734
735 switch ( $group ) {
736 case 'mail':
737 switch ( $key ) {
738 case 'from_name':
739 $return = defined( 'WPMS_MAIL_FROM_NAME' ) && WPMS_MAIL_FROM_NAME;
740 break;
741 case 'from_email':
742 $return = defined( 'WPMS_MAIL_FROM' ) && WPMS_MAIL_FROM;
743 break;
744 case 'mailer':
745 $return = defined( 'WPMS_MAILER' ) && WPMS_MAILER;
746 break;
747 case 'return_path':
748 $return = defined( 'WPMS_SET_RETURN_PATH' ) && ( WPMS_SET_RETURN_PATH === 'true' || WPMS_SET_RETURN_PATH === true );
749 break;
750 case 'from_name_force':
751 $return = defined( 'WPMS_MAIL_FROM_NAME_FORCE' ) && ( WPMS_MAIL_FROM_NAME_FORCE === 'true' || WPMS_MAIL_FROM_NAME_FORCE === true );
752 break;
753 case 'from_email_force':
754 $return = defined( 'WPMS_MAIL_FROM_FORCE' ) && ( WPMS_MAIL_FROM_FORCE === 'true' || WPMS_MAIL_FROM_FORCE === true );
755 break;
756 }
757
758 break;
759
760 case 'smtp':
761 switch ( $key ) {
762 case 'host':
763 $return = defined( 'WPMS_SMTP_HOST' ) && WPMS_SMTP_HOST;
764 break;
765 case 'port':
766 $return = defined( 'WPMS_SMTP_PORT' ) && WPMS_SMTP_PORT;
767 break;
768 case 'encryption':
769 $return = defined( 'WPMS_SSL' );
770 break;
771 case 'auth':
772 $return = defined( 'WPMS_SMTP_AUTH' );
773 break;
774 case 'autotls':
775 $return = defined( 'WPMS_SMTP_AUTOTLS' );
776 break;
777 case 'user':
778 $return = defined( 'WPMS_SMTP_USER' ) && WPMS_SMTP_USER;
779 break;
780 case 'pass':
781 $return = defined( 'WPMS_SMTP_PASS' ) && WPMS_SMTP_PASS;
782 break;
783 }
784
785 break;
786
787 case 'gmail':
788 switch ( $key ) {
789 case 'client_id':
790 $return = defined( 'WPMS_GMAIL_CLIENT_ID' ) && WPMS_GMAIL_CLIENT_ID;
791 break;
792 case 'client_secret':
793 $return = defined( 'WPMS_GMAIL_CLIENT_SECRET' ) && WPMS_GMAIL_CLIENT_SECRET;
794 break;
795 }
796
797 break;
798
799 case 'outlook':
800 switch ( $key ) {
801 case 'client_id':
802 $return = defined( 'WPMS_OUTLOOK_CLIENT_ID' ) && WPMS_OUTLOOK_CLIENT_ID;
803 break;
804 case 'client_secret':
805 $return = defined( 'WPMS_OUTLOOK_CLIENT_SECRET' ) && WPMS_OUTLOOK_CLIENT_SECRET;
806 break;
807 }
808
809 break;
810
811 case 'zoho':
812 switch ( $key ) {
813 case 'domain':
814 $return = defined( 'WPMS_ZOHO_DOMAIN' ) && WPMS_ZOHO_DOMAIN;
815 break;
816 case 'client_id':
817 $return = defined( 'WPMS_ZOHO_CLIENT_ID' ) && WPMS_ZOHO_CLIENT_ID;
818 break;
819 case 'client_secret':
820 $return = defined( 'WPMS_ZOHO_CLIENT_SECRET' ) && WPMS_ZOHO_CLIENT_SECRET;
821 break;
822 }
823
824 break;
825
826 case 'amazonses':
827 switch ( $key ) {
828 case 'client_id':
829 $return = defined( 'WPMS_AMAZONSES_CLIENT_ID' ) && WPMS_AMAZONSES_CLIENT_ID;
830 break;
831 case 'client_secret':
832 $return = defined( 'WPMS_AMAZONSES_CLIENT_SECRET' ) && WPMS_AMAZONSES_CLIENT_SECRET;
833 break;
834 case 'region':
835 $return = defined( 'WPMS_AMAZONSES_REGION' ) && WPMS_AMAZONSES_REGION;
836 break;
837 }
838
839 break;
840
841 case 'mailgun':
842 switch ( $key ) {
843 case 'api_key':
844 $return = defined( 'WPMS_MAILGUN_API_KEY' ) && WPMS_MAILGUN_API_KEY;
845 break;
846 case 'domain':
847 $return = defined( 'WPMS_MAILGUN_DOMAIN' ) && WPMS_MAILGUN_DOMAIN;
848 break;
849 case 'region':
850 $return = defined( 'WPMS_MAILGUN_REGION' ) && WPMS_MAILGUN_REGION;
851 break;
852 }
853
854 break;
855
856 case 'sendgrid':
857 switch ( $key ) {
858 case 'api_key':
859 $return = defined( 'WPMS_SENDGRID_API_KEY' ) && WPMS_SENDGRID_API_KEY;
860 break;
861 case 'domain':
862 $return = defined( 'WPMS_SENDGRID_DOMAIN' ) && WPMS_SENDGRID_DOMAIN;
863 break;
864 }
865
866 break;
867
868 case 'sparkpost':
869 switch ( $key ) {
870 case 'api_key':
871 $return = defined( 'WPMS_SPARKPOST_API_KEY' ) && WPMS_SPARKPOST_API_KEY;
872 break;
873 case 'region':
874 $return = defined( 'WPMS_SPARKPOST_REGION' ) && WPMS_SPARKPOST_REGION;
875 break;
876 }
877
878 break;
879
880 case 'postmark':
881 switch ( $key ) {
882 case 'server_api_token':
883 $return = defined( 'WPMS_POSTMARK_SERVER_API_TOKEN' ) && WPMS_POSTMARK_SERVER_API_TOKEN;
884 break;
885 case 'message_stream':
886 $return = defined( 'WPMS_POSTMARK_MESSAGE_STREAM' ) && WPMS_POSTMARK_MESSAGE_STREAM;
887 break;
888 }
889
890 break;
891
892 case 'smtpcom':
893 switch ( $key ) {
894 case 'api_key':
895 $return = defined( 'WPMS_SMTPCOM_API_KEY' ) && WPMS_SMTPCOM_API_KEY;
896 break;
897 case 'channel':
898 $return = defined( 'WPMS_SMTPCOM_CHANNEL' ) && WPMS_SMTPCOM_CHANNEL;
899 break;
900 }
901
902 break;
903
904 case 'sendinblue':
905 switch ( $key ) {
906 case 'api_key':
907 $return = defined( 'WPMS_SENDINBLUE_API_KEY' ) && WPMS_SENDINBLUE_API_KEY;
908 break;
909 case 'domain':
910 $return = defined( 'WPMS_SENDINBLUE_DOMAIN' ) && WPMS_SENDINBLUE_DOMAIN;
911 break;
912 }
913
914 break;
915
916 case 'pepipostapi':
917 switch ( $key ) {
918 case 'api_key':
919 $return = defined( 'WPMS_PEPIPOST_API_KEY' ) && WPMS_PEPIPOST_API_KEY;
920 break;
921 }
922
923 break;
924
925 case 'license':
926 switch ( $key ) {
927 case 'key':
928 $return = defined( 'WPMS_LICENSE_KEY' ) && WPMS_LICENSE_KEY;
929 break;
930 }
931
932 break;
933
934 case 'general':
935 switch ( $key ) {
936 case 'do_not_send':
937 /** @noinspection PhpUndefinedConstantInspection */
938 $return = defined( 'WPMS_DO_NOT_SEND' ) && WPMS_DO_NOT_SEND;
939 break;
940 case SummaryReportEmail::SETTINGS_SLUG:
941 $return = defined( 'WPMS_SUMMARY_REPORT_EMAIL_DISABLED' );
942 break;
943 }
944
945 break;
946 }
947
948 return apply_filters( 'wp_mail_smtp_options_is_const_defined', $return, $group, $key );
949 }
950
951 /**
952 * Set plugin options, all at once.
953 *
954 * @since 1.0.0
955 * @since 1.3.0 Added $once argument to save options only if they don't exist already.
956 * @since 1.4.0 Added Mailgun:region.
957 * @since 1.5.0 Added Outlook/AmazonSES, Email Log. Stop saving const values into DB.
958 * @since 2.5.0 Added $overwrite_existing method parameter.
959 *
960 * @param array $options Plugin options to save.
961 * @param bool $once Whether to update existing options or to add these options only once.
962 * @param bool $overwrite_existing Whether to overwrite existing settings or merge these passed options with existing ones.
963 */
964 public function set( $options, $once = false, $overwrite_existing = true ) {
965
966 // Merge existing settings with new values.
967 if ( ! $overwrite_existing ) {
968 $options = self::array_merge_recursive( $this->get_all_raw(), $options );
969 }
970
971 $options = $this->process_generic_options( $options );
972 $options = $this->process_mailer_specific_options( $options );
973 $options = apply_filters( 'wp_mail_smtp_options_set', $options );
974
975 // Whether to update existing options or to add these options only once if they don't exist yet.
976 if ( $once ) {
977 add_option( self::META_KEY, $options, '', 'no' ); // Do not autoload these options.
978 } else {
979 if ( is_multisite() && WP::use_global_plugin_settings() ) {
980 update_blog_option( get_main_site_id(), self::META_KEY, $options );
981 } else {
982 update_option( self::META_KEY, $options, 'no' );
983 }
984 }
985
986 // Now we need to re-cache values.
987 $this->populate_options();
988
989 do_action( 'wp_mail_smtp_options_set_after', $options );
990 }
991
992 /**
993 * Process the generic plugin options.
994 *
995 * @since 2.5.0
996 *
997 * @param array $options The options array.
998 *
999 * @return array
1000 */
1001 private function process_generic_options( $options ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded, Generic.Metrics.NestingLevel.MaxExceeded
1002
1003 foreach ( (array) $options as $group => $keys ) {
1004 foreach ( $keys as $option_name => $option_value ) {
1005 switch ( $group ) {
1006 case 'mail':
1007 switch ( $option_name ) {
1008 case 'from_name':
1009 $options[ $group ][ $option_name ] = sanitize_text_field( $option_value );
1010 break;
1011 case 'mailer':
1012 $mailer = sanitize_text_field( $option_value );
1013
1014 $mailer = in_array( $mailer, self::$mailers, true ) ? $mailer : 'mail';
1015
1016 $options[ $group ][ $option_name ] = $mailer;
1017 break;
1018 case 'from_email':
1019 if ( filter_var( $option_value, FILTER_VALIDATE_EMAIL ) ) {
1020 $options[ $group ][ $option_name ] = sanitize_email( $option_value );
1021 } else {
1022 $options[ $group ][ $option_name ] = sanitize_email(
1023 wp_mail_smtp()->get_processor()->get_default_email()
1024 );
1025 }
1026 break;
1027 case 'return_path':
1028 case 'from_name_force':
1029 case 'from_email_force':
1030 $options[ $group ][ $option_name ] = (bool) $option_value;
1031 break;
1032 }
1033 break;
1034
1035 case 'general':
1036 switch ( $option_name ) {
1037 case 'do_not_send':
1038 case 'am_notifications_hidden':
1039 case 'email_delivery_errors_hidden':
1040 case 'dashboard_widget_hidden':
1041 case 'uninstall':
1042 case UsageTracking::SETTINGS_SLUG:
1043 case SummaryReportEmail::SETTINGS_SLUG:
1044 $options[ $group ][ $option_name ] = (bool) $option_value;
1045 break;
1046 }
1047
1048 case 'debug_events':
1049 switch ( $option_name ) {
1050 case 'email_debug':
1051 $options[ $group ][ $option_name ] = (bool) $option_value;
1052 break;
1053 }
1054 }
1055 }
1056 }
1057
1058 return $options;
1059 }
1060
1061 /**
1062 * Process mailers-specific plugin options.
1063 *
1064 * @since 2.5.0
1065 *
1066 * @param array $options The options array.
1067 *
1068 * @return array
1069 */
1070 private function process_mailer_specific_options( $options ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded, Generic.Metrics.NestingLevel.MaxExceeded
1071
1072 if (
1073 ! empty( $options['mail']['mailer'] ) &&
1074 isset( $options[ $options['mail']['mailer'] ] ) &&
1075 in_array( $options['mail']['mailer'], self::$mailers, true )
1076 ) {
1077
1078 $mailer = $options['mail']['mailer'];
1079
1080 foreach ( $options[ $mailer ] as $option_name => $option_value ) {
1081 switch ( $option_name ) {
1082 case 'host': // smtp.
1083 case 'user': // smtp.
1084 case 'encryption': // smtp.
1085 case 'region': // mailgun/amazonses/sparkpost.
1086 $options[ $mailer ][ $option_name ] = $this->is_const_defined( $mailer, $option_name ) ? '' : sanitize_text_field( $option_value );
1087 break; // smtp.
1088 case 'port':
1089 $options[ $mailer ][ $option_name ] = $this->is_const_defined( $mailer, $option_name ) ? 25 : (int) $option_value;
1090 break;
1091 case 'auth': // smtp.
1092 case 'autotls': // smtp.
1093 $option_value = (bool) $option_value;
1094
1095 $options[ $mailer ][ $option_name ] = $this->is_const_defined( $mailer, $option_name ) ? false : $option_value;
1096 break;
1097
1098 case 'pass': // smtp.
1099 // Do not process as they may contain certain special characters, but allow to be overwritten using constants.
1100 $option_value = trim( (string) $option_value );
1101 $options[ $mailer ][ $option_name ] = $this->is_const_defined( $mailer, $option_name ) ? '' : $option_value;
1102
1103 if ( $mailer === 'smtp' && ! $this->is_const_defined( 'smtp', 'pass' ) ) {
1104 try {
1105 $options[ $mailer ][ $option_name ] = Crypto::encrypt( $option_value );
1106 } catch ( \Exception $e ) {} // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch, Squiz.Commenting.EmptyCatchComment.Missing, Squiz.ControlStructures.ControlSignature.NewlineAfterOpenBrace
1107 }
1108 break;
1109
1110 case 'api_key': // mailgun/sendgrid/sendinblue/pepipostapi/smtpcom/sparkpost.
1111 case 'domain': // mailgun/zoho/sendgrid/sendinblue.
1112 case 'client_id': // gmail/outlook/amazonses/zoho.
1113 case 'client_secret': // gmail/outlook/amazonses/zoho.
1114 case 'auth_code': // gmail/outlook.
1115 case 'channel': // smtpcom.
1116 case 'server_api_token': // postmark.
1117 case 'message_stream': // postmark.
1118 $options[ $mailer ][ $option_name ] = $this->is_const_defined( $mailer, $option_name ) ? '' : sanitize_text_field( $option_value );
1119 break;
1120
1121 case 'access_token': // gmail/outlook/zoho, is an array.
1122 case 'user_details': // outlook/zoho, is an array.
1123 // These options don't support constants.
1124 $options[ $mailer ][ $option_name ] = $option_value;
1125 break;
1126 }
1127 }
1128 }
1129
1130 return $options;
1131 }
1132
1133 /**
1134 * Merge recursively, including a proper substitution of values in sub-arrays when keys are the same.
1135 * It's more like array_merge() and array_merge_recursive() combined.
1136 *
1137 * @since 1.0.0
1138 *
1139 * @return array
1140 */
1141 public static function array_merge_recursive() {
1142
1143 $arrays = func_get_args();
1144
1145 if ( count( $arrays ) < 2 ) {
1146 return isset( $arrays[0] ) ? $arrays[0] : array();
1147 }
1148
1149 $merged = array();
1150
1151 while ( $arrays ) {
1152 $array = array_shift( $arrays );
1153
1154 if ( ! is_array( $array ) ) {
1155 return array();
1156 }
1157
1158 if ( empty( $array ) ) {
1159 continue;
1160 }
1161
1162 foreach ( $array as $key => $value ) {
1163 if ( is_string( $key ) ) {
1164 if (
1165 is_array( $value ) &&
1166 array_key_exists( $key, $merged ) &&
1167 is_array( $merged[ $key ] )
1168 ) {
1169 $merged[ $key ] = call_user_func( __METHOD__, $merged[ $key ], $value );
1170 } else {
1171 $merged[ $key ] = $value;
1172 }
1173 } else {
1174 $merged[] = $value;
1175 }
1176 }
1177 }
1178
1179 return $merged;
1180 }
1181
1182 /**
1183 * Check whether the site is using Pepipost SMTP or not.
1184 *
1185 * @deprecated 2.4.0
1186 *
1187 * @since 1.0.0
1188 *
1189 * @return bool
1190 */
1191 public function is_pepipost_active() {
1192
1193 _deprecated_function(
1194 __METHOD__,
1195 '2.4.0',
1196 'WPMailSMTP\Options::is_mailer_active()'
1197 );
1198
1199 return apply_filters( 'wp_mail_smtp_options_is_pepipost_active', $this->is_mailer_active( 'pepipost' ) );
1200 }
1201
1202 /**
1203 * Check whether the site is using provided mailer or not.
1204 *
1205 * @since 2.3.0
1206 *
1207 * @param string $mailer The mailer slug.
1208 *
1209 * @return bool
1210 */
1211 public function is_mailer_active( $mailer ) {
1212
1213 $mailer = sanitize_key( $mailer );
1214
1215 return apply_filters(
1216 "wp_mail_smtp_options_is_mailer_active_{$mailer}",
1217 $this->get( 'mail', 'mailer' ) === $mailer
1218 );
1219 }
1220
1221 /**
1222 * Check whether the site is using Pepipost/SMTP as a mailer or not.
1223 *
1224 * @since 1.1.0
1225 *
1226 * @return bool
1227 */
1228 public function is_mailer_smtp() {
1229 return apply_filters( 'wp_mail_smtp_options_is_mailer_smtp', in_array( $this->get( 'mail', 'mailer' ), array( 'pepipost', 'smtp' ), true ) );
1230 }
1231
1232 /**
1233 * Get all the options, but without stripping the slashes.
1234 *
1235 * @since 2.5.0
1236 *
1237 * @return array
1238 */
1239 public function get_all_raw() {
1240
1241 $options = $this->_options;
1242
1243 foreach ( $options as $group => $g_value ) {
1244 foreach ( $g_value as $key => $value ) {
1245 $options[ $group ][ $key ] = $this->get( $group, $key, false );
1246 }
1247 }
1248
1249 return $options;
1250 }
1251
1252 /**
1253 * Parse boolean value from string.
1254 *
1255 * @since 2.8.0
1256 *
1257 * @param string|boolean $value String or boolean value.
1258 *
1259 * @return boolean
1260 */
1261 public function parse_boolean( $value ) {
1262
1263 // Return early if it's boolean.
1264 if ( is_bool( $value ) ) {
1265 return $value;
1266 }
1267
1268 $value = trim( $value );
1269
1270 return $value === 'true';
1271 }
1272
1273 /**
1274 * Get a message of a constant that was set inside wp-config.php file.
1275 *
1276 * @since 2.8.0
1277 *
1278 * @param string $constant Constant name.
1279 *
1280 * @return string
1281 */
1282 public function get_const_set_message( $constant ) {
1283
1284 return sprintf( /* translators: %1$s - constant that was used; %2$s - file where it was used. */
1285 esc_html__( 'The value of this field was set using a constant %1$s most likely inside %2$s of your WordPress installation.', 'wp-mail-smtp' ),
1286 '<code>' . esc_html( $constant ) . '</code>',
1287 '<code>wp-config.php</code>'
1288 );
1289 }
1290
1291 /**
1292 * Whether option was changed.
1293 * Can be used only before option save to DB.
1294 *
1295 * @since 3.0.0
1296 *
1297 * @param string $new_value Submitted value (e.g from $_POST).
1298 * @param string $group Group key.
1299 * @param string $key Option key.
1300 *
1301 * @return bool
1302 */
1303 public function is_option_changed( $new_value, $group, $key ) {
1304
1305 $old_value = $this->get( $group, $key );
1306
1307 return $old_value !== $new_value;
1308 }
1309
1310 /**
1311 * Whether constant was changed.
1312 * Can be used only for insecure options.
1313 *
1314 * @since 3.0.0
1315 *
1316 * @param string $group Group key.
1317 * @param string $key Option key.
1318 *
1319 * @return bool
1320 */
1321 public function is_const_changed( $group, $key ) {
1322
1323 if ( ! $this->is_const_defined( $group, $key ) ) {
1324 return false;
1325 }
1326
1327 // Prevent double options update on multiple function call for same option.
1328 static $cache = [];
1329
1330 $cache_key = $group . '_' . $key;
1331
1332 if ( isset( $cache[ $cache_key ] ) ) {
1333 return $cache[ $cache_key ];
1334 }
1335
1336 $value = $this->get( $group, $key );
1337
1338 // Get old value from DB.
1339 add_filter( 'wp_mail_smtp_options_is_const_enabled', '__return_false', PHP_INT_MAX );
1340 $old_value = $this->get( $group, $key );
1341 remove_filter( 'wp_mail_smtp_options_is_const_enabled', '__return_false', PHP_INT_MAX );
1342
1343 $changed = $value !== $old_value;
1344
1345 // Save new constant value to DB.
1346 if ( $changed ) {
1347 $old_opt = $this->get_all_raw();
1348
1349 $old_opt[ $group ][ $key ] = $value;
1350 $this->set( $old_opt );
1351 }
1352
1353 $cache[ $cache_key ] = $changed;
1354
1355 return $changed;
1356 }
1357 }
1358