summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryehudah <yehudah@b8457f37-d9ea-0310-8a92-e5e31aec5664>2019-11-25 09:25:43 +0000
committeryehudah <yehudah@b8457f37-d9ea-0310-8a92-e5e31aec5664>2019-11-25 09:25:43 +0000
commitb5fd728e37aa2a9c7a5f37e8dead0a95117d541b (patch)
treea7158edc5e4e576e0377f078dabc87c699315c62
parentc61784411988d36d9bbd93cd3a97e773990af342 (diff)
downloadPost-SMTP-b5fd728e37aa2a9c7a5f37e8dead0a95117d541b.zip
phpmailer delivery improvments
bug fixes add option to disable notifications fix Invalid “Reply-To” e-mail address
-rw-r--r--Postman/Extensions/Admin/PostmanAdmin.php31
-rw-r--r--Postman/Extensions/Admin/PostmanAdminView.php86
-rw-r--r--Postman/Extensions/Core/Notifications/INotify.php (renamed from Postman/notifications/INotify.php)0
-rw-r--r--Postman/Extensions/Core/Notifications/PostmanMailNotify.php (renamed from Postman/notifications/PostmanMailNotify.php)0
-rw-r--r--Postman/Extensions/Core/Notifications/PostmanNotify.php241
-rw-r--r--Postman/Extensions/Core/Notifications/PostmanNotifyOptions.php57
-rw-r--r--Postman/Extensions/Core/Notifications/PostmanPushoverNotify.php (renamed from Postman/notifications/PostmanPushoverNotify.php)0
-rw-r--r--Postman/Extensions/Core/Notifications/PostmanSlackNotify.php (renamed from Postman/notifications/PostmanSlackNotify.php)0
-rw-r--r--Postman/Extensions/License/EDD_SL_Plugin_Updater.php585
-rw-r--r--Postman/Extensions/License/PostmanLicenseHandler.php422
-rw-r--r--Postman/Extensions/License/PostmanLicenseManager.php102
-rw-r--r--Postman/Phpmailer/PostsmtpMailer.php147
-rw-r--r--Postman/Postman-Configuration/PostmanConfigurationController.php69
-rw-r--r--Postman/Postman-Configuration/PostmanRegisterConfigurationSettings.php92
-rw-r--r--Postman/Postman-Email-Log/PostmanEmailLogService.php65
-rw-r--r--Postman/Postman-Mail/PostmanMessage.php8
-rw-r--r--Postman/Postman.php6
-rw-r--r--Postman/PostmanAdminController.php4
-rw-r--r--Postman/PostmanInputSanitizer.php10
-rw-r--r--Postman/PostmanOptions.php44
-rw-r--r--Postman/PostmanWpMail.php29
-rw-r--r--Postman/notifications/PostmanNotify.php42
22 files changed, 1689 insertions, 351 deletions
diff --git a/Postman/Extensions/Admin/PostmanAdmin.php b/Postman/Extensions/Admin/PostmanAdmin.php
new file mode 100644
index 0000000..3b61a0a
--- /dev/null
+++ b/Postman/Extensions/Admin/PostmanAdmin.php
@@ -0,0 +1,31 @@
+<?php
+if ( ! defined( 'ABSPATH' ) ) exit;
+
+class PostmanAdmin {
+
+ public function __construct()
+ {
+ $PostmanLicenseManager = PostmanLicenseManager::get_instance();
+ $extensions = $PostmanLicenseManager->get_extensions();
+
+ if ( count( $extensions ) > 0 ) {
+ add_action('admin_menu', [ $this, 'add_menu' ], 20 );
+ }
+
+ }
+
+ public function add_menu() {
+ add_submenu_page(
+ PostmanViewController::POSTMAN_MENU_SLUG,
+ __('Extensions', 'post-smtp'),
+ __('Extensions', 'post-smtp'),
+ 'manage_options',
+ 'post-smtp-extensions',
+ [ $this, 'render_menu' ]
+ );
+ }
+
+ public function render_menu() {
+ include_once 'PostmanAdminView.php';
+ }
+}
diff --git a/Postman/Extensions/Admin/PostmanAdminView.php b/Postman/Extensions/Admin/PostmanAdminView.php
new file mode 100644
index 0000000..c9f0509
--- /dev/null
+++ b/Postman/Extensions/Admin/PostmanAdminView.php
@@ -0,0 +1,86 @@
+<?php if ( ! defined( 'ABSPATH' ) ) exit; ?>
+
+<style>
+ .form-table .row {
+ display: flex;
+ }
+
+ .form-table .row .flex > *:not(:last-child) {
+ margin-right: 5px;
+ }
+
+ .form-table .label {
+ align-self: center;
+ font-weight: bold;
+ }
+
+ .form-table .flex {
+ display: flex;
+ }
+
+ .form-table .flex input {
+ border-radius: 3px;
+ height: 30px;
+ margin: 0;
+ margin-left: 5px;
+ }
+
+ .form-table .flex button {
+ box-shadow: none;
+ height: 100%;
+ }
+</style>
+
+<div class="wrap">
+ <h1>Post SMTP Installed Extensions</h1>
+ <form action="" method="post">
+ <div class="form-table">
+ <?php
+ $PostmanLicenseManager = PostmanLicenseManager::get_instance();
+ $extensions = $PostmanLicenseManager->get_extensions();
+
+ foreach ( $extensions as $slug => $extension) :
+ $short_name = $extension['license_manager']->get_slug( $extension['plugin_data']['Name'] );
+ $nonce = $short_name . '_license_key-nonce';
+
+ $license_data = get_option( $short_name . '_license_active' );
+ $license_key = get_option( $short_name . '_license_key' );
+
+ $license_valid = is_object( $license_data ) && $license_data->license === 'valid';
+ $license_field_class = $license_valid ? 'readonly' : '';
+ $license_field_value = $license_valid ? base64_encode($license_key) : '';
+
+ wp_nonce_field( $nonce, $nonce );
+ ?>
+
+ <div class="row">
+ <div class="label">
+ <?php echo esc_html( $extension['plugin_data']['Name'] ); ?>
+ </div>
+
+ <div class="flex">
+ <div class="input">
+ <input <?php echo $license_field_class; ?>
+ type="password"
+ name="post_smtp_extension[<?php echo $short_name . '_license_key'; ?>]"
+ class="regular-text"
+ value="<?php echo $license_field_value; ?>"
+ placeholder="Serial Key">
+ </div>
+
+ <div class="buttons">
+ <?php if ( ! $license_valid ) :?>
+ <button type="submit" name="post_smtp_extension[<?php echo $short_name; ?>_activate]" class="button button-primary">Activate</button>
+ <?php endif; ?>
+
+ <button type="submit" name="post_smtp_extension[<?php echo $short_name; ?>_deactivate]" class="button button-secondary">Deactivate</button>
+ </div>
+ </div>
+
+ </div>
+
+ <?php endforeach; ?>
+
+ </div>
+ </form>
+</div>
diff --git a/Postman/notifications/INotify.php b/Postman/Extensions/Core/Notifications/INotify.php
index f40548d..f40548d 100644
--- a/Postman/notifications/INotify.php
+++ b/Postman/Extensions/Core/Notifications/INotify.php
diff --git a/Postman/notifications/PostmanMailNotify.php b/Postman/Extensions/Core/Notifications/PostmanMailNotify.php
index 922c304..922c304 100644
--- a/Postman/notifications/PostmanMailNotify.php
+++ b/Postman/Extensions/Core/Notifications/PostmanMailNotify.php
diff --git a/Postman/Extensions/Core/Notifications/PostmanNotify.php b/Postman/Extensions/Core/Notifications/PostmanNotify.php
new file mode 100644
index 0000000..d9f6a58
--- /dev/null
+++ b/Postman/Extensions/Core/Notifications/PostmanNotify.php
@@ -0,0 +1,241 @@
+<?php
+if ( ! defined( 'ABSPATH' ) ) {
+ exit; // Exit if accessed directly
+}
+require_once 'INotify.php';
+require_once 'PostmanMailNotify.php';
+require_once 'PostmanPushoverNotify.php';
+require_once 'PostmanSlackNotify.php';
+require_once 'PostmanNotifyOptions.php';
+
+class PostmanNotify {
+
+ const NOTIFICATIONS_OPTIONS = 'postman_notifications_options';
+ const NOTIFICATIONS_SECTION = 'postman_notifications_section';
+ const NOTIFICATIONS_PUSHOVER_CRED = 'postman_pushover_cred';
+ const NOTIFICATIONS_SLACK_CRED = 'postman_slack_cred';
+
+ public function __construct() {
+
+ $this->options = new PostmanNotifyOptions();
+
+ add_filter( 'post_smtp_admin_tabs', array( $this, 'tabs' ) );
+ add_action( 'post_smtp_settings_menu', array( $this, 'menu' ) );
+ add_action( 'post_smtp_settings_fields', array( $this, 'settings' ) );
+ add_action( 'post_smtp_on_failed', array( $this, 'notify' ), 10, 5 );
+ add_filter( 'post_smtp_sanitize', array( $this, 'sanitize' ), 10, 3 );
+ }
+
+ public function menu() {
+ print '<section id="notifications">';
+ do_settings_sections( self::NOTIFICATIONS_OPTIONS );
+
+ $currentKey = $this->options->getNotificationService();
+ $pushover = $currentKey == 'pushover' ? 'block' : 'none';
+ $slack = $currentKey == 'slack' ? 'block' : 'none';
+
+ echo '<div id="pushover_cred" style="display: ' . $pushover . ';">';
+ do_settings_sections( self::NOTIFICATIONS_PUSHOVER_CRED );
+ echo '</div>';
+
+ echo '<div id="slack_cred" style="display: ' . $slack . ';">';
+ do_settings_sections( self::NOTIFICATIONS_SLACK_CRED );
+ echo '</div>';
+
+ do_action( 'post_smtp_notification_settings' );
+
+ print '</section>';
+ }
+
+ public function sanitize($new_input, $input, $sanitizer) {
+ // Notifications
+ $sanitizer->sanitizeString( 'Pushover Service', PostmanNotifyOptions::NOTIFICATION_SERVICE, $input, $new_input, $this->options->getNotificationService() );
+ $sanitizer->sanitizePassword( 'Pushover Username', PostmanNotifyOptions::PUSHOVER_USER, $input, $new_input, $this->options->getPushoverUser() );
+ $sanitizer->sanitizePassword( 'Pushover Token', PostmanNotifyOptions::PUSHOVER_TOKEN, $input, $new_input, $this->options->getPushoverToken() );
+ $sanitizer->sanitizePassword( 'Slack Token', PostmanNotifyOptions::SLACK_TOKEN, $input, $new_input, $this->options->getSlackToken() );
+
+ // Chrome extension
+ $sanitizer->sanitizeString( 'Push Chrome Extension', PostmanNotifyOptions::NOTIFICATION_USE_CHROME, $input, $new_input );
+ $sanitizer->sanitizePassword( 'Push Chrome Extension UID', PostmanNotifyOptions::NOTIFICATION_CHROME_UID, $input, $new_input, $this->options->getNotificationChromeUid() );
+
+ return $new_input;
+ }
+
+ public function tabs($tabs) {
+ $tabs['notifications'] = __( 'Notifications', 'post-smtp' );
+
+ return $tabs;
+ }
+
+ public function settings() {
+ // Notifications
+ add_settings_section( self::NOTIFICATIONS_SECTION, _x( 'Notifications Settings', 'Configuration Section Title', 'post-smtp' ), array(
+ $this,
+ 'printNotificationsSectionInfo',
+ ), self::NOTIFICATIONS_OPTIONS );
+
+ add_settings_field( PostmanNotifyOptions::NOTIFICATION_SERVICE, _x( 'Notification Service', 'Configuration Input Field', 'post-smtp' ), array(
+ $this,
+ 'notification_service_callback',
+ ), self::NOTIFICATIONS_OPTIONS, self::NOTIFICATIONS_SECTION );
+
+ // Pushover
+ add_settings_section( 'pushover_credentials', _x( 'Pushover Credentials', 'Configuration Section Title', 'post-smtp' ), array(
+ $this,
+ 'printNotificationsSectionInfo',
+ ), self::NOTIFICATIONS_PUSHOVER_CRED );
+
+ add_settings_field( PostmanNotifyOptions::PUSHOVER_USER, _x( 'Pushover User Key', 'Configuration Input Field', 'post-smtp' ), array(
+ $this,
+ 'pushover_user_callback',
+ ), self::NOTIFICATIONS_PUSHOVER_CRED, 'pushover_credentials' );
+
+ add_settings_field( PostmanNotifyOptions::PUSHOVER_TOKEN, _x( 'Pushover App Token', 'Configuration Input Field', 'post-smtp' ), array(
+ $this,
+ 'pushover_token_callback',
+ ), self::NOTIFICATIONS_PUSHOVER_CRED, 'pushover_credentials' );
+
+ // Slack
+ add_settings_section( 'slack_credentials', _x( 'Slack Credentials', 'Configuration Section Title', 'post-smtp' ), array(
+ $this,
+ 'printNotificationsSectionInfo',
+ ), self::NOTIFICATIONS_SLACK_CRED );
+
+ add_settings_field( PostmanNotifyOptions::SLACK_TOKEN, _x( 'Slack Webhook', 'Configuration Input Field', 'post-smtp' ), array(
+ $this,
+ 'slack_token_callback',
+ ), self::NOTIFICATIONS_SLACK_CRED, 'slack_credentials' );
+
+ add_settings_field( PostmanNotifyOptions::NOTIFICATION_USE_CHROME, _x( 'Push to chrome extension', 'Configuration Input Field', 'post-smtp' ), array(
+ $this,
+ 'notification_use_chrome_callback',
+ ), self::NOTIFICATIONS_OPTIONS, self::NOTIFICATIONS_SECTION );
+
+ add_settings_field( 'notification_chrome_uid', _x( 'Chrome Extension UID', 'Configuration Input Field', 'post-smtp' ), array(
+ $this,
+ 'notification_chrome_uid_callback',
+ ), self::NOTIFICATIONS_OPTIONS, self::NOTIFICATIONS_SECTION );
+ }
+
+ /**
+ * Print the Section text
+ */
+ public function printNotificationsSectionInfo() {
+ }
+
+ public function notification_service_callback() {
+ $inputDescription = __( 'Select the notification service you want to recieve alerts about failed emails.' );
+
+ $options = apply_filters('post_smtp_notification_service', array(
+ 'none' => __( 'None', 'post-smtp' ),
+ 'default' => __( 'WP Admin Email', 'post-smtp' ),
+ 'pushover' => __( 'Pushover', 'post-smtp' ),
+ 'slack' => __( 'Slack', 'post-smtp' ),
+ ));
+
+ printf( '<select id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]">', 'postman_options', PostmanNotifyOptions::NOTIFICATION_SERVICE );
+ $currentKey = $this->options->getNotificationService();
+
+ foreach ( $options as $key => $label ) {
+ $this->printSelectOption( $label, $key, $currentKey );
+ }
+
+ printf( '</select><br/><span class="postman_input_description">%s</span>', $inputDescription );
+ }
+
+ public function notification_use_chrome_callback() {
+ $value = $this->options->useChromeExtension();
+ printf( '<input type="checkbox" id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]" %3$s />', 'postman_options', PostmanNotifyOptions::NOTIFICATION_USE_CHROME, $value ? 'checked="checked"' : '' );
+ }
+
+ public function notification_chrome_uid_callback() {
+ printf( '<input type="password" id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', 'postman_options', 'notification_chrome_uid', PostmanUtils::obfuscatePassword( $this->options->getNotificationChromeUid() ) );
+ }
+
+ public function pushover_user_callback() {
+ printf( '<input type="password" id="pushover_user" name="%s[%s]" value="%s" />', 'postman_options', PostmanNotifyOptions::PUSHOVER_USER, $this->options->getPushoverUser() );
+ }
+
+ public function pushover_token_callback() {
+ printf( '<input type="password" id="pushover_token" name="%s[%s]" value="%s" />', 'postman_options', PostmanNotifyOptions::PUSHOVER_TOKEN, $this->options->getPushoverToken() );
+ }
+
+ public function slack_token_callback() {
+ printf( '<input type="password" id="slack_token" name="%s[%s]" value="%s" />', 'postman_options', PostmanNotifyOptions::SLACK_TOKEN, $this->options->getSlackToken() );
+ echo '<a target="_blank" href="https://slack.postmansmtp.com/">' . __( 'Get your webhook URL here', 'post-smtp' ) . '</a>';
+
+ }
+
+ /**
+ * @param PostmanEmailLog $log
+ * @param PostmanMessage $message
+ * @param string $transcript
+ * @param PostmanTransport $transport
+ * @param string $errorMessage
+ */
+ public function notify ($log, $postmanMessage, $transcript, $transport, $errorMessage ) {
+ $message = __( 'You getting this message because an error detected while delivered your email.', 'post-smtp' );
+ $message .= "\r\n" . sprintf( __( 'For the domain: %1$s','post-smtp' ), get_bloginfo('url') );
+ $message .= "\r\n" . __( 'The log to paste when you open a support issue:', 'post-smtp' ) . "\r\n";
+
+ if ( $errorMessage && ! empty( $errorMessage ) ) {
+
+ $message = $message . $errorMessage;
+
+ $notification_service = PostmanNotifyOptions::getInstance()->getNotificationService();
+ switch ($notification_service) {
+ case 'none':
+ $notifyer = false;
+ break;
+ case 'default':
+ $notifyer = new PostmanMailNotify;
+ break;
+ case 'pushover':
+ $notifyer = new PostmanPushoverNotify;
+ break;
+ case 'slack':
+ $notifyer = new PostmanSlackNotify;
+ break;
+ default:
+ $notifyer = new PostmanMailNotify;
+ }
+
+ $notifyer = apply_filters('post_smtp_notifier', $notifyer, $notification_service);
+
+ // Notifications
+ if ( $notifyer ) {
+ $notifyer->send_message($message, $log);
+ }
+
+ $this->push_to_chrome($errorMessage);
+ }
+ }
+
+ public function push_to_chrome($message) {
+ $push_chrome = PostmanNotifyOptions::getInstance()->useChromeExtension();
+
+ if ( $push_chrome ) {
+ $uid = PostmanNotifyOptions::getInstance()->getNotificationChromeUid();
+
+ if ( empty( $uid ) ) {
+ return;
+ }
+
+ $url = 'https://postmansmtp.com/chrome/' . $uid;
+
+ $args = array(
+ 'body' => array(
+ 'message' => $message
+ )
+ );
+
+ $response = wp_remote_post( $url , $args );
+ }
+ }
+
+ private function printSelectOption( $label, $optionKey, $currentKey ) {
+ $optionPattern = '<option value="%1$s" %2$s>%3$s</option>';
+ printf( $optionPattern, $optionKey, $optionKey == $currentKey ? 'selected="selected"' : '', $label );
+ }
+}
+new PostmanNotify(); \ No newline at end of file
diff --git a/Postman/Extensions/Core/Notifications/PostmanNotifyOptions.php b/Postman/Extensions/Core/Notifications/PostmanNotifyOptions.php
new file mode 100644
index 0000000..08c27db
--- /dev/null
+++ b/Postman/Extensions/Core/Notifications/PostmanNotifyOptions.php
@@ -0,0 +1,57 @@
+<?php
+
+class PostmanNotifyOptions {
+
+ const DEFAULT_NOTIFICATION_SERVICE = 'default';
+ const NOTIFICATION_SERVICE = 'notification_service';
+ const NOTIFICATION_USE_CHROME = 'notification_use_chrome';
+ const NOTIFICATION_CHROME_UID = 'notification_chrome_uid';
+ const PUSHOVER_USER = 'pushover_user';
+ const PUSHOVER_TOKEN = 'pushover_token';
+ const SLACK_TOKEN = 'slack_token';
+
+ private $options;
+
+ public function __construct()
+ {
+ $this->options = get_option( 'postman_options' );
+ }
+
+ public function getNotificationService() {
+ if ( isset( $this->options [ self::NOTIFICATION_SERVICE ] ) ) {
+ return $this->options [ self::NOTIFICATION_SERVICE ];
+ } else {
+ return self::DEFAULT_NOTIFICATION_SERVICE;
+ }
+ }
+
+ public function getPushoverUser() {
+ if ( isset( $this->options [ self::PUSHOVER_USER ] ) ) {
+ return base64_decode( $this->options [ self::PUSHOVER_USER ] );
+ }
+ }
+
+ public function getPushoverToken() {
+ if ( isset( $this->options [ self::PUSHOVER_TOKEN ] ) ) {
+ return base64_decode( $this->options [ self::PUSHOVER_TOKEN ] );
+ }
+ }
+
+ public function getSlackToken() {
+ if ( isset( $this->options [ self::SLACK_TOKEN ] ) ) {
+ return base64_decode( $this->options [ self::SLACK_TOKEN ] );
+ }
+ }
+
+ public function useChromeExtension() {
+ if ( isset( $this->options [ self::NOTIFICATION_USE_CHROME ] ) ) {
+ return $this->options [ self::NOTIFICATION_USE_CHROME ];
+ }
+ }
+
+ public function getNotificationChromeUid() {
+ if ( isset( $this->options [ self::NOTIFICATION_CHROME_UID ] ) ) {
+ return base64_decode( $this->options [ self::NOTIFICATION_CHROME_UID ] );
+ }
+ }
+} \ No newline at end of file
diff --git a/Postman/notifications/PostmanPushoverNotify.php b/Postman/Extensions/Core/Notifications/PostmanPushoverNotify.php
index 14ef7d2..14ef7d2 100644
--- a/Postman/notifications/PostmanPushoverNotify.php
+++ b/Postman/Extensions/Core/Notifications/PostmanPushoverNotify.php
diff --git a/Postman/notifications/PostmanSlackNotify.php b/Postman/Extensions/Core/Notifications/PostmanSlackNotify.php
index 5b6fae3..5b6fae3 100644
--- a/Postman/notifications/PostmanSlackNotify.php
+++ b/Postman/Extensions/Core/Notifications/PostmanSlackNotify.php
diff --git a/Postman/Extensions/License/EDD_SL_Plugin_Updater.php b/Postman/Extensions/License/EDD_SL_Plugin_Updater.php
new file mode 100644
index 0000000..0673834
--- /dev/null
+++ b/Postman/Extensions/License/EDD_SL_Plugin_Updater.php
@@ -0,0 +1,585 @@
+<?php
+
+// Exit if accessed directly
+if ( ! defined( 'ABSPATH' ) ) exit;
+
+/**
+ * Allows plugins to use their own update API.
+ *
+ * @author Easy Digital Downloads
+ * @version 1.6.19
+ */
+class EDD_SL_Plugin_Updater {
+
+ private $api_url = '';
+ private $api_data = array();
+ private $name = '';
+ private $slug = '';
+ private $version = '';
+ private $wp_override = false;
+ private $cache_key = '';
+
+ private $health_check_timeout = 5;
+
+ /**
+ * Class constructor.
+ *
+ * @uses plugin_basename()
+ * @uses hook()
+ *
+ * @param string $_api_url The URL pointing to the custom API endpoint.
+ * @param string $_plugin_file Path to the plugin file.
+ * @param array $_api_data Optional data to send with API calls.
+ */
+ public function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
+
+ global $edd_plugin_data;
+
+ $this->api_url = trailingslashit( $_api_url );
+ $this->api_data = $_api_data;
+ $this->name = plugin_basename( $_plugin_file );
+ $this->slug = basename( $_plugin_file, '.php' );
+ $this->version = $_api_data['version'];
+ $this->wp_override = isset( $_api_data['wp_override'] ) ? (bool) $_api_data['wp_override'] : false;
+ $this->beta = ! empty( $this->api_data['beta'] ) ? true : false;
+ $this->cache_key = 'edd_sl_' . md5( serialize( $this->slug . $this->api_data['license'] . $this->beta ) );
+
+ $edd_plugin_data[ $this->slug ] = $this->api_data;
+
+ /**
+ * Fires after the $edd_plugin_data is setup.
+ *
+ * @since x.x.x
+ *
+ * @param array $edd_plugin_data Array of EDD SL plugin data.
+ */
+ do_action( 'post_edd_sl_plugin_updater_setup', $edd_plugin_data );
+
+ // Set up hooks.
+ $this->init();
+
+ }
+
+ /**
+ * Set up WordPress filters to hook into WP's update process.
+ *
+ * @uses add_filter()
+ *
+ * @return void
+ */
+ public function init() {
+
+ add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
+ add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
+ remove_action( 'after_plugin_row_' . $this->name, 'wp_plugin_update_row', 10 );
+ add_action( 'after_plugin_row_' . $this->name, array( $this, 'show_update_notification' ), 10, 2 );
+ add_action( 'admin_init', array( $this, 'show_changelog' ) );
+
+ }
+
+ /**
+ * Check for Updates at the defined API endpoint and modify the update array.
+ *
+ * This function dives into the update API just when WordPress creates its update array,
+ * then adds a custom API call and injects the custom plugin data retrieved from the API.
+ * It is reassembled from parts of the native WordPress plugin update code.
+ * See wp-includes/update.php line 121 for the original wp_update_plugins() function.
+ *
+ * @uses api_request()
+ *
+ * @param array $_transient_data Update array build by WordPress.
+ * @return array Modified update array with custom plugin data.
+ */
+ public function check_update( $_transient_data ) {
+
+ global $pagenow;
+
+ if ( ! is_object( $_transient_data ) ) {
+ $_transient_data = new stdClass;
+ }
+
+ if ( 'plugins.php' == $pagenow && is_multisite() ) {
+ return $_transient_data;
+ }
+
+ if ( ! empty( $_transient_data->response ) && ! empty( $_transient_data->response[ $this->name ] ) && false === $this->wp_override ) {
+ return $_transient_data;
+ }
+
+ $version_info = $this->get_cached_version_info();
+
+ if ( false === $version_info ) {
+ $version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug, 'beta' => $this->beta ) );
+
+ $this->set_version_info_cache( $version_info );
+
+ }
+
+ if ( false !== $version_info && is_object( $version_info ) && isset( $version_info->new_version ) ) {
+
+ if ( version_compare( $this->version, $version_info->new_version, '<' ) ) {
+
+ $_transient_data->response[ $this->name ] = $version_info;
+
+ // Make sure the plugin property is set to the plugin's name/location. See issue 1463 on Software Licensing's GitHub repo.
+ $_transient_data->response[ $this->name ]->plugin = $this->name;
+
+ }
+
+ $_transient_data->last_checked = time();
+ $_transient_data->checked[ $this->name ] = $this->version;
+
+ }
+
+ return $_transient_data;
+ }
+
+ /**
+ * show update nofication row -- needed for multisite subsites, because WP won't tell you otherwise!
+ *
+ * @param string $file
+ * @param array $plugin
+ */
+ public function show_update_notification( $file, $plugin ) {
+
+ if ( is_network_admin() ) {
+ return;
+ }
+
+ if( ! current_user_can( 'update_plugins' ) ) {
+ return;
+ }
+
+ if( ! is_multisite() ) {
+ return;
+ }
+
+ if ( $this->name != $file ) {
+ return;
+ }
+
+ // Remove our filter on the site transient
+ remove_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ), 10 );
+
+ $update_cache = get_site_transient( 'update_plugins' );
+
+ $update_cache = is_object( $update_cache ) ? $update_cache : new stdClass();
+
+ if ( empty( $update_cache->response ) || empty( $update_cache->response[ $this->name ] ) ) {
+
+ $version_info = $this->get_cached_version_info();
+
+ if ( false === $version_info ) {
+ $version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug, 'beta' => $this->beta ) );
+
+ // Since we disabled our filter for the transient, we aren't running our object conversion on banners, sections, or icons. Do this now:
+ if ( isset( $version_info->banners ) && ! is_array( $version_info->banners ) ) {
+ $version_info->banners = $this->convert_object_to_array( $version_info->banners );
+ }
+
+ if ( isset( $version_info->sections ) && ! is_array( $version_info->sections ) ) {
+ $version_info->sections = $this->convert_object_to_array( $version_info->sections );
+ }
+
+ if ( isset( $version_info->icons ) && ! is_array( $version_info->icons ) ) {
+ $version_info->icons = $this->convert_object_to_array( $version_info->icons );
+ }
+
+ if ( isset( $version_info->icons ) && ! is_array( $version_info->icons ) ) {
+ $version_info->icons = $this->convert_object_to_array( $version_info->icons );
+ }
+
+ if ( isset( $version_info->contributors ) && ! is_array( $version_info->contributors ) ) {
+ $version_info->contributors = $this->convert_object_to_array( $version_info->contributors );
+ }
+
+ $this->set_version_info_cache( $version_info );
+ }
+
+ if ( ! is_object( $version_info ) ) {
+ return;
+ }
+
+ if ( version_compare( $this->version, $version_info->new_version, '<' ) ) {
+
+ $update_cache->response[ $this->name ] = $version_info;
+
+ }
+
+ $update_cache->last_checked = time();
+ $update_cache->checked[ $this->name ] = $this->version;
+
+ set_site_transient( 'update_plugins', $update_cache );
+
+ } else {
+
+ $version_info = $update_cache->response[ $this->name ];
+
+ }
+
+ // Restore our filter
+ add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
+
+ if ( ! empty( $update_cache->response[ $this->name ] ) && version_compare( $this->version, $version_info->new_version, '<' ) ) {
+
+ // build a plugin list row, with update notification
+ $wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
+ # <tr class="plugin-update-tr"><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange">
+ echo '<tr class="plugin-update-tr" id="' . $this->slug . '-update" data-slug="' . $this->slug . '" data-plugin="' . $this->slug . '/' . $file . '">';
+ echo '<td colspan="3" class="plugin-update colspanchange">';
+ echo '<div class="update-message notice inline notice-warning notice-alt">';
+
+ $changelog_link = self_admin_url( 'index.php?edd_sl_action=view_plugin_changelog&plugin=' . $this->name . '&slug=' . $this->slug . '&TB_iframe=true&width=772&height=911' );
+
+ if ( empty( $version_info->download_link ) ) {
+ printf(
+ __( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s.', 'easy-digital-downloads' ),
+ esc_html( $version_info->name ),
+ '<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
+ esc_html( $version_info->new_version ),
+ '</a>'
+ );
+ } else {
+ printf(
+ __( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s or %5$supdate now%6$s.', 'easy-digital-downloads' ),
+ esc_html( $version_info->name ),
+ '<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
+ esc_html( $version_info->new_version ),
+ '</a>',
+ '<a href="' . esc_url( wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $this->name, 'upgrade-plugin_' . $this->name ) ) .'">',
+ '</a>'
+ );
+ }
+
+ do_action( "in_plugin_update_message-{$file}", $plugin, $version_info );
+
+ echo '</div></td></tr>';
+ }
+ }
+
+ /**
+ * Updates information on the "View version x.x details" page with custom data.
+ *
+ * @uses api_request()
+ *
+ * @param mixed $_data
+ * @param string $_action
+ * @param object $_args
+ * @return object $_data
+ */
+ public function plugins_api_filter( $_data, $_action = '', $_args = null ) {
+
+ if ( $_action != 'plugin_information' ) {
+
+ return $_data;
+
+ }
+
+ if ( ! isset( $_args->slug ) || ( $_args->slug != $this->slug ) ) {
+
+ return $_data;
+
+ }
+
+ $to_send = array(
+ 'slug' => $this->slug,
+ 'is_ssl' => is_ssl(),
+ 'fields' => array(
+ 'banners' => array(),
+ 'reviews' => false,
+ 'icons' => array(),
+ )
+ );
+
+ $cache_key = 'edd_api_request_' . md5( serialize( $this->slug . $this->api_data['license'] . $this->beta ) );
+
+ // Get the transient where we store the api request for this plugin for 24 hours
+ $edd_api_request_transient = $this->get_cached_version_info( $cache_key );
+
+ //If we have no transient-saved value, run the API, set a fresh transient with the API value, and return that value too right now.
+ if ( empty( $edd_api_request_transient ) ) {
+
+ $api_response = $this->api_request( 'plugin_information', $to_send );
+
+ // Expires in 3 hours
+ $this->set_version_info_cache( $api_response, $cache_key );
+
+ if ( false !== $api_response ) {
+ $_data = $api_response;
+ }
+
+ } else {
+ $_data = $edd_api_request_transient;
+ }
+
+ // Convert sections into an associative array, since we're getting an object, but Core expects an array.
+ if ( isset( $_data->sections ) && ! is_array( $_data->sections ) ) {
+ $_data->sections = $this->convert_object_to_array( $_data->sections );
+ }
+
+ // Convert banners into an associative array, since we're getting an object, but Core expects an array.
+ if ( isset( $_data->banners ) && ! is_array( $_data->banners ) ) {
+ $_data->banners = $this->convert_object_to_array( $_data->banners );
+ }
+
+ // Convert icons into an associative array, since we're getting an object, but Core expects an array.
+ if ( isset( $_data->icons ) && ! is_array( $_data->icons ) ) {
+ $_data->icons = $this->convert_object_to_array( $_data->icons );
+ }
+
+ // Convert contributors into an associative array, since we're getting an object, but Core expects an array.
+ if ( isset( $_data->contributors ) && ! is_array( $_data->contributors ) ) {
+ $_data->contributors = $this->convert_object_to_array( $_data->contributors );
+ }
+
+ if( ! isset( $_data->plugin ) ) {
+ $_data->plugin = $this->name;
+ }
+
+ return $_data;
+ }
+
+ /**
+ * Convert some objects to arrays when injecting data into the update API
+ *
+ * Some data like sections, banners, and icons are expected to be an associative array, however due to the JSON
+ * decoding, they are objects. This method allows us to pass in the object and return an associative array.
+ *
+ * @since 3.6.5
+ *
+ * @param stdClass $data
+ *
+ * @return array
+ */
+ private function convert_object_to_array( $data ) {
+ $new_data = array();
+ foreach ( $data as $key => $value ) {
+ $new_data[ $key ] = is_object( $value ) ? $this->convert_object_to_array( $value ) : $value;
+ }
+
+ return $new_data;
+ }
+
+ /**
+ * Disable SSL verification in order to prevent download update failures
+ *
+ * @param array $args
+ * @param string $url
+ * @return object $array
+ */
+ public function http_request_args( $args, $url ) {
+
+ $verify_ssl = $this->verify_ssl();
+ if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
+ $args['sslverify'] = $verify_ssl;
+ }
+ return $args;
+
+ }
+
+ /**
+ * Calls the API and, if successfull, returns the object delivered by the API.
+ *
+ * @uses get_bloginfo()
+ * @uses wp_remote_post()
+ * @uses is_wp_error()
+ *
+ * @param string $_action The requested action.
+ * @param array $_data Parameters for the API action.
+ * @return false|object
+ */
+ private function api_request( $_action, $_data ) {
+
+ global $wp_version, $edd_plugin_url_available;
+
+ $verify_ssl = $this->verify_ssl();
+
+ // Do a quick status check on this domain if we haven't already checked it.
+ $store_hash = md5( $this->api_url );
+ if ( ! is_array( $edd_plugin_url_available ) || ! isset( $edd_plugin_url_available[ $store_hash ] ) ) {
+ $test_url_parts = parse_url( $this->api_url );
+
+ $scheme = ! empty( $test_url_parts['scheme'] ) ? $test_url_parts['scheme'] : 'http';
+ $host = ! empty( $test_url_parts['host'] ) ? $test_url_parts['host'] : '';
+ $port = ! empty( $test_url_parts['port'] ) ? ':' . $test_url_parts['port'] : '';
+
+ if ( empty( $host ) ) {
+ $edd_plugin_url_available[ $store_hash ] = false;
+ } else {
+ $test_url = $scheme . '://' . $host . $port;
+ $response = wp_remote_get( $test_url, array( 'timeout' => $this->health_check_timeout, 'sslverify' => $verify_ssl ) );
+ $edd_plugin_url_available[ $store_hash ] = is_wp_error( $response ) ? false : true;
+ }
+ }
+
+ if ( false === $edd_plugin_url_available[ $store_hash ] ) {
+ return;
+ }
+
+ $data = array_merge( $this->api_data, $_data );
+
+ if ( $data['slug'] != $this->slug ) {
+ return;
+ }
+
+ if( $this->api_url == trailingslashit ( home_url() ) ) {
+ return false; // Don't allow a plugin to ping itself
+ }
+
+ $api_params = array(
+ 'edd_action' => 'get_version',
+ 'license' => ! empty( $data['license'] ) ? $data['license'] : '',
+ 'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,
+ 'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,
+ 'version' => isset( $data['version'] ) ? $data['version'] : false,
+ 'slug' => $data['slug'],
+ 'author' => $data['author'],
+ 'url' => home_url(),
+ 'beta' => ! empty( $data['beta'] ),
+ );
+
+ $request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => $verify_ssl, 'body' => $api_params ) );
+
+ if ( ! is_wp_error( $request ) ) {
+ $request = json_decode( wp_remote_retrieve_body( $request ) );
+ }
+
+ if ( $request && isset( $request->sections ) ) {
+ $request->sections = maybe_unserialize( $request->sections );
+ } else {
+ $request = false;
+ }
+
+ if ( $request && isset( $request->banners ) ) {
+ $request->banners = maybe_unserialize( $request->banners );
+ }
+
+ if ( $request && isset( $request->icons ) ) {
+ $request->icons = maybe_unserialize( $request->icons );
+ }
+
+ if( ! empty( $request->sections ) ) {
+ foreach( $request->sections as $key => $section ) {
+ $request->$key = (array) $section;
+ }
+ }
+
+ return $request;
+ }
+
+ public function show_changelog() {
+
+ global $edd_plugin_data;
+
+ if( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' != $_REQUEST['edd_sl_action'] ) {
+ return;
+ }
+
+ if( empty( $_REQUEST['plugin'] ) ) {
+ return;
+ }
+
+ if( empty( $_REQUEST['slug'] ) ) {
+ return;
+ }
+
+ if( ! current_user_can( 'update_plugins' ) ) {
+ wp_die( __( 'You do not have permission to install plugin updates', 'easy-digital-downloads' ), __( 'Error', 'easy-digital-downloads' ), array( 'response' => 403 ) );
+ }
+
+ $data = $edd_plugin_data[ $_REQUEST['slug'] ];
+ $beta = ! empty( $data['beta'] ) ? true : false;
+ $cache_key = md5( 'edd_plugin_' . sanitize_key( $_REQUEST['plugin'] ) . '_' . $beta . '_version_info' );
+ $version_info = $this->get_cached_version_info( $cache_key );
+
+ if( false === $version_info ) {
+
+ $api_params = array(
+ 'edd_action' => 'get_version',
+ 'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,
+ 'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,
+ 'slug' => $_REQUEST['slug'],
+ 'author' => $data['author'],
+ 'url' => home_url(),
+ 'beta' => ! empty( $data['beta'] )
+ );
+
+ $verify_ssl = $this->verify_ssl();
+ $request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => $verify_ssl, 'body' => $api_params ) );
+
+ if ( ! is_wp_error( $request ) ) {
+ $version_info = json_decode( wp_remote_retrieve_body( $request ) );
+ }
+
+
+ if ( ! empty( $version_info ) && isset( $version_info->sections ) ) {
+ $version_info->sections = maybe_unserialize( $version_info->sections );
+ } else {
+ $version_info = false;
+ }
+
+ if( ! empty( $version_info ) ) {
+ foreach( $version_info->sections as $key => $section ) {
+ $version_info->$key = (array) $section;
+ }
+ }
+
+ $this->set_version_info_cache( $version_info, $cache_key );
+
+ }
+
+ if( ! empty( $version_info ) && isset( $version_info->sections['changelog'] ) ) {
+ echo '<div style="background:#fff;padding:10px;">' . $version_info->sections['changelog'] . '</div>';
+ }
+
+ exit;
+ }
+
+ public function get_cached_version_info( $cache_key = '' ) {
+
+ if( empty( $cache_key ) ) {
+ $cache_key = $this->cache_key;
+ }
+
+ $cache = get_option( $cache_key );
+
+ if( empty( $cache['timeout'] ) || time() > $cache['timeout'] ) {
+ return false; // Cache is expired
+ }
+
+ // We need to turn the icons into an array, thanks to WP Core forcing these into an object at some point.
+ $cache['value'] = json_decode( $cache['value'] );
+ if ( ! empty( $cache['value']->icons ) ) {
+ $cache['value']->icons = (array) $cache['value']->icons;
+ }
+
+ return $cache['value'];
+
+ }
+
+ public function set_version_info_cache( $value = '', $cache_key = '' ) {
+
+ if( empty( $cache_key ) ) {
+ $cache_key = $this->cache_key;
+ }
+
+ $data = array(
+ 'timeout' => strtotime( '+3 hours', time() ),
+ 'value' => json_encode( $value )
+ );
+
+ update_option( $cache_key, $data, 'no' );
+
+ }
+
+ /**
+ * Returns if the SSL of the store should be verified.
+ *
+ * @since 1.6.13
+ * @return bool
+ */
+ private function verify_ssl() {
+ return (bool) apply_filters( 'edd_sl_api_request_verify_ssl', true, $this );
+ }
+
+}
diff --git a/Postman/Extensions/License/PostmanLicenseHandler.php b/Postman/Extensions/License/PostmanLicenseHandler.php
new file mode 100644
index 0000000..b24aa14
--- /dev/null
+++ b/Postman/Extensions/License/PostmanLicenseHandler.php
@@ -0,0 +1,422 @@
+<?php
+
+// Exit if accessed directly
+if ( ! defined( 'ABSPATH' ) ) exit;
+
+if ( ! class_exists( 'PostmanLicenseHandler' ) ) :
+
+
+class PostmanLicenseHandler {
+ private $file;
+ private $license;
+ private $license_data;
+ private $item_name;
+ private $item_id;
+ private $item_shortname;
+ private $version;
+ private $author;
+ private $api_url = 'http://localhost/psp/';
+
+
+ function __construct( $_file, $_item_name, $_version, $_author, $_optname = null, $_api_url = null, $_item_id = null ) {
+ $this->file = $_file;
+ $this->item_name = $_item_name;
+
+ if ( is_numeric( $_item_id ) ) {
+ $this->item_id = absint( $_item_id );
+ }
+
+ $this->item_shortname = $this->get_slug();
+ $this->version = $_version;
+ $this->license = trim( get_option( $this->item_shortname . '_license_key', '' ) );
+ $this->license_data = get_option( $this->item_shortname . '_license_active', '' );
+ $this->author = $_author;
+ $this->api_url = is_null( $_api_url ) ? $this->api_url : $_api_url;
+
+ /**
+ * Allows for backwards compatibility with old license options,
+ * i.e. if the plugins had license key fields previously, the license
+ * handler will automatically pick these up and use those in lieu of the
+ * user having to reactive their license.
+ */
+ if ( ! empty( $_optname ) ) {
+ $opt = get_option( $_optname, false );
+
+ if( isset( $opt ) && empty( $this->license ) ) {
+ $this->license = trim( $opt );
+ }
+ }
+
+ // Setup hooks
+ $this->includes();
+ $this->hooks();
+
+ }
+
+ /**
+ * Include the updater class
+ *
+ * @access private
+ * @return void
+ */
+ private function includes() {
+ if ( ! class_exists( 'EDD_SL_Plugin_Updater' ) ) {
+ require_once 'EDD_SL_Plugin_Updater.php';
+ }
+ }
+
+ /**
+ * Setup hooks
+ *
+ * @access private
+ * @return void
+ */
+ public function hooks() {
+
+ // Activate license key on settings save
+ add_action( 'admin_init', array( $this, 'activate_license' ) );
+
+ // Deactivate license key
+ add_action( 'admin_init', array( $this, 'deactivate_license' ) );
+
+ add_action( 'init', array( $this, 'cron' ), 20 );
+
+ // Check that license is valid once per week
+ add_action( 'admin_init', array( $this, 'validate_license' ) );
+
+ // Updater
+ add_action( 'admin_init', array( $this, 'auto_updater' ), 0 );
+
+ // Display notices to admins
+ add_action( 'admin_notices', array( $this, 'notices' ) );
+
+ add_action( 'in_plugin_update_message-' . plugin_basename( $this->file ), array( $this, 'plugin_row_license_missing' ), 10, 2 );
+ }
+
+ /**
+ * Auto updater
+ *
+ * @access private
+ * @return void
+ */
+ public function auto_updater() {
+
+ $args = array(
+ 'version' => $this->version,
+ 'license' => $this->license,
+ 'author' => $this->author,
+ 'beta' => function_exists( 'edd_extension_has_beta_support' ) && edd_extension_has_beta_support( $this->item_shortname ),
+ );
+
+ if( ! empty( $this->item_id ) ) {
+ $args['item_id'] = $this->item_id;
+ } else {
+ $args['item_name'] = $this->item_name;
+ }
+
+ // Setup the updater
+ $edd_updater = new EDD_SL_Plugin_Updater(
+ $this->api_url,
+ $this->file,
+ $args
+ );
+ }
+
+ public function cron() {
+ if ( ! wp_next_scheduled( $this->item_shortname . '_scheduled_events' ) ) {
+ wp_schedule_event( current_time( 'timestamp', true ), 'daily', $this->item_shortname . '_scheduled_events' );
+ }
+ }
+
+ public function get_slug() {
+ return preg_replace( '/[^a-zA-Z0-9_\s]/', '', str_replace( ' ', '_', strtolower( $this->item_name ) ) );
+ }
+
+ /**
+ * Display help text at the top of the Licenses tag
+ *
+ * @since 2.5
+ * @param string $active_tab
+ * @return void
+ */
+ public function license_help_text( $active_tab = '' ) {
+
+ static $has_ran;
+
+ if( 'licenses' !== $active_tab ) {
+ return;
+ }
+
+ if( ! empty( $has_ran ) ) {
+ return;
+ }
+
+ echo '<p>' . sprintf(
+ __( 'Enter your extension license keys here to receive updates for purchased extensions. If your license key has expired, please <a href="%s" target="_blank">renew your license</a>.', 'easy-digital-downloads' ),
+ 'http://docs.easydigitaldownloads.com/article/1000-license-renewal'
+ ) . '</p>';
+
+ $has_ran = true;
+
+ }
+
+
+ /**
+ * Activate the license key
+ *
+ * @return void
+ */
+ public function activate_license() {
+
+ if ( ! isset( $_POST['post_smtp_extension'][ $this->item_shortname . '_activate'] ) ) {
+ return;
+ }
+
+ if ( ! isset( $_REQUEST[ $this->item_shortname . '_license_key-nonce'] ) || ! wp_verify_nonce( $_REQUEST[ $this->item_shortname . '_license_key-nonce'], $this->item_shortname . '_license_key-nonce' ) ) {
+
+ return;
+
+ }
+
+ if ( ! current_user_can( 'manage_options' ) ) {
+ return;
+ }
+
+ if ( empty( $_POST['post_smtp_extension'][ $this->item_shortname . '_license_key'] ) ) {
+
+ delete_option( $this->item_shortname . '_license_active' );
+ delete_option( $this->item_shortname . '_license_key' );
+
+ return;
+
+ }
+
+ foreach ( $_POST as $key => $value ) {
+ if( false !== strpos( $key, 'license_key_deactivate' ) ) {
+ // Don't activate a key when deactivating a different key
+ return;
+ }
+ }
+
+ $details = get_option( $this->item_shortname . '_license_active' );
+
+ if ( is_object( $details ) && 'valid' === $details->license ) {
+ return;
+ }
+
+ $license = sanitize_text_field( $_POST['post_smtp_extension'][ $this->item_shortname . '_license_key'] );
+
+ if( empty( $license ) ) {
+ return;
+ }
+
+ // Data to send to the API
+ $api_params = array(
+ 'edd_action' => 'activate_license',
+ 'license' => $license,
+ 'item_name' => urlencode( $this->item_name ),
+ 'url' => home_url()
+ );
+
+ if ( ! empty( $this->item_id ) ) {
+ $api_params['item_id'] = $this->item_id;
+ }
+
+ // Call the API
+ $response = wp_remote_post(
+ $this->api_url,
+ array(
+ 'timeout' => 15,
+ 'sslverify' => false,
+ 'body' => $api_params
+ )
+ );
+
+ // Make sure there are no errors
+ if ( is_wp_error( $response ) ) {
+ return;
+ }
+
+ // Tell WordPress to look for updates
+ set_site_transient( 'update_plugins', null );
+
+ // Decode license data
+ $license_data = json_decode( wp_remote_retrieve_body( $response ) );
+
+ update_option( $this->item_shortname . '_license_active', $license_data );
+ update_option( $this->item_shortname . '_license_key', $license );
+
+ $slug = plugin_basename($this->file);
+ PostmanLicenseManager::get_instance()->add_extension($slug);
+
+ }
+
+
+ /**
+ * Deactivate the license key
+ *
+ * @return void
+ */
+ public function deactivate_license() {
+
+ if ( ! isset( $_POST['post_smtp_extension'][ $this->item_shortname . '_deactivate'] ) ) {
+ return;
+ }
+
+ if ( ! isset( $_POST['post_smtp_extension'][ $this->item_shortname . '_license_key'] ) )
+ return;
+
+ if( ! wp_verify_nonce( $_REQUEST[ $this->item_shortname . '_license_key-nonce'], $this->item_shortname . '_license_key-nonce' ) ) {
+
+ wp_die( __( 'Nonce verification failed', 'easy-digital-downloads' ), __( 'Error', 'easy-digital-downloads' ), array( 'response' => 403 ) );
+
+ }
+
+ if( ! current_user_can( 'manage_options' ) ) {
+ return;
+ }
+
+ $license_key = sanitize_text_field( base64_decode( $_POST['post_smtp_extension'][ $this->item_shortname . '_license_key'] ) );
+
+ // Run on deactivate button press
+ // Data to send to the API
+ $api_params = array(
+ 'edd_action' => 'deactivate_license',
+ 'license' => $license_key,
+ 'item_name' => urlencode( $this->item_name ),
+ 'url' => home_url()
+ );
+
+ if ( ! empty( $this->item_id ) ) {
+ $api_params['item_id'] = $this->item_id;
+ }
+
+ // Call the API
+ $response = wp_remote_post(
+ $this->api_url,
+ array(
+ 'timeout' => 15,
+ 'sslverify' => false,
+ 'body' => $api_params
+ )
+ );
+
+ // Make sure there are no errors
+ if ( is_wp_error( $response ) ) {
+ return;
+ }
+
+ // Decode the license data
+ $license_data = json_decode( wp_remote_retrieve_body( $response ) );
+
+ delete_option( $this->item_shortname . '_license_active' );
+ delete_option( $this->item_shortname . '_license_key' );
+
+ $slug = plugin_basename($this->file);
+ PostmanLicenseManager::get_instance()->remove_extension($slug);
+
+ }
+
+ public function validate_license() {
+ if ( false === ( $cron_data = get_transient( $this->item_shortname . '_cron' ) ) ) {
+ $this->license_check();
+
+ set_transient( $this->item_shortname . '_cron', true, rand( 12, 48 ) * HOUR_IN_SECONDS );
+ }
+ }
+
+
+ /**
+ * Check if license key is valid once per week
+ *
+ * @since 2.5
+ * @return void
+ */
+ public function license_check() {
+
+ // data to send in our API request
+ $api_params = array(
+ 'edd_action'=> 'check_license',
+ 'license' => $this->license,
+ 'item_name' => urlencode( $this->item_name ),
+ 'url' => home_url()
+ );
+
+ // Call the API
+ $response = wp_remote_post(
+ $this->api_url,
+ array(
+ 'timeout' => 15,
+ 'sslverify' => false,
+ 'body' => $api_params
+ )
+ );
+
+ // make sure the response came back okay
+ if ( is_wp_error( $response ) ) {
+ return false;
+ }
+
+ $license_data = json_decode( wp_remote_retrieve_body( $response ) );
+
+ update_option( $this->item_shortname . '_license_active', $license_data );
+
+ }
+
+
+ /**
+ * Admin notices for errors
+ *
+ * @return void
+ */
+ public function notices() {
+
+ $showed_invalid_message = null;
+
+ if( empty( $this->license ) ) {
+ return;
+ }
+
+ if( ! current_user_can( 'manage_options' ) ) {
+ return;
+ }
+
+ $messages = array();
+
+ $license = get_option( $this->item_shortname . '_license_active' );
+
+ if( is_object( $license ) && 'valid' !== $license->license && empty( $showed_invalid_message ) ) {
+
+ if( isset( $_GET['page'] ) && 'post-smtp-extensions' === $_GET['page'] ) {
+
+ $messages[] = sprintf(
+ __( '%s has invalid or expired license key for Post SMTP.'),
+ '<strong>' . $this->item_name . '</strong>'
+ );
+
+ $showed_invalid_message = true;
+
+ }
+
+ }
+
+ if( ! empty( $messages ) ) {
+
+ foreach( $messages as $message ) {
+
+ echo '<div class="error">';
+ echo '<p>' . $message . '</p>';
+ echo '</div>';
+
+ }
+
+ }
+
+ }
+
+ public function is_licensed() {
+ return is_object($this->license_data) && 'valid' === $this->license_data->license;
+ }
+}
+
+endif; // end class_exists check
diff --git a/Postman/Extensions/License/PostmanLicenseManager.php b/Postman/Extensions/License/PostmanLicenseManager.php
new file mode 100644
index 0000000..280b564
--- /dev/null
+++ b/Postman/Extensions/License/PostmanLicenseManager.php
@@ -0,0 +1,102 @@
+<?php
+if ( ! defined( 'ABSPATH' ) ) exit;
+
+class PostmanLicenseManager {
+
+ const ENDPOINT = 'https://postmansmtp.com';
+
+ const CORE_EXTENSIONS = [ 'gmail_api', 'sendgrid_api', 'mandrill_api', 'mailgun_api' ];
+
+ private $extensions;
+
+ private $rand_cache_interval = 12;
+
+ private static $instance;
+
+ public static function get_instance() {
+ if ( ! self::$instance ) {
+ self::$instance = new static();
+ }
+
+ return self::$instance;
+ }
+
+ /**
+ * PostmanLicenseManager constructor.
+ */
+ private function __construct()
+ {
+ $this->includes();
+ $this->rand_cache_interval = rand( 1, 24 );
+
+ add_filter( 'extra_plugin_headers', [ $this, 'add_extension_headers' ] );
+ }
+
+ public function includes() {
+ include_once 'PostmanLicenseHandler.php';
+
+ include_once ABSPATH . '/wp-admin/includes/plugin.php';
+
+ }
+
+
+ function add_extension_headers($headers) {
+ $headers[] = 'Class';
+ $headers[] = 'Slug';
+
+ return $headers;
+ }
+
+ /**
+ * Init
+ */
+ public function init() {
+
+ $plugins = get_plugins();
+ foreach ( $plugins as $plugin_dir_and_filename => $plugin_data ) {
+
+ if ( ! is_plugin_active( $plugin_dir_and_filename ) ) {
+ continue;
+ }
+
+ if ( false !== strpos( $plugin_dir_and_filename, 'post-smtp-extension' ) ) {
+ $slug = $plugin_dir_and_filename;
+ $class = $plugin_data['Class'];
+ $plugin_path = WP_CONTENT_DIR . '/plugins/' . $plugin_dir_and_filename;
+
+ $this->extensions[$slug]['plugin_data'] = $plugin_data;
+ $this->extensions[$slug]['plugin_dir_and_filename'] = $plugin_dir_and_filename;
+ $this->extensions[$slug]['license_manager'] = new PostmanLicenseHandler(
+ $plugin_path, $plugin_data['Name'],
+ $plugin_data['Version'], $plugin_data['Author']
+ );
+ if ( $this->extensions[$slug]['license_manager']->is_licensed() ) {
+ include_once $plugin_path;
+
+ $this->extensions[$slug]['instance'] = new $class;
+ }
+ }
+ }
+
+ if ( ! empty( $this->extensions ) ) {
+ new PostmanAdmin();
+ }
+ }
+
+ public function add_extension($slug) {
+ $plugin_path = WP_CONTENT_DIR . '/plugins/' . $this->extensions[$slug]['plugin_dir_and_filename'];
+ $class = $this->extensions[$slug]['plugin_data']['Class'];
+
+ include_once $plugin_path;
+ $this->extensions[$slug]['instance'] = new $class;
+ }
+
+ public function remove_extension($slug) {
+ $this->extensions[$slug]['instance'] = null;
+ unset($this->extensions[$slug]['instance']);
+ }
+
+ public function get_extensions() {
+ return $this->extensions;
+ }
+} \ No newline at end of file
diff --git a/Postman/Phpmailer/PostsmtpMailer.php b/Postman/Phpmailer/PostsmtpMailer.php
index b3a421b..e52091d 100644
--- a/Postman/Phpmailer/PostsmtpMailer.php
+++ b/Postman/Phpmailer/PostsmtpMailer.php
@@ -2,8 +2,10 @@
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
-require_once ABSPATH . WPINC . '/class-phpmailer.php';
-require_once ABSPATH . WPINC . '/class-smtp.php';
+
+if ( ! class_exists( 'PHPMailer', false ) ) {
+ require_once ABSPATH . WPINC . '/class-phpmailer.php';
+}
add_action('plugins_loaded', function() {
global $phpmailer;
@@ -17,12 +19,53 @@ class PostsmtpMailer extends PHPMailer {
private $error;
+ private $transcript = '';
+
public function __construct($exceptions = null)
{
parent::__construct($exceptions);
+ $this->set_vars();
+ $this->hooks();
+
+ }
+
+ public function set_vars() {
$this->options = PostmanOptions::getInstance();
- add_filter( 'postman_wp_mail_result', [ $this, 'postman_wp_mail_result' ] );
+ $this->Debugoutput = function($str, $level) {
+ $this->transcript .= $str;
+ };
+ }
+
+ public function hooks() {
+ if ( $this->options->getTransportType() == 'smtp' ) {
+ add_action( 'phpmailer_init', array( $this, 'phpmailer_smtp_init' ) );
+ }
+ }
+
+ /**
+ * @param PHPMailer $mail
+ */
+ public function phpmailer_smtp_init($mail) {
+ $mail->SMTPDebug = 3;
+ $mail->isSMTP();
+ $mail->Host = $this->options->getHostname();
+
+ if ( $this->options->getAuthenticationType() !== 'none' ) {
+ $mail->SMTPAuth = true;
+ $mail->Username = $this->options->getUsername();
+ $mail->Password = $this->options->getPassword();
+ }
+
+ if ( $this->options->getEncryptionType() !== 'none' ) {
+ $mail->SMTPSecure = $this->options->getEncryptionType();
+ }
+
+ $mail->Port = $this->options->getPort();
+
+ if ( $this->options->isPluginSenderEmailEnforced() ) {
+ $mail->setFrom( $this->options->getMessageSenderEmail() , $this->options->getMessageSenderName () );
+ }
}
public function send()
@@ -33,40 +76,46 @@ class PostsmtpMailer extends PHPMailer {
$postmanWpMail = new PostmanWpMail();
$postmanWpMail->init();
- $senderEmail = $this->options->getMessageSenderEmail();
- $senderName = $this->options->getMessageSenderName();
-
- // create a PostmanMessage instance
- $message = $postmanWpMail->createNewMessage();
-
- $message->setFrom( $senderEmail, $senderName );
- $message->addHeaders( $this->getHeaders() );
- $message->setBodyTextPart( $this->AltBody );
- $message->setBodyHtmlPart( $this->Body );
- $message->setBody( $this->Body );
- $message->setSubject( $this->Subject );
- $message->addTo( $this->flatArray($this->getToAddresses() ) );
- $message->setReplyTo( $this->flatArray( $this->getReplyToAddresses() ) );
- $message->addCc( $this->flatArray($this->getCcAddresses() ) );
- $message->addBCc( $this->flatArray( $this->getBccAddresses() ) );
- $message->setReplyTo( $this->flatArray( $this->getReplyToAddresses() ) );
- $message->setAttachments( $this->getAttachments() );
-
- // create a PostmanEmailLog instance
+ $backtrace = debug_backtrace();
+
+ list($to, $subject, $body, $headers, $attachments) = array_pad( $backtrace[1]['args'], 5, null );
+
+ // build the message
+ $postmanMessage = $postmanWpMail->processWpMailCall( $to, $subject, $body, $headers, $attachments );
+
+ // build the email log entry
$log = new PostmanEmailLog();
+ $log->originalTo = $to;
+ $log->originalSubject = $subject;
+ $log->originalMessage = $body;
+ $log->originalHeaders = $headers;
- $log->originalTo = $this->flatArray($this->getToAddresses() );
- $log->originalSubject = $this->Subject;
- $log->originalMessage = $this->Body;
- $log->originalHeaders = $this->getCustomHeaders();
+ // get the transport and create the transportConfig and engine
+ $transport = PostmanTransportRegistry::getInstance()->getActiveTransport();
+
+ add_filter( 'postman_wp_mail_result', [ $this, 'postman_wp_mail_result' ] );
try {
- return $postmanWpMail->sendMessage( $message, $log );
+
+ if ( $send_email = apply_filters( 'post_smtp_do_send_email', true ) ) {
+ $result = $this->options->getTransportType() !== 'smtp' ?
+ $postmanWpMail->send( $to, $subject, $body, $headers, $attachments ) :
+ $this->sendSmtp();
+ }
+
+
+ do_action( 'post_smtp_on_success', $log, $postmanMessage, $this->transcript, $transport );
+
+ return $result;
+
} catch (phpmailerException $exc) {
$this->error = $exc;
$this->mailHeader = '';
+
+ do_action( 'post_smtp_on_failed', $log, $postmanMessage, $this->transcript, $transport, $exc->getMessage() );
+
$this->setError($exc->getMessage());
if ($this->exceptions) {
throw $exc;
@@ -76,50 +125,20 @@ class PostsmtpMailer extends PHPMailer {
}
- public function getAttachments() {
- $attachments = parent::getAttachments();
-
- $data = array();
- foreach ( $attachments as $attachment ) {
- $data[] = $attachment[0];
+ public function sendSmtp() {
+ if (!$this->preSend()) {
+ return false;
}
-
- return $data;
+ return $this->postSend();
}
- private function getHeaders() {
- $headers = array();
- foreach ( $this->getCustomHeaders() as $header ) {
- $headers[] = "{$header[0]}: {$header[1]}";
- }
- return $headers;
- }
-
- public function postman_wp_mail_result() {
+ public function postman_wp_mail_result() {
$result = [
'time' => '',
'exception' => $this->error,
- 'transcript' => '',
+ 'transcript' => $this->transcript,
];
return $result;
}
-
- private function flatArray($arr) {
- $result = [];
- foreach ( $arr as $key => $value ) {
- if ( is_array( $value ) ) {
- foreach ($value as $k => $v ) {
- if ( empty( $v ) ) {
- continue;
- }
- $value = $v;
- }
- }
-
- $result[] = $value;
- }
-
- return implode(',', $result );
- }
} \ No newline at end of file
diff --git a/Postman/Postman-Configuration/PostmanConfigurationController.php b/Postman/Postman-Configuration/PostmanConfigurationController.php
index 59fbdb8..c63d6a9 100644
--- a/Postman/Postman-Configuration/PostmanConfigurationController.php
+++ b/Postman/Postman-Configuration/PostmanConfigurationController.php
@@ -201,13 +201,21 @@ class PostmanConfigurationController {
print '<div class="wrap">';
PostmanViewController::outputChildPageHeader( __( 'Settings', 'post-smtp' ), 'advanced_config' );
+
+ $config_tabs = apply_filters( 'post_smtp_admin_tabs', array(
+ 'account_config' => __( 'Account', 'post-smtp' ),
+ 'fallback' => __( 'Fallback', 'post-smtp' ),
+ 'message_config' => __( 'Message', 'post-smtp' ),
+ 'logging_config' => __( 'Logging', 'post-smtp' ),
+ 'advanced_options_config' => __( 'Advanced', 'post-smtp' ),
+ ) );
+
print '<div id="config_tabs"><ul>';
- print sprintf( '<li><a href="#account_config">%s</a></li>', __( 'Account', 'post-smtp' ) );
- print sprintf( '<li><a href="#fallback">%s</a></li>', __( 'Fallback', 'post-smtp' ) );
- print sprintf( '<li><a href="#message_config">%s</a></li>', __( 'Message', 'post-smtp' ) );
- print sprintf( '<li><a href="#logging_config">%s</a></li>', __( 'Logging', 'post-smtp' ) );
- print sprintf( '<li><a href="#advanced_options_config">%s</a></li>', __( 'Advanced', 'post-smtp' ) );
- print sprintf( '<li><a href="#notifications">%s</a></li>', __( 'Notifications', 'post-smtp' ) );
+
+ foreach ( $config_tabs as $slug => $tab ) :
+ printf( '<li><a href="#%s">%s</a></li>', $slug, $tab );
+ endforeach;
+
print '</ul>';
print '<form method="post" action="options.php">';
@@ -294,9 +302,9 @@ class PostmanConfigurationController {
<th scope="row"><?php _e('Security', 'post-smtp' ); ?></th>
<?php
$security_options = array(
- 'none' => __( 'None', 'post-smtp' ),
- 'ssl' => __( 'SSL', 'post-smtp' ),
- 'tls' => __( 'TLS', 'post-smtp' ),
+ 'none' => __( 'None', 'post-smtp' ),
+ 'ssl' => __( 'SSL', 'post-smtp' ),
+ 'tls' => __( 'TLS', 'post-smtp' ),
);
?>
<td>
@@ -313,17 +321,17 @@ class PostmanConfigurationController {
</td>
</tr>
- <tr>
- <th scope="row"><?php _e('From Email', 'post-smtp' ); ?></th>
- <td>
- <input type="email" id="fallback-smtp-from-email"
- value="<?php echo $this->options->getFallbackFromEmail(); ?>"
- name="postman_options[<?php echo PostmanOptions::FALLBACK_FROM_EMAIL; ?>]"
- >
- <br>
- <small><?php _e( "Use allowed email, for example: If you are using Gmail, type your Gmail adress.", 'post-smtp' ); ?></small>
- </td>
- </tr>
+ <tr>
+ <th scope="row"><?php _e('From Email', 'post-smtp' ); ?></th>
+ <td>
+ <input type="email" id="fallback-smtp-from-email"
+ value="<?php echo $this->options->getFallbackFromEmail(); ?>"
+ name="postman_options[<?php echo PostmanOptions::FALLBACK_FROM_EMAIL; ?>]"
+ >
+ <br>
+ <small><?php _e( "Use allowed email, for example: If you are using Gmail, type your Gmail adress.", 'post-smtp' ); ?></small>
+ </td>
+ </tr>
<tr valign="">
<th scope="row"><?php _e( 'Use SMTP Authentication?', 'post-smtp' ); ?></th>
@@ -387,24 +395,7 @@ class PostmanConfigurationController {
do_settings_sections( PostmanAdminController::ADVANCED_OPTIONS );
print '</section>';
- print '<section id="notifications">';
- do_settings_sections( PostmanAdminController::NOTIFICATIONS_OPTIONS );
-
- $currentKey = $this->options->getNotificationService();
- $pushover = $currentKey == 'pushover' ? 'block' : 'none';
- $slack = $currentKey == 'slack' ? 'block' : 'none';
-
- echo '<div id="pushover_cred" style="display: ' . $pushover . ';">';
- do_settings_sections( PostmanAdminController::NOTIFICATIONS_PUSHOVER_CRED );
- echo '</div>';
-
- echo '<div id="slack_cred" style="display: ' . $slack . ';">';
- do_settings_sections( PostmanAdminController::NOTIFICATIONS_SLACK_CRED );
- echo '</div>';
-
- do_action( 'post_smtp_notification_settings' );
-
- print '</section>';
+ do_action( 'post_smtp_settings_menu' );
submit_button();
print '</form>';
@@ -762,7 +753,7 @@ class PostmanManageConfigurationAjaxHandler extends PostmanAbstractAjaxHandler {
wp_send_json_success( $response );
} else {
/* translators: where %s is the URL to the Connectivity Test page */
- $configuration ['message'] = sprintf( __( 'Postman can\'t find any way to send mail on your system. Run a <a href="%s">connectivity test</a>.', 'post-smtp' ), PostmanViewController::getPageUrl( PostmanViewController::PORT_TEST_SLUG ) );
+ $configuration ['message'] = sprintf( __( 'Postman can\'t find any way to send mail on your system. Run a <a href="%s">connectivity test</a>.', 'post-smtp' ), PostmanViewController::getPageUrl( PostmanConnectivityTestController::PORT_TEST_SLUG ) );
$response ['configuration'] = $configuration;
if ( $this->logger->isTrace() ) {
$this->logger->trace( 'configuration:' );
diff --git a/Postman/Postman-Configuration/PostmanRegisterConfigurationSettings.php b/Postman/Postman-Configuration/PostmanRegisterConfigurationSettings.php
index 705ef23..9c0170b 100644
--- a/Postman/Postman-Configuration/PostmanRegisterConfigurationSettings.php
+++ b/Postman/Postman-Configuration/PostmanRegisterConfigurationSettings.php
@@ -186,55 +186,7 @@ class PostmanSettingsRegistry {
'temporaryDirectoryCallback',
), PostmanAdminController::ADVANCED_OPTIONS, PostmanAdminController::ADVANCED_SECTION );
- // Notifications
- add_settings_section( PostmanAdminController::NOTIFICATIONS_SECTION, _x( 'Notifications Settings', 'Configuration Section Title', 'post-smtp' ), array(
- $this,
- 'printNotificationsSectionInfo',
- ), PostmanAdminController::NOTIFICATIONS_OPTIONS );
-
- add_settings_field( PostmanOptions::NOTIFICATION_SERVICE, _x( 'Notification Service', 'Configuration Input Field', 'post-smtp' ), array(
- $this,
- 'notification_service_callback',
- ), PostmanAdminController::NOTIFICATIONS_OPTIONS, PostmanAdminController::NOTIFICATIONS_SECTION );
-
- // Pushover
- add_settings_section( 'pushover_credentials', _x( 'Pushover Credentials', 'Configuration Section Title', 'post-smtp' ), array(
- $this,
- 'printNotificationsSectionInfo',
- ), PostmanAdminController::NOTIFICATIONS_PUSHOVER_CRED );
-
- add_settings_field( PostmanOptions::PUSHOVER_USER, _x( 'Pushover User Key', 'Configuration Input Field', 'post-smtp' ), array(
- $this,
- 'pushover_user_callback',
- ), PostmanAdminController::NOTIFICATIONS_PUSHOVER_CRED, 'pushover_credentials' );
-
- add_settings_field( PostmanOptions::PUSHOVER_TOKEN, _x( 'Pushover App Token', 'Configuration Input Field', 'post-smtp' ), array(
- $this,
- 'pushover_token_callback',
- ), PostmanAdminController::NOTIFICATIONS_PUSHOVER_CRED, 'pushover_credentials' );
-
- // Slack
- add_settings_section( 'slack_credentials', _x( 'Slack Credentials', 'Configuration Section Title', 'post-smtp' ), array(
- $this,
- 'printNotificationsSectionInfo',
- ), PostmanAdminController::NOTIFICATIONS_SLACK_CRED );
-
- add_settings_field( PostmanOptions::SLACK_TOKEN, _x( 'Slack Webhook', 'Configuration Input Field', 'post-smtp' ), array(
- $this,
- 'slack_token_callback',
- ), PostmanAdminController::NOTIFICATIONS_SLACK_CRED, 'slack_credentials' );
-
- add_settings_field( PostmanOptions::NOTIFICATION_USE_CHROME, _x( 'Push to chrome extension', 'Configuration Input Field', 'post-smtp' ), array(
- $this,
- 'notification_use_chrome_callback',
- ), PostmanAdminController::NOTIFICATIONS_OPTIONS, PostmanAdminController::NOTIFICATIONS_SECTION );
-
- add_settings_field( PostmanOptions::NOTIFICATION_CHROME_UID, _x( 'Chrome Extension UID', 'Configuration Input Field', 'post-smtp' ), array(
- $this,
- 'notification_chrome_uid_callback',
- ), PostmanAdminController::NOTIFICATIONS_OPTIONS, PostmanAdminController::NOTIFICATIONS_SECTION );
-
- do_action( 'post_smtp_settings' );
+ do_action( 'post_smtp_settings_fields' );
}
}
@@ -442,48 +394,6 @@ class PostmanSettingsRegistry {
printf( '</select><br/><span class="postman_input_description">%s</span>', $inputDescription );
}
- public function notification_service_callback() {
- $inputDescription = __( 'Select the notification service you want to recieve alerts about failed emails.' );
-
- $options = apply_filters('post_smtp_notification_service', array(
- 'default' => __( 'WP Admin Email', 'post-smtp' ),
- 'pushover' => __( 'Pushover', 'post-smtp' ),
- 'slack' => __( 'Slack', 'post-smtp' ),
- ));
-
- printf( '<select id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]">', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::NOTIFICATION_SERVICE );
- $currentKey = $this->options->getNotificationService();
-
- foreach ( $options as $key => $label ) {
- $this->printSelectOption( $label, $key, $currentKey );
- }
-
- printf( '</select><br/><span class="postman_input_description">%s</span>', $inputDescription );
- }
-
- public function notification_use_chrome_callback() {
- $value = $this->options->useChromeExtension();
- printf( '<input type="checkbox" id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]" %3$s />', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::NOTIFICATION_USE_CHROME, $value ? 'checked="checked"' : '' );
- }
-
- public function notification_chrome_uid_callback() {
- printf( '<input type="password" id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::NOTIFICATION_CHROME_UID, PostmanUtils::obfuscatePassword( $this->options->getNotificationChromeUid() ) );
- }
-
- public function pushover_user_callback() {
- printf( '<input type="password" id="pushover_user" name="%s[%s]" value="%s" />', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::PUSHOVER_USER, $this->options->getPushoverUser() );
- }
-
- public function pushover_token_callback() {
- printf( '<input type="password" id="pushover_token" name="%s[%s]" value="%s" />', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::PUSHOVER_TOKEN, $this->options->getPushoverToken() );
- }
-
- public function slack_token_callback() {
- printf( '<input type="password" id="slack_token" name="%s[%s]" value="%s" />', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::SLACK_TOKEN, $this->options->getSlackToken() );
- echo '<a target="_blank" href="https://slack.postmansmtp.com/">' . __( 'Get your webhook URL here', 'post-smtp' ) . '</a>';
-
- }
-
private function printSelectOption( $label, $optionKey, $currentKey ) {
$optionPattern = '<option value="%1$s" %2$s>%3$s</option>';
printf( $optionPattern, $optionKey, $optionKey == $currentKey ? 'selected="selected"' : '', $label );
diff --git a/Postman/Postman-Email-Log/PostmanEmailLogService.php b/Postman/Postman-Email-Log/PostmanEmailLogService.php
index 2538700..624342d 100644
--- a/Postman/Postman-Email-Log/PostmanEmailLogService.php
+++ b/Postman/Postman-Email-Log/PostmanEmailLogService.php
@@ -4,6 +4,7 @@ if ( ! defined( 'ABSPATH' ) ) {
}
require_once dirname(__DIR__ ) . '/PostmanLogFields.php';
+require_once POST_SMTP_PATH . '/Postman/Extensions/Core/Notifications/PostmanNotify.php';
if ( ! class_exists( 'PostmanEmailLog' ) ) {
class PostmanEmailLog {
@@ -56,6 +57,9 @@ if ( ! class_exists( 'PostmanEmailLogService' ) ) {
*/
private function __construct() {
$this->logger = new PostmanLogger( get_class( $this ) );
+
+ add_action('post_smtp_on_success', array( $this, 'write_success_log' ), 10, 4 );
+ add_action('post_smtp_on_failed', array( $this, 'write_failed_log' ), 10, 5 );
}
/**
@@ -69,6 +73,20 @@ if ( ! class_exists( 'PostmanEmailLogService' ) ) {
return $inst;
}
+ public function write_success_log($log, $message, $transcript, $transport) {
+ $options = PostmanOptions::getInstance();
+ if ( $options->getRunMode() == PostmanOptions::RUN_MODE_PRODUCTION || $options->getRunMode() == PostmanOptions::RUN_MODE_LOG_ONLY ) {
+ $this->writeSuccessLog( $log, $message, $transcript, $transport );
+ }
+ }
+
+ public function write_failed_log($log, $message, $transcript, $transport, $statusMessage) {
+ $options = PostmanOptions::getInstance();
+ if ( $options->getRunMode() == PostmanOptions::RUN_MODE_PRODUCTION || $options->getRunMode() == PostmanOptions::RUN_MODE_LOG_ONLY ) {
+ $this->writeFailureLog( $log, $message, $transcript, $transport, $statusMessage );
+ }
+ }
+
/**
* Logs successful email attempts
*
@@ -118,7 +136,6 @@ if ( ! class_exists( 'PostmanEmailLogService' ) ) {
$options = PostmanOptions::getInstance();
- $this->checkForLogErrors( $log ,$message );
$new_status = $log->statusMessage;
if ( $options->is_fallback && empty( $log->statusMessage ) ) {
@@ -129,6 +146,8 @@ if ( ! class_exists( 'PostmanEmailLogService' ) ) {
$new_status = '( ** Fallback ** ) ' . $log->statusMessage;
}
+ $new_status = apply_filters( 'post_smtp_log_status', $new_status, $log, $message );
+
// nothing here is sanitized as WordPress should take care of
// making database writes safe
$my_post = array(
@@ -187,50 +206,6 @@ if ( ! class_exists( 'PostmanEmailLogService' ) ) {
$purger->truncateLogItems( PostmanOptions::getInstance()->getMailLoggingMaxEntries() );
}
- private function checkForLogErrors( PostmanEmailLog $log, $postMessage ) {
- $message = __( 'You getting this message because an error detected while delivered your email.', 'post-smtp' );
- $message .= "\r\n" . sprintf( __( 'For the domain: %1$s','post-smtp' ), get_bloginfo('url') );
- $message .= "\r\n" . __( 'The log to paste when you open a support issue:', 'post-smtp' ) . "\r\n";
-
- if ( $log->statusMessage && ! empty( $log->statusMessage ) ) {
- require_once POST_SMTP_PATH . '/Postman/notifications/PostmanNotify.php';
-
- $message = $message . $log->statusMessage;
-
- $notification_service = PostmanOptions::getInstance()->getNotificationService();
- switch ($notification_service) {
- case 'default':
- $notifyer = new PostmanMailNotify;
- break;
- case 'pushover':
- $notifyer = new PostmanPushoverNotify;
- break;
- case 'slack':
- $notifyer = new PostmanSlackNotify;
- break;
- default:
- $notifyer = new PostmanMailNotify;
- }
-
- $notifyer = apply_filters( 'post_smtp_notifier', $notifyer, $notification_service );
-
- // Notifications
- $notify = new PostmanNotify( $notifyer );
- $notify->send($message, $log);
- $notify->push_to_chrome($log->statusMessage);
- }
-
- /**
- * @todo
- * After commented by me, check if it was needed.
- */
- preg_match_all( '/(.*)From/s', $log->sessionTranscript, $matches );
-
- if ( isset( $matches[1][0] ) && ! empty( $matches[1][0] ) && strpos( strtolower( $matches[1][0] ), 'error' ) !== false ) {
- $message = $message . $log->sessionTranscript;
- }
- }
-
/**
* Creates a Log object for use by writeToEmailLog()
*
diff --git a/Postman/Postman-Mail/PostmanMessage.php b/Postman/Postman-Mail/PostmanMessage.php
index 12099ba..4099a02 100644
--- a/Postman/Postman-Mail/PostmanMessage.php
+++ b/Postman/Postman-Mail/PostmanMessage.php
@@ -450,7 +450,13 @@ if ( ! class_exists( 'PostmanMessage' ) ) {
break;
case 'reply-to' :
$this->logProcessHeader( 'Reply-To', $name, $content );
- $this->setReplyTo( $content );
+ $pattern = '/[a-z0-9_\-\+\.]+@[a-z0-9\-]+\.([a-z]{2,4})(?:\.[a-z]{2})?/i';
+ preg_match_all($pattern, $content, $matches);
+
+ if ( isset( $matches[0] ) && is_email( $matches[0] ) ) {
+ $this->setReplyTo( $content );
+ }
+
break;
case 'sender' :
$this->logProcessHeader( 'Sender', $name, $content );
diff --git a/Postman/Postman.php b/Postman/Postman.php
index 51b2ab1..9f4f7ce 100644
--- a/Postman/Postman.php
+++ b/Postman/Postman.php
@@ -70,6 +70,8 @@ class Postman {
require_once 'Postman-Mail/PostmanMyMailConnector.php';
require_once 'Postman-Mail/PostmanContactForm7.php';
require_once 'Phpmailer/PostsmtpMailer.php';
+ require_once 'Extensions/License/PostmanLicenseManager.php';
+ require_once 'Extensions/Admin/PostmanAdmin.php';
//require_once 'Postman-Mail/PostmanWooCommerce.php';
// get plugin metadata - alternative to get_plugin_data
@@ -188,6 +190,9 @@ class Postman {
* ref: http://codex.wordpress.org/Plugin_API/Action_Reference#Actions_Run_During_a_Typical_Request
*/
public function on_plugins_loaded() {
+
+ PostmanLicenseManager::get_instance()->init();
+
// load the text domain
$this->loadTextDomain();
@@ -215,6 +220,7 @@ class Postman {
* ref: https://codex.wordpress.org/Function_Reference/register_activation_hook
*/
public function on_activation() {
+
if ( $this->logger->isInfo() ) {
$this->logger->info( 'Activating plugin' );
}
diff --git a/Postman/PostmanAdminController.php b/Postman/PostmanAdminController.php
index 1e43c6d..128fa16 100644
--- a/Postman/PostmanAdminController.php
+++ b/Postman/PostmanAdminController.php
@@ -55,10 +55,6 @@ if ( ! class_exists( 'PostmanAdminController' ) ) {
const MULTISITE_SECTION = 'postman_multisite_section';
const ADVANCED_OPTIONS = 'postman_advanced_options';
const ADVANCED_SECTION = 'postman_advanced_section';
- const NOTIFICATIONS_OPTIONS = 'postman_notifications_options';
- const NOTIFICATIONS_SECTION = 'postman_notifications_section';
- const NOTIFICATIONS_PUSHOVER_CRED = 'postman_pushover_cred';
- const NOTIFICATIONS_SLACK_CRED = 'postman_slack_cred';
const EMAIL_VALIDATION_SECTION = 'postman_email_validation_section';
const EMAIL_VALIDATION_OPTIONS = 'postman_email_validation_options';
diff --git a/Postman/PostmanInputSanitizer.php b/Postman/PostmanInputSanitizer.php
index 75a0041..a8cdca7 100644
--- a/Postman/PostmanInputSanitizer.php
+++ b/Postman/PostmanInputSanitizer.php
@@ -73,16 +73,6 @@ if ( ! class_exists( 'PostmanInputSanitizer' ) ) {
$this->sanitizeInt( 'Transcript Size', PostmanOptions::TRANSCRIPT_SIZE, $input, $new_input );
$this->sanitizeString( 'Temporary Directory', PostmanOptions::TEMPORARY_DIRECTORY, $input, $new_input );
- // Notifications
- $this->sanitizeString( 'Pushover Service', PostmanOptions::NOTIFICATION_SERVICE, $input, $new_input, $this->options->getNotificationService() );
- $this->sanitizePassword( 'Pushover Username', PostmanOptions::PUSHOVER_USER, $input, $new_input, $this->options->getPushoverUser() );
- $this->sanitizePassword( 'Pushover Token', PostmanOptions::PUSHOVER_TOKEN, $input, $new_input, $this->options->getPushoverToken() );
- $this->sanitizePassword( 'Slack Token', PostmanOptions::SLACK_TOKEN, $input, $new_input, $this->options->getSlackToken() );
-
- // Chrome extension
- $this->sanitizeString( 'Push Chrome Extension', PostmanOptions::NOTIFICATION_USE_CHROME, $input, $new_input );
- $this->sanitizePassword( 'Push Chrome Extension UID', PostmanOptions::NOTIFICATION_CHROME_UID, $input, $new_input, $this->options->getNotificationChromeUid() );
-
// Fallback
$this->sanitizeString( 'Use fallback', PostmanOptions::FALLBACK_SMTP_ENABLED, $input, $new_input );
$this->sanitizeString( 'Fallback hostname', PostmanOptions::FALLBACK_SMTP_HOSTNAME, $input, $new_input );
diff --git a/Postman/PostmanOptions.php b/Postman/PostmanOptions.php
index e2e78d6..30434bd 100644
--- a/Postman/PostmanOptions.php
+++ b/Postman/PostmanOptions.php
@@ -109,12 +109,6 @@ if ( ! class_exists( 'PostmanOptions' ) ) {
const TRANSCRIPT_SIZE = 'transcript_size';
const TEMPORARY_DIRECTORY = 'tmp_dir';
const DISABLE_EMAIL_VALIDAITON = 'disable_email_validation';
- const NOTIFICATION_SERVICE = 'notification_service';
- const NOTIFICATION_USE_CHROME = 'notification_use_chrome';
- const NOTIFICATION_CHROME_UID = 'notification_chrome_uid';
- const PUSHOVER_USER = 'pushover_user';
- const PUSHOVER_TOKEN = 'pushover_token';
- const SLACK_TOKEN = 'slack_token';
// Fallback
const FALLBACK_SMTP_ENABLED = 'fallback_smtp_enabled';
@@ -133,7 +127,6 @@ if ( ! class_exists( 'PostmanOptions' ) ) {
const DEFAULT_MAIL_LOG_ENABLED = self::MAIL_LOG_ENABLED_OPTION_YES;
const DEFAULT_MAIL_LOG_ENTRIES = 250;
const DEFAULT_LOG_LEVEL = PostmanLogger::ERROR_INT;
- const DEFAULT_NOTIFICATION_SERVICE = 'default';
const DEFAULT_TRANSPORT_TYPE = 'smtp'; // must match what's in PostmanSmtpModuleTransport
const DEFAULT_TCP_READ_TIMEOUT = 60;
const DEFAULT_TCP_CONNECTION_TIMEOUT = 10;
@@ -247,13 +240,6 @@ if ( ! class_exists( 'PostmanOptions' ) ) {
} else { return self::DEFAULT_LOG_LEVEL; }
}
- public function getNotificationService() {
- if ( isset( $this->options [ PostmanOptions::NOTIFICATION_SERVICE ] ) ) {
- return $this->options [ PostmanOptions::NOTIFICATION_SERVICE ];
- } else {
- return self::DEFAULT_NOTIFICATION_SERVICE;
- }
- }
public function getForcedToRecipients() {
if ( isset( $this->options [ self::FORCED_TO_RECIPIENTS ] ) ) {
@@ -481,36 +467,6 @@ if ( ! class_exists( 'PostmanOptions' ) ) {
return $this->options [ PostmanOptions::MAILGUN_REGION ];
}
}
-
- public function getPushoverUser() {
- if ( isset( $this->options [ PostmanOptions::PUSHOVER_USER ] ) ) {
- return base64_decode( $this->options [ PostmanOptions::PUSHOVER_USER ] );
- }
- }
-
- public function getPushoverToken() {
- if ( isset( $this->options [ PostmanOptions::PUSHOVER_TOKEN ] ) ) {
- return base64_decode( $this->options [ PostmanOptions::PUSHOVER_TOKEN ] );
- }
- }
-
- public function getSlackToken() {
- if ( isset( $this->options [ PostmanOptions::SLACK_TOKEN ] ) ) {
- return base64_decode( $this->options [ PostmanOptions::SLACK_TOKEN ] );
- }
- }
-
- public function useChromeExtension() {
- if ( isset( $this->options [ PostmanOptions::NOTIFICATION_USE_CHROME ] ) ) {
- return $this->options [ PostmanOptions::NOTIFICATION_USE_CHROME ];
- }
- }
-
- public function getNotificationChromeUid() {
- if ( isset( $this->options [ PostmanOptions::NOTIFICATION_CHROME_UID ] ) ) {
- return base64_decode( $this->options [ PostmanOptions::NOTIFICATION_CHROME_UID ] );
- }
- }
public function getReplyTo() {
if ( isset( $this->options [ PostmanOptions::REPLY_TO ] ) ) {
diff --git a/Postman/PostmanWpMail.php b/Postman/PostmanWpMail.php
index 3a2b508..c108cce 100644
--- a/Postman/PostmanWpMail.php
+++ b/Postman/PostmanWpMail.php
@@ -25,6 +25,8 @@ if ( ! class_exists( 'PostmanWpMail' ) ) {
require_once 'Postman-Mail/PostmanMailEngine.php';
require_once 'Postman-Auth/PostmanAuthenticationManagerFactory.php';
require_once 'PostmanState.php';
+
+ PostmanEmailLogService::getInstance();
}
/**
@@ -95,7 +97,7 @@ if ( ! class_exists( 'PostmanWpMail' ) ) {
* @param mixed $headers
* @param mixed $attachments
*/
- private function processWpMailCall( $to, $subject, $message, $headers, $attachments ) {
+ public function processWpMailCall( $to, $subject, $message, $headers, $attachments ) {
$this->logger->trace( 'wp_mail parameters before applying WordPress wp_mail filter:' );
$this->traceParameters( $to, $subject, $message, $headers, $attachments );
@@ -199,7 +201,6 @@ if ( ! class_exists( 'PostmanWpMail' ) ) {
// apply the WordPress filters
// may impact the from address, from email, charset and content-type
$message->applyFilters();
- //do_action_ref_array( 'phpmailer_init', array( &$message ) );
// create the body parts (if they are both missing)
if ( $message->isBodyPartsEmpty() ) {
@@ -229,8 +230,13 @@ if ( ! class_exists( 'PostmanWpMail' ) ) {
}
$this->logger->debug( 'Sending mail' );
+
// may throw an exception attempting to contact the SMTP server
- $engine->send( $message );
+ if ( $send_email = apply_filters( 'post_smtp_do_send_email', true ) ) {
+ $engine->send($message);
+ } else {
+ $this->transcript = 'Bypassed By MailControl For Post SMTP';
+ }
// increment the success counter, unless we are just tesitng
if ( ! $testMode ) {
@@ -241,10 +247,10 @@ if ( ! class_exists( 'PostmanWpMail' ) ) {
// clean up
$this->postSend( $engine, $startTime, $options, $transport );
- if ( $options->getRunMode() == PostmanOptions::RUN_MODE_PRODUCTION || $options->getRunMode() == PostmanOptions::RUN_MODE_LOG_ONLY ) {
- // log the successful delivery
- PostmanEmailLogService::getInstance()->writeSuccessLog( $log, $message, $engine->getTranscript(), $transport );
- }
+ /**
+ * Do stuff after successful delivery
+ */
+ do_action( 'post_smtp_on_success', $log, $message, $engine->getTranscript(), $transport );
// return successful
return true;
@@ -263,10 +269,11 @@ if ( ! class_exists( 'PostmanWpMail' ) ) {
// clean up
$this->postSend( $engine, $startTime, $options, $transport );
- if ( $options->getRunMode() == PostmanOptions::RUN_MODE_PRODUCTION || $options->getRunMode() == PostmanOptions::RUN_MODE_LOG_ONLY ) {
- // log the failed delivery
- PostmanEmailLogService::getInstance()->writeFailureLog( $log, $message, $engine->getTranscript(), $transport, $e->getMessage() );
- }
+
+ /**
+ * Do stuff after failed delivery
+ */
+ do_action( 'post_smtp_on_failed', $log, $message, $engine->getTranscript(), $transport, $e->getMessage() );
// Fallback
if ( $this->fallback( $log, $message, $options ) ) {
diff --git a/Postman/notifications/PostmanNotify.php b/Postman/notifications/PostmanNotify.php
deleted file mode 100644
index 7654ecb..0000000
--- a/Postman/notifications/PostmanNotify.php
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-if ( ! defined( 'ABSPATH' ) ) {
- exit; // Exit if accessed directly
-}
-require_once 'INotify.php';
-require_once 'PostmanMailNotify.php';
-require_once 'PostmanPushoverNotify.php';
-require_once 'PostmanSlackNotify.php';
-
-class PostmanNotify {
- private $notify;
-
- public function __construct( Postman_Notify $notify ) {
- $this->notify = $notify;
- }
-
- public function send( $message, $log ) {
- $this->notify->send_message( $message );
- }
-
- public function push_to_chrome($message) {
- $push_chrome = PostmanOptions::getInstance()->useChromeExtension();
-
- if ( $push_chrome ) {
- $uid = PostmanOptions::getInstance()->getNotificationChromeUid();
-
- if ( empty( $uid ) ) {
- return;
- }
-
- $url = 'https://postmansmtp.com/chrome/' . $uid;
-
- $args = array(
- 'body' => array(
- 'message' => $message
- )
- );
-
- $response = wp_remote_post( $url , $args );
- }
- }
-} \ No newline at end of file