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