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