| 1 |
<?php |
| 2 |
|
| 3 |
/** |
| 4 |
* Plugin Name: WPO365 | MICROSOFT 365 GRAPH MAILER |
| 5 |
* Plugin URI: https://wordpress.org/plugins/wpo365-msgraphmailer |
| 6 |
* Description: WPO365 | MS GRAPH MAILER re-configures your WordPress website to send transactional emails from one of your Microsoft 365 Exchange Online / Mail enabled accounts using Microsoft Graph instead of - for example - using SMTP. |
| 7 |
* Version: 2.34 |
| 8 |
* Author: marco@wpo365.com |
| 9 |
* Author URI: https://www.wpo365.com |
| 10 |
* License: GPL2+ |
| 11 |
*/ |
| 12 |
|
| 13 |
namespace Wpo; |
| 14 |
|
| 15 |
require __DIR__ . '/vendor/autoload.php'; |
| 16 |
|
| 17 |
use \Wpo\Core\Globals; |
| 18 |
use \Wpo\Core\Permissions_Helpers; |
| 19 |
use \Wpo\Services\Dependency_Service; |
| 20 |
use \Wpo\Services\Options_Service; |
| 21 |
use \Wpo\Services\Request_Service; |
| 22 |
use \Wpo\Services\Router_Service; |
| 23 |
|
| 24 |
// Prevent public access to this script |
| 25 |
defined('ABSPATH') or die(); |
| 26 |
|
| 27 |
if (!class_exists('\Wpo\MsGraphMailer')) { |
| 28 |
|
| 29 |
class MsGraphMailer |
| 30 |
{ |
| 31 |
|
| 32 |
private $dependencies; |
| 33 |
|
| 34 |
private $no_conflict = true; |
| 35 |
|
| 36 |
public function __construct() |
| 37 |
{ |
| 38 |
$this->deactivation_hooks(); |
| 39 |
add_action('plugins_loaded', array($this, 'load'), 1); |
| 40 |
add_filter('cron_schedules', '\Wpo\Core\Cron_Helpers::add_cron_schedules', 10, 1); |
| 41 |
} |
| 42 |
|
| 43 |
public function load() |
| 44 |
{ |
| 45 |
// If WPO365 | LOGIN exists and is active then do not initialize this plugin. |
| 46 |
if (\file_exists(dirname(__DIR__) . '/wpo365-login')) { |
| 47 |
include_once(ABSPATH . 'wp-admin/includes/plugin.php'); |
| 48 |
|
| 49 |
if (is_plugin_active('wpo365-login/wpo365-login.php')) { |
| 50 |
add_action('admin_notices', array($this, 'ensure_wpo365_login'), 10, 0); |
| 51 |
return; |
| 52 |
} |
| 53 |
} |
| 54 |
|
| 55 |
Globals::set_global_vars(__FILE__, __DIR__); |
| 56 |
$this->cache_dependencies(); |
| 57 |
Options_Service::ensure_options_cache(); |
| 58 |
$this->update_request_log(); |
| 59 |
$this->add_wp_hooks(); |
| 60 |
Router_Service::has_route(); |
| 61 |
} |
| 62 |
|
| 63 |
public function ensure_wpo365_login() |
| 64 |
{ |
| 65 |
echo '<div class="notice notice-error" style="margin-left: 2px;"><p>' |
| 66 |
. 'The <strong>WPO365 | MS GRAPH MAILER</strong> plugin has detected that you have also installed the <strong>WPO365 | LOGIN</strong> plugin. ' |
| 67 |
. 'Since that plugin offers the same functionality <a href="https://www.wpo365.com/features/" target="_blank">plus a lot more</a> and uses the ' |
| 68 |
. 'same configuration-source, the <em>Microsoft Graph Mailer</em> of the <strong>WPO365 | LOGIN</strong> plugin will be used instead. ' |
| 69 |
. '<br><br>' |
| 70 |
. 'See the <a href="https://docs.wpo365.com/article/141-send-email-using-microsoft-graph-mailer" target="_blank">online documentation</a> for details.' |
| 71 |
. '</p></div>'; |
| 72 |
} |
| 73 |
|
| 74 |
private function cache_dependencies() |
| 75 |
{ |
| 76 |
$this->dependencies = Dependency_Service::get_instance(); |
| 77 |
$this->dependencies->add('Request_Service', Request_Service::get_instance(true)); |
| 78 |
} |
| 79 |
|
| 80 |
private function add_wp_hooks() |
| 81 |
{ |
| 82 |
// Plugin updater and license checker |
| 83 |
// Plugin updater and license checker |
| 84 |
if (class_exists('\Wpo\Core\Plugin_Updater')) { |
| 85 |
\Wpo\Core\Plugin_Updater::add_hooks(); |
| 86 |
} |
| 87 |
|
| 88 |
// Do super admin stuff |
| 89 |
if ((is_admin() || is_network_admin()) && Permissions_Helpers::user_is_admin(\wp_get_current_user())) { |
| 90 |
|
| 91 |
// Add and hide wizard (page) |
| 92 |
add_action('admin_menu', '\Wpo\Pages\Wizard_Page::add_management_page'); |
| 93 |
add_action('network_admin_menu', '\Wpo\Pages\Wizard_Page::add_management_page'); |
| 94 |
|
| 95 |
new \Wpo\Pages\License_Page(); |
| 96 |
|
| 97 |
// Show admin notification when WPO365 not properly configured |
| 98 |
add_action('admin_notices', '\Wpo\Services\Notifications_Service::show_admin_notices', 10, 0); |
| 99 |
add_action('network_admin_notices', '\Wpo\Services\Notifications_Service::show_admin_notices', 10, 0); |
| 100 |
add_action('admin_init', '\Wpo\Services\Notifications_Service::dismiss_admin_notices', 10, 0); |
| 101 |
|
| 102 |
// Wire up AJAX backend services |
| 103 |
add_action('wp_ajax_wpo365_delete_settings', '\Wpo\Services\Ajax_Service::delete_settings'); |
| 104 |
add_action('wp_ajax_wpo365_delete_tokens', '\Wpo\Services\Ajax_Service::delete_tokens'); |
| 105 |
add_action('wp_ajax_wpo365_get_settings', '\Wpo\Services\Ajax_Service::get_settings'); |
| 106 |
add_action('wp_ajax_wpo365_update_settings', '\Wpo\Services\Ajax_Service::update_settings'); |
| 107 |
add_action('wp_ajax_wpo365_get_log', '\Wpo\Services\Ajax_Service::get_log'); |
| 108 |
add_action('wp_ajax_wpo365_dismiss_wpo_health_messages', '\Wpo\Services\Ajax_Service::dismiss_wpo_health_messages'); |
| 109 |
add_action('wp_ajax_wpo365_get_wpo_health_messages', '\Wpo\Services\Ajax_Service::get_wpo_health_messages'); |
| 110 |
add_action('wp_ajax_wpo365_get_parseable_options', '\Wpo\Services\Ajax_Service::get_parseable_options'); |
| 111 |
add_action('wp_ajax_wpo365_get_insights_summary', '\Wpo\Services\Ajax_Service::get_insights_summary'); |
| 112 |
add_action('wp_ajax_wpo365_get_insights', '\Wpo\Services\Ajax_Service::get_insights'); |
| 113 |
add_action('wp_ajax_wpo365_truncate_insights_data', '\Wpo\Services\Ajax_Service::truncate_insights_data'); |
| 114 |
|
| 115 |
// Graph mailer |
| 116 |
add_action('wp_ajax_wpo365_send_test_mail', '\Wpo\Services\Ajax_Service::send_test_mail'); |
| 117 |
add_action('wp_ajax_wpo365_get_mail_authorization_url', '\Wpo\Services\Ajax_Service::get_mail_authorization_url'); |
| 118 |
add_action('wp_ajax_wpo365_get_mail_auth_configuration', '\Wpo\Services\Ajax_Service::get_mail_auth_configuration'); |
| 119 |
add_action('wp_ajax_wpo365_try_migrate_mail_app_principal_info', '\Wpo\Services\Ajax_Service::try_migrate_mail_app_principal_info'); |
| 120 |
|
| 121 |
// Graph mailer auditing |
| 122 |
if (class_exists('\Wpo\Mail\Mail_Db')) { |
| 123 |
// Wire up AJAX backend services |
| 124 |
add_action('wp_ajax_wpo365_get_mail_log', '\Wpo\Mail\Mail_Ajax_Service::get_mail_log'); |
| 125 |
add_action('wp_ajax_wpo365_send_mail_again', '\Wpo\Mail\Mail_Ajax_Service::send_mail_again'); |
| 126 |
add_action('wp_ajax_wpo365_truncate_mail_log', '\Wpo\Mail\Mail_Ajax_Service::truncate_mail_log'); |
| 127 |
|
| 128 |
if (method_exists('\Wpo\Mail\Mail_Ajax_Service', 'mail_auto_retry')) { |
| 129 |
add_action('wp_ajax_wpo365_mail_auto_retry', '\Wpo\Mail\Mail_Ajax_Service::mail_auto_retry'); |
| 130 |
} |
| 131 |
} |
| 132 |
|
| 133 |
// Show settings link |
| 134 |
add_filter((is_network_admin() ? 'network_admin_' : '') . 'plugin_action_links_' . $GLOBALS['WPO_CONFIG']['plugin'], '\Wpo\Core\Plugin_Helpers::get_configuration_action_link', 10, 1); |
| 135 |
|
| 136 |
// Add license related messages to WP Admin |
| 137 |
\Wpo\Core\Plugin_Updater::show_license_notices(); |
| 138 |
|
| 139 |
// Ensure WP Cron job to check for each registered application whether its secret will epxire soon is added. |
| 140 |
|
| 141 |
if (class_exists('\Wpo\Services\Password_Credentials_Service')) { |
| 142 |
\Wpo\Services\Password_Credentials_Service::ensure_check_password_credentials_expiration(); |
| 143 |
} |
| 144 |
} // End of admin stuff |
| 145 |
|
| 146 |
// WP Cron job triggered action to check for each registered application whether its secret will epxire soon. |
| 147 |
add_action('wpo_check_password_credentials_expiration', '\Wpo\Services\Password_Credentials_Service::check_password_credentials_expiration'); |
| 148 |
|
| 149 |
// Add custom cron schedule for user sync |
| 150 |
add_filter('cron_schedules', '\Wpo\Core\Cron_Helpers::add_cron_schedules', 10, 1); |
| 151 |
|
| 152 |
// Clean up on shutdown |
| 153 |
add_action('shutdown', '\Wpo\Services\Request_Service::shutdown'); |
| 154 |
|
| 155 |
add_action('admin_enqueue_scripts', '\Wpo\Core\Script_Helpers::enqueue_wizard', 10, 0); |
| 156 |
|
| 157 |
// Replace phpmailer with Graph Mailer (but only if configured) |
| 158 |
// According to https://developer.wordpress.org/reference/functions/wp_mail/ wp_mail is available after plugins_loaded |
| 159 |
add_action('phpmailer_init', '\Wpo\Mail\Mailer::init', PHP_INT_MAX); |
| 160 |
add_filter('wp_mail_from', '\Wpo\Mail\Mailer::mail_from', 10, 1); |
| 161 |
|
| 162 |
if (Options_Service::get_global_boolean_var('mail_log', false) && method_exists('\Wpo\Mail\Mail_Db', 'add_mail_log')) { |
| 163 |
// Log each wp_mail in the wpo365_table |
| 164 |
add_filter('wp_mail', '\Wpo\Mail\Mail_Db::add_mail_log', 10, 1); |
| 165 |
} |
| 166 |
|
| 167 |
if (Options_Service::get_global_boolean_var('mail_throttling_enabled') && method_exists('\Wpo\Mail\Mail_Db', 'check_message_rate_limit')) { |
| 168 |
add_filter('wpo365/mail/before', '\Wpo\Mail\Mail_Db::check_message_rate_limit'); |
| 169 |
} |
| 170 |
|
| 171 |
if (Options_Service::get_global_boolean_var('mail_auto_retry') && method_exists('\Wpo\Mail\Mail_Db', 'process_unsent_messages')) { |
| 172 |
add_action('wpo_process_unsent_messages', '\Wpo\Mail\Mail_Db::process_unsent_messages'); |
| 173 |
} |
| 174 |
|
| 175 |
// Add safe style css |
| 176 |
add_filter('safe_style_css', '\Wpo\Core\WordPress_Helpers::safe_css', 10, 1); |
| 177 |
|
| 178 |
// Admin menu bar notifications |
| 179 |
if (Options_Service::get_global_boolean_var('mail_staging_mode', false) && class_exists('\Wpo\Mail\Mail_Notifications')) { |
| 180 |
add_action('admin_bar_menu', '\Wpo\Mail\Mail_Notifications::staging_mode_active', 100); |
| 181 |
add_action('wp_enqueue_scripts', '\Wpo\Core\Script_Helpers::add_admin_bar_styles'); |
| 182 |
add_action('admin_enqueue_scripts', '\Wpo\Core\Script_Helpers::add_admin_bar_styles'); |
| 183 |
} |
| 184 |
|
| 185 |
// Update WPO365 extensions cache whenever a plugin is added or deleted |
| 186 |
add_action('activated_plugin', '\Wpo\Core\Extensions_Helpers::plugin_activated', 10, 2); |
| 187 |
add_action('deactivated_plugin', '\Wpo\Core\Extensions_Helpers::plugin_deactivated', 10, 2); |
| 188 |
|
| 189 |
// Check again for updates after upgrader process completes to fix "Update available notice" |
| 190 |
add_action('upgrader_process_complete', '\Wpo\Core\Extensions_Helpers::plugin_updated', 10, 2); |
| 191 |
|
| 192 |
// To collect Insights |
| 193 |
if (Options_Service::get_global_boolean_var('insights_enabled', false)) { |
| 194 |
add_action('wpo365/mail/sent', '\Wpo\Services\Event_Service::mail_sent__handler', 10, 1); |
| 195 |
add_action('wpo365/mail/sent/fail', '\Wpo\Services\Event_Service::mail_sent_fail__handler', 10, 1); |
| 196 |
} |
| 197 |
|
| 198 |
// To collect cURL logging |
| 199 |
if (Options_Service::get_global_boolean_var('curl_logging_enabled')) { |
| 200 |
add_action('http_api_curl', '\Wpo\Services\Log_Service::enable_curl_logging', 10, 3); |
| 201 |
} |
| 202 |
} |
| 203 |
|
| 204 |
private function update_request_log() |
| 205 |
{ |
| 206 |
$request_service = Request_Service::get_instance(); |
| 207 |
$request = $request_service->get_request($GLOBALS['WPO_CONFIG']['request_id']); |
| 208 |
$request_log = $request->get_item('request_log'); |
| 209 |
$request_log['debug_log'] = Options_Service::get_global_boolean_var('debug_log', false); |
| 210 |
$request->set_item('request_log', $request_log); |
| 211 |
} |
| 212 |
|
| 213 |
private function deactivation_hooks() |
| 214 |
{ |
| 215 |
if (\class_exists('\Wpo\Mail\Mail_Db')) { |
| 216 |
// Delete possible cron jobs |
| 217 |
register_deactivation_hook(__FILE__, function () { |
| 218 |
wp_clear_scheduled_hook('wpo_process_unsent_messages'); |
| 219 |
Options_Service::add_update_option('mail_auto_retry', false); |
| 220 |
}); |
| 221 |
} |
| 222 |
|
| 223 |
register_deactivation_hook(__FILE__, function () { |
| 224 |
global $wpdb; |
| 225 |
|
| 226 |
$wpdb->query( |
| 227 |
$wpdb->prepare( |
| 228 |
"DELETE FROM $wpdb->options |
| 229 |
WHERE `option_name` LIKE '%s' |
| 230 |
AND `option_name` != '%s' |
| 231 |
AND `option_name` != '%s'", |
| 232 |
'%wpo365%', |
| 233 |
'wpo365_options', |
| 234 |
'wpo365_mail_authorization' |
| 235 |
) |
| 236 |
); |
| 237 |
|
| 238 |
$wpdb->query( |
| 239 |
$wpdb->prepare( |
| 240 |
"DELETE FROM $wpdb->options WHERE `option_name` LIKE '%s'", |
| 241 |
'wpo_app_only_access_tokens' |
| 242 |
) |
| 243 |
); |
| 244 |
}); |
| 245 |
} |
| 246 |
} |
| 247 |
} |
| 248 |
|
| 249 |
$wpo365_msgraphmailer = new MsGraphMailer(); |
| 250 |
|