PluginProbe ʕ •ᴥ•ʔ
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin / 4.9.0
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin v4.9.0
4.9.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 / Core.php
wp-mail-smtp / src Last commit date
Abilities 5 days ago Admin 5 days ago Compatibility 5 days ago Helpers 5 days ago Integrations 5 days ago Providers 5 days ago Queue 5 days ago Reports 5 days ago Tasks 5 days ago TestEmail 5 days ago UsageTracking 5 days ago WPCLI 5 days ago AbstractConnection.php 5 days ago Conflicts.php 5 days ago Connect.php 5 days ago Connection.php 5 days ago ConnectionInterface.php 5 days ago ConnectionsManager.php 5 days ago Core.php 5 days ago DBRepair.php 5 days ago Debug.php 5 days ago EmailSendingDebug.php 5 days ago Geo.php 5 days ago MailCatcher.php 5 days ago MailCatcherInterface.php 5 days ago MailCatcherTrait.php 5 days ago MailCatcherV6.php 5 days ago Migration.php 5 days ago MigrationAbstract.php 5 days ago Migrations.php 5 days ago OptimizedEmailSending.php 5 days ago Options.php 5 days ago Processor.php 5 days ago SiteHealth.php 5 days ago Upgrade.php 5 days ago Uploads.php 5 days ago WP.php 5 days ago WPMailArgs.php 5 days ago WPMailInitiator.php 5 days ago
Core.php
1419 lines
1 <?php
2
3 namespace WPMailSMTP;
4
5 use Exception;
6 use ReflectionFunction;
7 use WPMailSMTP\Abilities\AbilityRegistrar;
8 use WPMailSMTP\Abilities\DebugEvents\GetDebugEventsAbility;
9 use WPMailSMTP\Admin\AdminBarMenu;
10 use WPMailSMTP\Admin\DashboardWidget;
11 use WPMailSMTP\Admin\DebugEvents\DebugEvents;
12 use WPMailSMTP\Admin\EmailSendingErrors\EmailSendingErrors;
13 use WPMailSMTP\Admin\Notifications;
14 use WPMailSMTP\Compatibility\Compatibility;
15 use WPMailSMTP\Integrations\WPCode\RegisterLibrary as RegisterWPCodeLibrary;
16 use WPMailSMTP\Providers\Outlook\Provider as OutlookProvider;
17 use WPMailSMTP\Providers\Sendlayer\QuickConnect as SendlayerQuickConnect;
18 use WPMailSMTP\Queue\Queue;
19 use WPMailSMTP\Reports\Reports;
20 use WPMailSMTP\Tasks\Meta;
21 use WPMailSMTP\UsageTracking\UsageTracking;
22 use WPMailSMTP\WPCLI\Bootstrap as WPCLIBootstrap;
23
24 /**
25 * Class Core to handle all plugin initialization.
26 *
27 * @since 1.0.0
28 */
29 class Core {
30
31 /**
32 * URL to plugin directory.
33 *
34 * @since 1.0.0
35 *
36 * @var string Without trailing slash.
37 */
38 public $plugin_url;
39
40 /**
41 * URL to Lite plugin assets directory.
42 *
43 * @since 1.5.0
44 *
45 * @var string Without trailing slash.
46 */
47 public $assets_url;
48
49 /**
50 * Path to plugin directory.
51 *
52 * @since 1.0.0
53 *
54 * @var string Without trailing slash.
55 */
56 public $plugin_path;
57
58 /**
59 * Shortcut to get access to Pro functionality using wp_mail_smtp()->pro->example().
60 *
61 * @since 1.5.0
62 *
63 * @var \WPMailSMTP\Pro\Pro
64 */
65 public $pro;
66
67 /**
68 * Abilities API registrar.
69 *
70 * @since 4.9.0
71 *
72 * @var AbilityRegistrar
73 */
74 private $abilities_registrar;
75
76 /**
77 * Core constructor.
78 *
79 * @since 1.0.0
80 */
81 public function __construct() {
82
83 $this->plugin_url = rtrim( plugin_dir_url( __DIR__ ), '/\\' );
84 $this->assets_url = $this->plugin_url . '/assets';
85 $this->plugin_path = rtrim( plugin_dir_path( __DIR__ ), '/\\' );
86
87 if ( $this->is_not_loadable() ) {
88 add_action( 'admin_notices', 'wp_mail_smtp_insecure_php_version_notice' );
89
90 if ( WP::use_global_plugin_settings() ) {
91 add_action( 'network_admin_notices', 'wp_mail_smtp_insecure_php_version_notice' );
92 }
93
94 return;
95 }
96
97 // Finally, load all the plugin.
98 $this->hooks();
99 $this->init_early();
100 }
101
102 /**
103 * Currently used for Pro version only.
104 *
105 * @since 1.5.0
106 *
107 * @return bool
108 */
109 protected function is_not_loadable() {
110
111 // Check the Pro.
112 if (
113 is_readable( $this->plugin_path . '/src/Pro/Pro.php' ) &&
114 ! $this->is_pro_allowed()
115 ) {
116 // So there is a Pro version, but its PHP version check failed.
117 return true;
118 }
119
120 return false;
121 }
122
123 /**
124 * Assign all hooks to proper places.
125 *
126 * @since 1.0.0
127 */
128 public function hooks() {
129
130 // Activation hook.
131 register_activation_hook( WPMS_PLUGIN_FILE, [ $this, 'activate' ] );
132
133 // Initialize DB migrations.
134 add_action( 'plugins_loaded', [ $this, 'get_migrations' ] );
135
136 // Load Pro if available.
137 add_action( 'plugins_loaded', [ $this, 'get_pro' ] );
138
139 // Redefine PHPMailer.
140 add_action( 'plugins_loaded', [ $this, 'get_processor' ] );
141 add_action( 'plugins_loaded', [ $this, 'replace_phpmailer' ] );
142
143 // Various notifications.
144 add_action( 'admin_init', [ $this, 'init_notifications' ] );
145
146 add_action( 'init', [ $this, 'init' ] );
147
148 // Initialize Action Scheduler tasks.
149 add_action( 'init', [ $this, 'get_tasks' ], 5 );
150
151 add_action( 'plugins_loaded', [ $this, 'get_usage_tracking' ] );
152 add_action( 'plugins_loaded', [ $this, 'get_admin_bar_menu' ] );
153 add_action( 'plugins_loaded', [ $this, 'get_notifications' ] );
154 add_action( 'plugins_loaded', [ $this, 'get_connect' ], 15 );
155 add_action( 'plugins_loaded', [ $this, 'get_compatibility' ], 0 );
156 add_action( 'plugins_loaded', [ $this, 'get_dashboard_widget' ], 20 );
157 add_action( 'plugins_loaded', [ $this, 'get_reports' ] );
158 add_action( 'plugins_loaded', [ $this, 'get_db_repair' ] );
159 add_action( 'plugins_loaded', [ $this, 'get_connections_manager' ], 20 );
160 add_action( 'plugins_loaded', [ $this, 'get_wp_mail_initiator' ] );
161 add_action( 'plugins_loaded', [ $this, 'get_queue' ] );
162 add_action(
163 'plugins_loaded',
164 function() {
165 ( new OptimizedEmailSending() )->hooks();
166 ( new OutlookProvider() )->hooks();
167 ( new SendlayerQuickConnect() )->hooks();
168 ( new EmailSendingErrors() )->hooks();
169 ( new RegisterWPCodeLibrary() )->hooks();
170 $this->get_abilities_registrar()->hooks();
171 }
172 );
173
174 if ( defined( 'WP_CLI' ) && WP_CLI ) {
175 add_action( 'init', [ new WPCLIBootstrap(), 'register' ], 20 );
176 }
177 }
178
179 /**
180 * Initial plugin actions.
181 *
182 * @since 1.0.0
183 */
184 public function init() {
185
186 // Load translations just in case.
187 load_plugin_textdomain( 'wp-mail-smtp', false, plugin_basename( wp_mail_smtp()->plugin_path ) . '/assets/languages' );
188
189 /*
190 * Constantly check in admin area, that we don't need to upgrade DB.
191 * Do not wait for the `admin_init` hook, because some actions are already done
192 * on `plugins_loaded`, so migration has to be done before.
193 * We should not fire this in AJAX requests.
194 */
195 if ( WP::in_wp_admin() ) {
196 $this->get_upgrade();
197 $this->detect_conflicts();
198 }
199
200 // In admin area, regardless of AJAX or not AJAX request.
201 if ( is_admin() ) {
202 $this->get_admin();
203 $this->get_site_health()->init();
204
205 // Register Debug Event hooks.
206 ( new DebugEvents() )->hooks();
207 }
208
209 // Plugin admin area notices. Display to "admins" only.
210 if ( current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
211 add_action( 'admin_notices', array( '\WPMailSMTP\WP', 'display_admin_notices' ) );
212 add_action( 'admin_notices', array( $this, 'display_general_notices' ) );
213
214 if ( WP::use_global_plugin_settings() ) {
215 add_action( 'network_admin_notices', array( '\WPMailSMTP\WP', 'display_admin_notices' ) );
216 add_action( 'network_admin_notices', array( $this, 'display_general_notices' ) );
217 }
218 }
219 }
220
221 /**
222 * Whether the Pro part of the plugin is allowed to be loaded.
223 *
224 * @since 1.5.0
225 * @since 1.6.0 Added a filter.
226 *
227 * @return bool
228 */
229 protected function is_pro_allowed() {
230
231 $is_allowed = true;
232
233 if ( ! is_readable( $this->plugin_path . '/src/Pro/Pro.php' ) ) {
234 $is_allowed = false;
235 }
236
237 return apply_filters( 'wp_mail_smtp_core_is_pro_allowed', $is_allowed );
238 }
239
240 /**
241 * Get/Load the Pro code of the plugin if it exists.
242 *
243 * @since 1.6.2
244 *
245 * @return \WPMailSMTP\Pro\Pro
246 */
247 public function get_pro() {
248
249 if ( ! $this->is_pro_allowed() ) {
250 return $this->pro;
251 }
252
253 if ( ! $this->is_pro() ) {
254 $this->pro = new \WPMailSMTP\Pro\Pro();
255 }
256
257 return $this->pro;
258 }
259
260 /**
261 * Get the Abilities API registrar.
262 *
263 * @since 4.9.0
264 *
265 * @return AbilityRegistrar
266 */
267 public function get_abilities_registrar() {
268
269 if ( ! isset( $this->abilities_registrar ) ) {
270 $this->abilities_registrar = new AbilityRegistrar(
271 [
272 GetDebugEventsAbility::class,
273 ]
274 );
275 }
276
277 return $this->abilities_registrar;
278 }
279
280 /**
281 * Get/Load the Tasks code of the plugin.
282 *
283 * @since 2.1.0
284 *
285 * @return \WPMailSMTP\Tasks\Tasks
286 */
287 public function get_tasks() {
288
289 static $tasks;
290
291 if ( ! isset( $tasks ) ) {
292 $tasks = apply_filters( 'wp_mail_smtp_core_get_tasks', new Tasks\Tasks() );
293 $tasks->init();
294 }
295
296 return $tasks;
297 }
298
299 /**
300 * This method allows to overwrite certain core WP functions, because it's fired:
301 * - after `muplugins_loaded` hook,
302 * - before WordPress own `wp-includes/pluggable.php` file include,
303 * - before `plugin_loaded` and `plugins_loaded` hooks.
304 *
305 * @since 1.5.0
306 */
307 protected function init_early() {
308
309 // Action Scheduler requires a special early loading procedure.
310 $this->load_action_scheduler();
311
312 // Load Pro specific files early.
313 $pro_files = $this->is_pro_allowed() ? \WPMailSMTP\Pro\Pro::PLUGGABLE_FILES : array();
314
315 $files = (array) apply_filters( 'wp_mail_smtp_core_init_early_include_files', $pro_files );
316
317 foreach ( $files as $file ) {
318 $path = $this->plugin_path . '/' . $file;
319
320 if ( is_readable( $path ) ) {
321 /** @noinspection PhpIncludeInspection */
322 include_once $path;
323 }
324 }
325 }
326
327 /**
328 * Load the plugin core processor.
329 *
330 * @since 1.0.0
331 *
332 * @return Processor
333 */
334 public function get_processor() {
335
336 static $processor;
337
338 if ( ! isset( $processor ) ) {
339
340 /**
341 * Filters Processor instance.
342 *
343 * @since 4.0.0
344 *
345 * @param Processor $processor Processor instance.
346 */
347 $processor = apply_filters(
348 'wp_mail_smtp_core_get_processor',
349 new Processor()
350 );
351
352 if ( method_exists( $processor, 'hooks' ) ) {
353 $processor->hooks();
354 }
355 }
356
357 return $processor;
358 }
359
360 /**
361 * Load the plugin admin area.
362 *
363 * @since 1.0.0
364 *
365 * @return Admin\Area
366 */
367 public function get_admin() {
368
369 static $admin;
370
371 if ( ! isset( $admin ) ) {
372 $admin = apply_filters( 'wp_mail_smtp_core_get_admin', new Admin\Area() );
373
374 if ( method_exists( $admin, 'hooks' ) ) {
375 $admin->hooks();
376 }
377 }
378
379 return $admin;
380 }
381
382 /**
383 * Load the plugin providers loader.
384 *
385 * @since 1.0.0
386 *
387 * @return Providers\Loader
388 */
389 public function get_providers() {
390
391 static $providers;
392
393 if ( ! isset( $providers ) ) {
394 $providers = apply_filters( 'wp_mail_smtp_core_get_providers', new Providers\Loader() );
395 }
396
397 return $providers;
398 }
399
400 /**
401 * Load the plugin option migrator.
402 *
403 * @deprecated 3.0.0
404 *
405 * @since 1.0.0
406 *
407 * @return Migration
408 */
409 public function get_migration() {
410
411 _deprecated_function( __METHOD__, '3.0.0' );
412
413 static $migration;
414
415 if ( ! isset( $migration ) ) {
416 $migration = apply_filters( 'wp_mail_smtp_core_get_migration', new Migration() );
417 }
418
419 return $migration;
420 }
421
422 /**
423 * Initialize DB migrations.
424 *
425 * @deprecated 4.0.0
426 *
427 * @since 3.0.0
428 */
429 public function init_migrations() {
430
431 _deprecated_function( __METHOD__, '3.10.0', '\WPMailSMTP\Migrations::init_migrations_on_request' );
432
433 $this->get_migrations()->init_migrations_on_request();
434 }
435
436 /**
437 * Get the Migrations object.
438 *
439 * @since 4.0.0
440 *
441 * @return Migrations
442 */
443 public function get_migrations() {
444
445 static $migrations;
446
447 if ( ! isset( $migrations ) ) {
448 $migrations = new Migrations();
449
450 $migrations->hooks();
451 }
452
453 return $migrations;
454 }
455
456 /**
457 * Load the plugin upgrader.
458 *
459 * @since 1.1.0
460 *
461 * @return Upgrade
462 */
463 public function get_upgrade() {
464
465 static $upgrade;
466
467 if ( ! isset( $upgrade ) ) {
468 $upgrade = apply_filters( 'wp_mail_smtp_core_get_upgrade', new Upgrade() );
469
470 if ( method_exists( $upgrade, 'run' ) ) {
471 $upgrade->run();
472 }
473 }
474
475 return $upgrade;
476 }
477
478 /**
479 * Get the plugin's WP Site Health object.
480 *
481 * @since 1.9.0
482 *
483 * @return SiteHealth
484 */
485 public function get_site_health() {
486
487 static $site_health;
488
489 if ( ! isset( $site_health ) ) {
490 $site_health = apply_filters( 'wp_mail_smtp_core_get_site_health', new SiteHealth() );
491 }
492
493 return $site_health;
494 }
495
496 /**
497 * Display various notifications to a user.
498 *
499 * @since 1.0.0
500 */
501 public function init_notifications() { }
502
503 /**
504 * Display all debug mail-delivery related notices.
505 *
506 * @since 1.3.0
507 * @since 1.6.0 Added a filter that allows to hide debug errors.
508 */
509 public static function display_general_notices() {
510
511 if ( wp_mail_smtp()->is_blocked() ) {
512 ?>
513
514 <div class="notice <?php echo esc_attr( WP::ADMIN_NOTICE_ERROR ); ?>">
515 <p>
516 <?php
517 $notices[] = sprintf(
518 /* translators: %s - plugin name and its version. */
519 __( '<strong>EMAILING DISABLED:</strong> The %s is currently blocking all emails from being sent.', 'wp-mail-smtp' ),
520 esc_html( 'WP Mail SMTP v' . WPMS_PLUGIN_VER )
521 );
522
523 if ( Options::init()->is_const_defined( 'general', 'do_not_send' ) ) {
524 $notices[] = sprintf(
525 /* translators: %1$s - constant name; %2$s - constant value. */
526 __( 'To send emails, change the value of the %1$s constant to %2$s.', 'wp-mail-smtp' ),
527 '<code>WPMS_DO_NOT_SEND</code>',
528 '<code>false</code>'
529 );
530 } else {
531 $notices[] = sprintf(
532 /* translators: %s - plugin Misc settings page URL. */
533 __( 'To send emails, go to plugin <a href="%s">Misc settings</a> and disable the "Do Not Send" option.', 'wp-mail-smtp' ),
534 esc_url( add_query_arg( 'tab', 'misc', wp_mail_smtp()->get_admin()->get_admin_page_url() ) )
535 );
536 }
537
538 if (
539 wp_mail_smtp()->get_admin()->is_admin_page( 'tools' ) &&
540 (
541 ! isset( $_GET['tab'] ) ||
542 ( isset( $_GET['tab'] ) && $_GET['tab'] === 'test' )
543 )
544 ) {
545 $notices[] = esc_html__( 'If you create a test email on this page, it will still be sent.', 'wp-mail-smtp' );
546 }
547
548 echo wp_kses_post( implode( ' ', $notices ) );
549 ?>
550 </p>
551 </div>
552
553 <?php
554 return;
555 }
556
557 if ( wp_mail_smtp()->get_admin()->is_admin_page() ) {
558 wp_mail_smtp()->wp_mail_function_incorrect_location_notice();
559 }
560 }
561
562 /**
563 * Check whether we are working with a new plugin install.
564 *
565 * @since 1.3.0
566 *
567 * @return bool
568 */
569 protected function is_new_install() {
570
571 /*
572 * No previously installed 0.*.
573 * 'wp_mail_smtp_initial_version' option appeared in 1.3.0. So we make sure it exists.
574 * No previous plugin upgrades.
575 */
576 if (
577 ! get_option( 'mailer', false ) &&
578 get_option( 'wp_mail_smtp_initial_version', false ) &&
579 version_compare( WPMS_PLUGIN_VER, get_option( 'wp_mail_smtp_initial_version' ), '=' )
580 ) {
581 return true;
582 }
583
584 return false;
585 }
586
587 /**
588 * Detect if there are plugins activated that will cause a conflict.
589 *
590 * @since 1.3.0
591 * @since 1.5.0 Moved the logic to Conflicts class.
592 */
593 public function detect_conflicts() {
594
595 // Display only for those who can actually deactivate plugins.
596 if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
597 return;
598 }
599
600 $conflicts = new Conflicts();
601
602 if ( $conflicts->is_detected() ) {
603 $conflicts->notify();
604 }
605 }
606
607 /**
608 * Init the \PHPMailer replacement.
609 *
610 * @since 1.0.0
611 *
612 * @return MailCatcherInterface
613 */
614 public function replace_phpmailer() {
615
616 global $phpmailer;
617
618 return $this->replace_w_fake_phpmailer( $phpmailer );
619 }
620
621 /**
622 * Overwrite default PhpMailer with our MailCatcher.
623 *
624 * @since 1.0.0
625 * @since 1.5.0 Throw external PhpMailer exceptions, inherits default WP behavior.
626 *
627 * @param null $obj PhpMailer object to override with own implementation.
628 *
629 * @return MailCatcherInterface
630 */
631 protected function replace_w_fake_phpmailer( &$obj = null ) {
632
633 $obj = $this->generate_mail_catcher( true );
634
635 return $obj;
636 }
637
638 /**
639 * What to do on plugin activation.
640 *
641 * @since 1.0.0
642 * @since 2.0.0 Changed from general `plugin_activate` hook to this plugin specific activation hook.
643 */
644 public function activate() {
645
646 // Store the plugin version when initial install occurred.
647 add_option( 'wp_mail_smtp_initial_version', WPMS_PLUGIN_VER, '', false );
648
649 // Store the plugin version activated to reference with upgrades.
650 update_option( 'wp_mail_smtp_version', WPMS_PLUGIN_VER, false );
651
652 // Save default options, only once.
653 Options::init()->set( Options::get_defaults(), true );
654
655 /**
656 * Store the timestamp of first plugin activation.
657 *
658 * @since 2.1.0
659 */
660 add_option( 'wp_mail_smtp_activated_time', time(), '', false );
661
662 /**
663 * Store the timestamp of the first plugin activation by license type.
664 *
665 * @since 2.3.0
666 */
667 $license_type = is_readable( $this->plugin_path . '/src/Pro/Pro.php' ) ? 'pro' : 'lite';
668 $activated = get_option( 'wp_mail_smtp_activated', [] );
669
670 if ( empty( $activated[ $license_type ] ) ) {
671 $activated[ $license_type ] = time();
672 update_option( 'wp_mail_smtp_activated', $activated );
673 }
674
675 set_transient( 'wp_mail_smtp_just_activated', true, 60 );
676
677 // Add transient to trigger redirect to the Setup Wizard.
678 set_transient( 'wp_mail_smtp_activation_redirect', true, 30 );
679 }
680
681 /**
682 * Whether this is a Pro version of a plugin.
683 *
684 * @since 1.5.0
685 *
686 * @return bool
687 */
688 public function is_pro() {
689
690 return apply_filters( 'wp_mail_smtp_core_is_pro', ! empty( $this->pro ) );
691 }
692
693 /**
694 * Get the current license type.
695 *
696 * @since 1.5.0
697 *
698 * @return string Default value: lite.
699 */
700 public function get_license_type() {
701
702 $type = Options::init()->get( 'license', 'type' );
703
704 if ( empty( $type ) ) {
705 $type = 'lite';
706 }
707
708 return strtolower( $type );
709 }
710
711 /**
712 * Get the current license key.
713 *
714 * @since 1.5.0
715 *
716 * @return string
717 */
718 public function get_license_key() {
719
720 $key = Options::init()->get( 'license', 'key' );
721
722 if ( empty( $key ) ) {
723 $key = '';
724 }
725
726 return $key;
727 }
728
729 /**
730 * Upgrade link used within the various admin pages.
731 *
732 * @since 1.5.0
733 * @since 1.5.1 Support all UTM params.
734 *
735 * @param array|string $utm Array of UTM params, or if string provided - utm_content URL parameter.
736 *
737 * @return string
738 */
739 public function get_upgrade_link( $utm ) {
740
741 $url = $this->get_utm_url( 'https://wpmailsmtp.com/lite-upgrade/', $utm );
742
743 /**
744 * Filters upgrade link.
745 *
746 * @since 1.5.0
747 *
748 * @param string $url Upgrade link.
749 */
750 return apply_filters( 'wp_mail_smtp_core_get_upgrade_link', $url );
751 }
752
753 /**
754 * Get UTM URL.
755 *
756 * @since 3.4.0
757 *
758 * @param string $url Base url.
759 * @param array|string $utm Array of UTM params, or if string provided - utm_content URL parameter.
760 *
761 * @return string
762 */
763 public function get_utm_url( $url, $utm ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
764
765 // Defaults.
766 $source = 'WordPress';
767 $medium = 'plugin-settings';
768 $campaign = $this->is_pro() ? 'plugin' : 'liteplugin';
769 $content = 'general';
770 $locale = get_user_locale();
771
772 if ( is_array( $utm ) ) {
773 if ( isset( $utm['source'] ) ) {
774 $source = $utm['source'];
775 }
776 if ( isset( $utm['medium'] ) ) {
777 $medium = $utm['medium'];
778 }
779 if ( isset( $utm['campaign'] ) ) {
780 $campaign = $utm['campaign'];
781 }
782 if ( isset( $utm['content'] ) ) {
783 $content = $utm['content'];
784 }
785 if ( isset( $utm['locale'] ) ) {
786 $locale = $utm['locale'];
787 }
788 } elseif ( is_string( $utm ) ) {
789 $content = $utm;
790 }
791
792 $query_args = [
793 'utm_source' => esc_attr( rawurlencode( $source ) ),
794 'utm_medium' => esc_attr( rawurlencode( $medium ) ),
795 'utm_campaign' => esc_attr( rawurlencode( $campaign ) ),
796 'utm_locale' => esc_attr( sanitize_key( $locale ) ),
797 ];
798
799 if ( ! empty( $content ) ) {
800 $query_args['utm_content'] = esc_attr( rawurlencode( $content ) );
801 }
802
803 return add_query_arg( $query_args, $url );
804 }
805
806 /**
807 * Whether the emailing functionality is blocked, with either an option or a constatnt.
808 *
809 * @since 1.7.0
810 *
811 * @return bool
812 */
813 public function is_blocked() {
814
815 return (bool) Options::init()->get( 'general', 'do_not_send' );
816 }
817
818 /**
819 * Whether the white-labeling is enabled.
820 * White-labeling disables the plugin "About us" page, it replaces any plugin marketing texts or images with
821 * white label ones.
822 *
823 * @since 2.0.0
824 *
825 * @return bool
826 */
827 public function is_white_labeled() {
828
829 return (bool) apply_filters( 'wp_mail_smtp_is_white_labeled', false );
830 }
831
832 /**
833 * Require the action scheduler in an early plugins_loaded hook (-10).
834 *
835 * @see https://actionscheduler.org/usage/#load-order
836 *
837 * @since 2.1.0
838 */
839 public function load_action_scheduler() {
840
841 require_once $this->plugin_path . '/vendor/woocommerce/action-scheduler/action-scheduler.php';
842 }
843
844 /**
845 * Get the list of all custom DB tables that should be present in the DB.
846 *
847 * @since 2.1.2
848 *
849 * @return array List of table names.
850 */
851 public function get_custom_db_tables() {
852
853 $tables = [
854 Meta::get_table_name(),
855 DebugEvents::get_table_name(),
856 ];
857
858 if ( $this->get_queue()->is_enabled() ) {
859 $tables[] = Queue::get_table_name();
860 }
861
862 return apply_filters( 'wp_mail_smtp_core_get_custom_db_tables', $tables );
863 }
864
865 /**
866 * Generate the correct MailCatcher object based on the PHPMailer version used in WP.
867 *
868 * Also conditionally require the needed class files.
869 *
870 * @see https://make.wordpress.org/core/2020/07/01/external-library-updates-in-wordpress-5-5-call-for-testing/
871 *
872 * @since 2.2.0
873 *
874 * @param bool $exceptions True if external exceptions should be thrown.
875 *
876 * @return MailCatcherInterface
877 */
878 public function generate_mail_catcher( $exceptions = null ) {
879
880 $is_old_version = version_compare( get_bloginfo( 'version' ), '5.5-alpha', '<' );
881
882 if ( $is_old_version ) {
883 if ( ! class_exists( '\PHPMailer', false ) ) {
884 require_once ABSPATH . WPINC . '/class-phpmailer.php';
885 }
886
887 $class_name = MailCatcher::class;
888 } else {
889 if ( ! class_exists( '\PHPMailer\PHPMailer\PHPMailer', false ) ) {
890 require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
891 }
892
893 if ( ! class_exists( '\PHPMailer\PHPMailer\Exception', false ) ) {
894 require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
895 }
896
897 if ( ! class_exists( '\PHPMailer\PHPMailer\SMTP', false ) ) {
898 require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php';
899 }
900
901 $class_name = MailCatcherV6::class;
902 }
903
904 /**
905 * Filters MailCatcher class name.
906 *
907 * @since 3.7.0
908 *
909 * @param string $mail_catcher The MailCatcher class name.
910 */
911 $class_name = apply_filters( 'wp_mail_smtp_core_generate_mail_catcher', $class_name );
912
913 $mail_catcher = new $class_name( $exceptions );
914
915 if ( $is_old_version ) {
916 $mail_catcher::$validator = static function ( $email ) {
917 return (bool) is_email( $email );
918 };
919 }
920
921 return $mail_catcher;
922 }
923
924 /**
925 * Check if the passed object is a valid PHPMailer object.
926 *
927 * @since 2.2.0
928 *
929 * @param object $phpmailer A potential PHPMailer object to be tested.
930 *
931 * @return bool
932 */
933 public function is_valid_phpmailer( $phpmailer ) {
934
935 return $phpmailer instanceof MailCatcherInterface ||
936 $phpmailer instanceof \PHPMailer ||
937 $phpmailer instanceof \PHPMailer\PHPMailer\PHPMailer;
938 }
939
940 /**
941 * Force the `mail.from_email_force` plugin option to always return true if the current saved mailer is Gmail.
942 * Alters the plugin options retrieving via the Options::get method.
943 *
944 * The gmail mailer check is performed when this filter is added.
945 *
946 * @deprecated 2.7.0
947 *
948 * @since 2.2.0
949 *
950 * @param mixed $value The value of the plugin option that is being retrieved via Options::get method.
951 * @param string $group The group of the plugin option that is being retrieved via Options::get method.
952 * @param string $key The key of the plugin option that is being retrieved via Options::get method.
953 *
954 * @return mixed
955 */
956 public function gmail_mailer_get_from_email_force( $value, $group, $key ) {
957
958 _deprecated_function( __METHOD__, '2.7.0' );
959
960 if ( $group === 'mail' && $key === 'from_email_force' ) {
961 $value = true;
962 }
963
964 return $value;
965 }
966
967 /**
968 * Load the plugin admin bar menu and initialize it.
969 *
970 * @since 2.3.0
971 *
972 * @return AdminBarMenu
973 */
974 public function get_admin_bar_menu() {
975
976 static $admin_bar_menu;
977
978 if ( ! isset( $admin_bar_menu ) ) {
979 $admin_bar_menu = apply_filters(
980 'wp_mail_smtp_core_get_admin_bar_menu',
981 new AdminBarMenu()
982 );
983
984 if ( method_exists( $admin_bar_menu, 'init' ) ) {
985 $admin_bar_menu->init();
986 }
987 }
988
989 return $admin_bar_menu;
990 }
991
992 /**
993 * Load the plugin usage tracking.
994 *
995 * @since 2.3.0
996 *
997 * @return UsageTracking
998 */
999 public function get_usage_tracking() {
1000
1001 static $usage_tracking;
1002
1003 if ( ! isset( $usage_tracking ) ) {
1004 $usage_tracking = apply_filters( 'wp_mail_smtp_core_get_usage_tracking', new UsageTracking() );
1005
1006 if ( method_exists( $usage_tracking, 'load' ) ) {
1007 add_action( 'after_setup_theme', [ $usage_tracking, 'load' ] );
1008 }
1009 }
1010
1011 return $usage_tracking;
1012 }
1013
1014 /**
1015 * Load the plugin admin notifications functionality and initializes it.
1016 *
1017 * @since 2.3.0
1018 *
1019 * @return Notifications
1020 */
1021 public function get_notifications() {
1022
1023 static $notifications;
1024
1025 if ( ! isset( $notifications ) ) {
1026 $notifications = apply_filters(
1027 'wp_mail_smtp_core_get_notifications',
1028 new Notifications()
1029 );
1030
1031 if ( method_exists( $notifications, 'init' ) ) {
1032 $notifications->init();
1033 }
1034 }
1035
1036 return $notifications;
1037 }
1038
1039 /**
1040 * Prepare the HTML output for a plugin loader/spinner.
1041 *
1042 * @since 2.4.0
1043 *
1044 * @param string $color The color of the loader ('', 'blue' or 'white'), where '' is default orange.
1045 * @param string $size The size of the loader ('lg', 'md', 'sm').
1046 *
1047 * @return string
1048 */
1049 public function prepare_loader( $color = '', $size = 'md' ) {
1050
1051 $svg_name = 'loading';
1052
1053 if ( in_array( $color, [ 'blue', 'white' ], true ) ) {
1054 $svg_name .= '-' . $color;
1055 }
1056
1057 if ( ! in_array( $size, [ 'lg', 'md', 'sm' ], true ) ) {
1058 $size = 'md';
1059 }
1060
1061 return '<img src="' . esc_url( $this->plugin_url . '/assets/images/loaders/' . $svg_name . '.svg' ) . '" alt="' . esc_attr__( 'Loading', 'wp-mail-smtp' ) . '" class="wp-mail-smtp-loading wp-mail-smtp-loading-' . $size . '">';
1062 }
1063
1064 /**
1065 * Initialize the Connect functionality.
1066 * This has to execute after pro was loaded, since we need check for plugin license type (if pro or not).
1067 * That's why it's hooked to the same WP hook (`plugins_loaded`) as `get_pro` with lower priority.
1068 *
1069 * @since 2.6.0
1070 */
1071 public function get_connect() {
1072
1073 static $connect;
1074
1075 if ( ! isset( $connect ) && ! $this->is_pro() ) {
1076 $connect = apply_filters( 'wp_mail_smtp_core_get_connect', new Connect() );
1077
1078 if ( method_exists( $connect, 'hooks' ) ) {
1079 $connect->hooks();
1080 }
1081 }
1082
1083 return $connect;
1084 }
1085
1086 /**
1087 * Load the plugin compatibility functionality and initializes it.
1088 *
1089 * @since 2.8.0
1090 *
1091 * @return Compatibility
1092 */
1093 public function get_compatibility() {
1094
1095 static $compatibility;
1096
1097 if ( ! isset( $compatibility ) ) {
1098
1099 /**
1100 * Filters compatibility instance.
1101 *
1102 * @since 2.8.0
1103 *
1104 * @param \WPMailSMTP\Compatibility\Compatibility $compatibility Compatibility instance.
1105 */
1106 $compatibility = apply_filters( 'wp_mail_smtp_core_get_compatibility', new Compatibility() );
1107
1108 if ( method_exists( $compatibility, 'init' ) ) {
1109 $compatibility->init();
1110 }
1111 }
1112
1113 return $compatibility;
1114 }
1115
1116 /**
1117 * Get the Dashboard Widget object (lite or pro version).
1118 *
1119 * @since 2.9.0
1120 *
1121 * @return DashboardWidget
1122 */
1123 public function get_dashboard_widget() {
1124
1125 static $dashboard_widget;
1126
1127 if ( ! isset( $dashboard_widget ) ) {
1128
1129 /**
1130 * Filter the dashboard widget class name.
1131 *
1132 * @since 2.9.0
1133 *
1134 * @param DashboardWidget $class_name The dashboard widget class name to be instantiated.
1135 */
1136 $class_name = apply_filters( 'wp_mail_smtp_core_get_dashboard_widget', DashboardWidget::class );
1137 $dashboard_widget = new $class_name();
1138
1139 if ( method_exists( $dashboard_widget, 'init' ) ) {
1140 $dashboard_widget->init();
1141 }
1142 }
1143
1144 return $dashboard_widget;
1145 }
1146
1147 /**
1148 * Get the reports object (lite or pro version).
1149 *
1150 * @since 3.0.0
1151 *
1152 * @return Reports
1153 */
1154 public function get_reports() {
1155
1156 static $reports;
1157
1158 if ( ! isset( $reports ) ) {
1159
1160 /**
1161 * Filter the reports class name.
1162 *
1163 * @since 3.0.0
1164 *
1165 * @param Reports $class_name The reports class name to be instantiated.
1166 */
1167 $class_name = apply_filters( 'wp_mail_smtp_core_get_reports', Reports::class );
1168 $reports = new $class_name();
1169
1170 if ( method_exists( $reports, 'init' ) ) {
1171 $reports->init();
1172 }
1173 }
1174
1175 return $reports;
1176 }
1177
1178 /**
1179 * Get the DBRepair object (lite or pro version).
1180 *
1181 * @since 3.6.0
1182 *
1183 * @return DBRepair
1184 */
1185 public function get_db_repair() {
1186
1187 static $db_repair;
1188
1189 if ( ! isset( $db_repair ) ) {
1190
1191 /**
1192 * Filter the DBRepair class name.
1193 *
1194 * @since 3.6.0
1195 *
1196 * @param DBRepair $class_name The reports class name to be instantiated.
1197 */
1198 $class_name = apply_filters( 'wp_mail_smtp_core_get_db_repair', DBRepair::class );
1199 $db_repair = new $class_name();
1200
1201 if ( method_exists( $db_repair, 'hooks' ) ) {
1202 $db_repair->hooks();
1203 }
1204 }
1205
1206 return $db_repair;
1207 }
1208
1209 /**
1210 * Get connections manager.
1211 *
1212 * @since 3.7.0
1213 *
1214 * @return ConnectionsManager
1215 */
1216 public function get_connections_manager() {
1217
1218 static $connections_manager = null;
1219
1220 if ( is_null( $connections_manager ) ) {
1221
1222 /**
1223 * Filter the connections manager class name.
1224 *
1225 * @since 3.7.0
1226 *
1227 * @param ConnectionsManager $connections_manager The connections manager class name to be instantiated.
1228 */
1229 $class_name = apply_filters( 'wp_mail_smtp_core_get_connections_manager', ConnectionsManager::class );
1230 $connections_manager = new $class_name();
1231
1232 if ( method_exists( $connections_manager, 'hooks' ) ) {
1233 $connections_manager->hooks();
1234 }
1235 }
1236
1237 return $connections_manager;
1238 }
1239
1240 /**
1241 * Get the `wp_mail` function initiator.
1242 *
1243 * @since 3.7.0
1244 *
1245 * @return WPMailInitiator
1246 */
1247 public function get_wp_mail_initiator() {
1248
1249 static $wp_mail_initiator = null;
1250
1251 if ( is_null( $wp_mail_initiator ) ) {
1252
1253 /**
1254 * Filter the `wp_mail` function initiator class name.
1255 *
1256 * @since 3.7.0
1257 *
1258 * @param WPMailInitiator $wp_mail_initiator The `wp_mail` function initiator class name to be instantiated.
1259 */
1260 $class_name = apply_filters( 'wp_mail_smtp_core_get_wp_mail_initiator', WPMailInitiator::class );
1261 $wp_mail_initiator = new $class_name();
1262
1263 if ( method_exists( $wp_mail_initiator, 'hooks' ) ) {
1264 $wp_mail_initiator->hooks();
1265 }
1266 }
1267
1268 return $wp_mail_initiator;
1269 }
1270
1271 /**
1272 * Detect incorrect `wp_mail` function location and display warning.
1273 *
1274 * @since 3.5.0
1275 */
1276 private function wp_mail_function_incorrect_location_notice() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
1277
1278 /**
1279 * Filters whether to display incorrect `wp_mail` function location warning.
1280 *
1281 * @since 3.5.0
1282 *
1283 * @param bool $display Whether to display incorrect `wp_mail` function location warning.
1284 */
1285 $display_notice = apply_filters( 'wp_mail_smtp_core_wp_mail_function_incorrect_location_notice', true );
1286
1287 if ( ! $display_notice || ! defined( 'ABSPATH' ) || ! defined( 'WPINC' ) ) {
1288 return;
1289 }
1290
1291 try {
1292 $wp_mail_reflection = new ReflectionFunction( 'wp_mail' );
1293 $wp_mail_filepath = $wp_mail_reflection->getFileName();
1294 $separator = defined( 'DIRECTORY_SEPARATOR' ) ? DIRECTORY_SEPARATOR : '/';
1295
1296 $wp_mail_original_filepath = ABSPATH . WPINC . $separator . 'pluggable.php';
1297
1298 if ( str_replace( '\\', '/', $wp_mail_filepath ) === str_replace( '\\', '/', $wp_mail_original_filepath ) ) {
1299 return;
1300 }
1301
1302 if ( strpos( $wp_mail_filepath, WPINC . $separator . 'pluggable.php' ) !== false ) {
1303 return;
1304 }
1305
1306 $conflict = WP::get_initiator( $wp_mail_filepath );
1307
1308 $message = esc_html__( 'WP Mail SMTP has detected incorrect "wp_mail" function location. Usually, this means that emails will not be sent successfully!', 'wp-mail-smtp' );
1309
1310 if ( $conflict['type'] === 'plugin' ) {
1311 $message .= '<br><br>' . sprintf(
1312 /* translators: %s - plugin name. */
1313 esc_html__( 'It looks like the "%s" plugin is overwriting the "wp_mail" function. Please reach out to the plugin developer on how to disable or remove the "wp_mail" function overwrite to prevent conflicts with WP Mail SMTP.', 'wp-mail-smtp' ),
1314 esc_html( $conflict['name'] )
1315 );
1316 } elseif ( $conflict['type'] === 'mu-plugin' ) {
1317 $message .= '<br><br>' . sprintf(
1318 /* translators: %s - must-use plugin name. */
1319 esc_html__( 'It looks like the "%s" must-use plugin is overwriting the "wp_mail" function. Please reach out to your hosting provider on how to disable or remove the "wp_mail" function overwrite to prevent conflicts with WP Mail SMTP.', 'wp-mail-smtp' ),
1320 esc_html( $conflict['name'] )
1321 );
1322 } elseif ( $wp_mail_filepath === ABSPATH . 'wp-config.php' ) {
1323 $message .= '<br><br>' . esc_html__( 'It looks like it\'s overwritten in the "wp-config.php" file. Please reach out to your hosting provider on how to disable or remove the "wp_mail" function overwrite to prevent conflicts with WP Mail SMTP.', 'wp-mail-smtp' );
1324 }
1325
1326 $message .= '<br><br>' . sprintf(
1327 /* translators: %s - path. */
1328 esc_html__( 'Current function path: %s', 'wp-mail-smtp' ),
1329 $wp_mail_filepath . ':' . $wp_mail_reflection->getStartLine()
1330 );
1331
1332 printf(
1333 '<div class="notice %1$s"><p>%2$s</p></div>',
1334 esc_attr( WP::ADMIN_NOTICE_ERROR ),
1335 wp_kses( $message, [ 'br' => [] ] )
1336 );
1337 } catch ( Exception $e ) {
1338 return;
1339 }
1340 }
1341
1342 /**
1343 * Get the default capability to manage everything for WP Mail SMTP.
1344 *
1345 * @since 3.11.0
1346 *
1347 * @return string
1348 */
1349 public function get_capability_manage_options() {
1350
1351 /**
1352 * Filters the default capability to manage everything for WP Mail SMTP.
1353 *
1354 * @since 3.11.0
1355 *
1356 * @param string $capability The default capability to manage everything for WP Mail SMTP.
1357 */
1358 return apply_filters( 'wp_mail_smtp_core_get_capability_manage_options', 'manage_options' );
1359 }
1360
1361 /**
1362 * Capability required to manage WP Mail SMTP actions that operate on global plugin state.
1363 *
1364 * Returns `manage_network_options` on multisite when WP Mail SMTP's network-wide settings
1365 * mode is on, and `manage_options` otherwise. Use this getter (rather than
1366 * {@see Core::get_capability_manage_options()}) when the gated action reads or writes
1367 * state that lives on the main site / network scope in network-wide mode (the
1368 * `wp_mail_smtp` and `wp_mail_smtp_connections` option rows, license fields, OAuth
1369 * credentials, alerts subscriptions). Naming mirrors {@see WP::use_global_plugin_settings()}.
1370 *
1371 * @since 4.9.0
1372 *
1373 * @return string
1374 */
1375 public function get_capability_manage_global_options() {
1376
1377 $default = ( is_multisite() && WP::use_global_plugin_settings() )
1378 ? 'manage_network_options'
1379 : 'manage_options';
1380
1381 /**
1382 * Filters the capability required to manage global WP Mail SMTP actions.
1383 *
1384 * @since 4.9.0
1385 *
1386 * @param string $capability The default capability for global actions. Defaults to
1387 * `manage_network_options` on multisite when network-wide
1388 * settings are on, and `manage_options` otherwise.
1389 */
1390 return apply_filters( 'wp_mail_smtp_core_get_capability_manage_global_options', $default );
1391 }
1392
1393 /**
1394 * Load the queue functionality.
1395 *
1396 * @since 4.0.0
1397 *
1398 * @return Queue
1399 */
1400 public function get_queue() {
1401
1402 static $queue;
1403
1404 if ( ! isset( $queue ) ) {
1405 /**
1406 * Filter the Queue object.
1407 *
1408 * @since 4.0.0
1409 *
1410 * @param Queue $queue The Queue object.
1411 */
1412 $queue = apply_filters( 'wp_mail_smtp_core_get_queue', new Queue() );
1413 }
1414
1415 return $queue;
1416 }
1417
1418 }
1419