This commit is contained in:
2026-07-02 15:54:39 -06:00
commit 9883323161
17470 changed files with 4470592 additions and 0 deletions
@@ -0,0 +1,226 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Logging;
use Gravity_Forms\Gravity_SMTP\Apps\App_Service_Provider;
use Gravity_Forms\Gravity_SMTP\Apps\Config\Tools_Config;
use Gravity_Forms\Gravity_SMTP\Connectors\Connector_Service_Provider;
use Gravity_Forms\Gravity_SMTP\Data_Store\Const_Data_Store;
use Gravity_Forms\Gravity_SMTP\Data_Store\Data_Store_Router;
use Gravity_Forms\Gravity_SMTP\Data_Store\Opts_Data_Store;
use Gravity_Forms\Gravity_SMTP\Data_Store\Plugin_Opts_Data_Store;
use Gravity_Forms\Gravity_SMTP\Handler\Mail_Handler;
use Gravity_Forms\Gravity_SMTP\Logging\Config\Logging_Endpoints_Config;
use Gravity_Forms\Gravity_SMTP\Logging\Debug\Debug_Log_Event_Handler;
use Gravity_Forms\Gravity_SMTP\Logging\Debug\Debug_Logger;
use Gravity_Forms\Gravity_SMTP\Logging\Endpoints\Delete_Debug_Logs_Endpoint;
use Gravity_Forms\Gravity_SMTP\Logging\Endpoints\Delete_Email_Endpoint;
use Gravity_Forms\Gravity_SMTP\Logging\Endpoints\Delete_Events_Endpoint;
use Gravity_Forms\Gravity_SMTP\Logging\Endpoints\Get_Email_Message_Endpoint;
use Gravity_Forms\Gravity_SMTP\Logging\Endpoints\Get_Paginated_Debug_Log_Items_Endpoint;
use Gravity_Forms\Gravity_SMTP\Logging\Endpoints\Get_Paginated_Items_Endpoint;
use Gravity_Forms\Gravity_SMTP\Logging\Endpoints\Log_Item_Endpoint;
use Gravity_Forms\Gravity_SMTP\Logging\Endpoints\View_Log_Endpoint;
use Gravity_Forms\Gravity_SMTP\Logging\Log\Logger;
use Gravity_Forms\Gravity_SMTP\Logging\Log\WP_Mail_Logger;
use Gravity_Forms\Gravity_SMTP\Logging\Scheduling\Handler;
use Gravity_Forms\Gravity_SMTP\Utils\Attachments_Saver;
use Gravity_Forms\Gravity_Tools\Providers\Config_Service_Provider;
use Gravity_Forms\Gravity_Tools\Service_Container;
use Gravity_Forms\Gravity_Tools\Service_Provider;
use Gravity_Forms\Gravity_Tools\Utils\Utils_Service_Provider;
use Gravity_Forms\Gravity_SMTP\Models\Debug_Log_Model;
use Gravity_Forms\Gravity_Tools\Logging\DB_Logging_Provider;
use Gravity_Forms\Gravity_Tools\Logging\Parsers\File_Log_Parser;
class Logging_Service_Provider extends Config_Service_Provider {
const LOGGER = 'logger';
const WP_MAIL_LOGGER = 'wp_mail_logger';
const GET_PAGINATED_ITEMS_ENDPOINT = 'get_paginated_items_endpoint';
const GET_PAGINATED_DEBUG_LOG_ITEMS_ENDPOINT = 'get_paginated_debug_log_items_endpoint';
const DELETE_DEBUG_LOGS_ENDPOINT = 'delete_debug_logs_endpoint';
const DELETE_EMAIL_ENDPOINT = 'delete_email_endpoint';
const DELETE_EVENTS_ENDPOINT = 'delete_events_endpoint';
const GET_EMAIL_MESSAGE_ENDPOINT = 'get_email_message_endpoint';
const SCHEDULING_HANDLER = 'scheduling_handler';
const LOG_ITEM_ENDPOINT = 'log_item_endpoint';
const DEBUG_LOGGER = 'debug_logger_util';
const VIEW_DEBUG_LOG_ENDPOINT = 'view_debug_log_endpoint';
const DEBUG_LOG_DIR = 'debug_log_dir';
const DEBUG_LOG_FILEPATH = 'debug_log_filepath';
const DEBUG_LOG_MODEL = 'debug_log_model';
const DB_LOGGING_PROVIDER = 'db_logging_provider';
const DEBUG_LOG_EVENT_HANDLER = 'debug_log_event_handler';
const LOGGING_ENDPOINTS_CONFIG = 'logging_endpoints_config';
const RETENTION_ACTION_NAME = 'gravitysmtp_scheduler_handle_log_retention';
const DEBUG_LOG_RETENTION_CRON_HOOK = 'gravitysmtp_scheduler_handle_debug_retention';
protected $configs = array(
self::LOGGING_ENDPOINTS_CONFIG => Logging_Endpoints_Config::class,
);
public function register( Service_Container $container ) {
parent::register( $container );
$this->container->add( Connector_Service_Provider::DATA_STORE_CONST, function () {
return new Const_Data_Store();
} );
$this->container->add( Connector_Service_Provider::DATA_STORE_OPTS, function () {
return new Opts_Data_Store();
} );
$this->container->add( Connector_Service_Provider::DATA_STORE_PLUGIN_OPTS, function () {
return new Plugin_Opts_Data_Store();
} );
$this->container->add( Connector_Service_Provider::DATA_STORE_ROUTER, function () use ( $container ) {
return new Data_Store_Router( $container->get( Connector_Service_Provider::DATA_STORE_CONST ), $container->get( Connector_Service_Provider::DATA_STORE_OPTS ), $container->get( Connector_Service_Provider::DATA_STORE_PLUGIN_OPTS ) );
} );
$this->container->add( self::LOGGER, function () use ( $container ) {
return new Logger( $container->get( Connector_Service_Provider::LOG_DETAILS_MODEL ) );
} );
$this->container->add( self::WP_MAIL_LOGGER, function () use ( $container ) {
return new WP_Mail_Logger( $container->get( self::LOGGER ), $container->get( Connector_Service_Provider::EVENT_MODEL ), $container->get( Utils_Service_Provider::SOURCE_PARSER ), $container->get( Utils_Service_Provider::HEADER_PARSER ) );
} );
$this->container->add( self::DEBUG_LOG_MODEL, function () use ( $container ) {
return new Debug_Log_Model();
} );
$this->container->add( self::GET_PAGINATED_ITEMS_ENDPOINT, function () use ( $container ) {
return new Get_Paginated_Items_Endpoint( $container->get( Connector_Service_Provider::EVENT_MODEL ), $container->get( Utils_Service_Provider::RECIPIENT_PARSER ) );
} );
$this->container->add( self::GET_PAGINATED_DEBUG_LOG_ITEMS_ENDPOINT, function () use ( $container ) {
return new Get_Paginated_Debug_Log_Items_Endpoint( $container->get( self::DEBUG_LOG_MODEL ) );
} );
$this->container->add( self::DELETE_DEBUG_LOGS_ENDPOINT, function () use ( $container ) {
return new Delete_Debug_Logs_Endpoint( $container->get( self::DEBUG_LOG_MODEL ) );
} );
$this->container->add( self::DELETE_EMAIL_ENDPOINT, function () use ( $container ) {
return new Delete_Email_Endpoint( $container->get( Connector_Service_Provider::EVENT_MODEL ) );
} );
$this->container->add( self::DELETE_EVENTS_ENDPOINT, function () use ( $container ) {
return new Delete_Events_Endpoint( $container->get( Connector_Service_Provider::EVENT_MODEL ) );
} );
$this->container->add( self::GET_EMAIL_MESSAGE_ENDPOINT, function () use ( $container ) {
return new Get_Email_Message_Endpoint( $container->get( Connector_Service_Provider::EVENT_MODEL ) );
} );
$this->container->add( self::SCHEDULING_HANDLER, function () use ( $container ) {
return new Handler( $container->get( Connector_Service_Provider::DATA_STORE_ROUTER ), $container->get( Connector_Service_Provider::EVENT_MODEL ), $container->get( Connector_Service_Provider::LOG_DETAILS_MODEL ) );
} );
$this->container->add( self::DB_LOGGING_PROVIDER, function () use ( $container ) {
return new DB_Logging_Provider( $container->get( self::DEBUG_LOG_MODEL ) );
} );
$this->container->add( self::DEBUG_LOGGER, function () use ( $container ) {
$data = $container->get( Connector_Service_Provider::DATA_STORE_ROUTER );
$log_level = $data->get_plugin_setting( Tools_Config::SETTING_DEBUG_LOG_LEVEL, DB_Logging_Provider::DEBUG );
return new Debug_Logger( $container->get( self::DB_LOGGING_PROVIDER ), $log_level );
} );
$this->container->add( self::LOG_ITEM_ENDPOINT, function () use ( $container ) {
return new Log_Item_Endpoint( $container->get( self::DEBUG_LOGGER ) );
} );
$this->container->add( self::VIEW_DEBUG_LOG_ENDPOINT, function () use ( $container ) {
$debug_logger = $container->get( self::DEBUG_LOGGER );
$debug_model = $container->get( self::DEBUG_LOG_MODEL );
return new View_Log_Endpoint( $container->get( Connector_Service_Provider::DATA_STORE_ROUTER ), $debug_logger, $debug_model );
} );
$this->container->add( self::DEBUG_LOG_EVENT_HANDLER, function () use ( $container ) {
return new Debug_Log_Event_Handler( $container->get( self::DEBUG_LOGGER ), $container->get( Connector_Service_Provider::DATA_STORE_ROUTER ) );
} );
$this->container->add( Utils_Service_Provider::ATTACHMENTS_SAVER, function () use ( $container ) {
return new Attachments_Saver( $container->get( Logging_Service_Provider::DEBUG_LOGGER ) );
} );
}
public function init( Service_Container $container ) {
add_action( 'wp_ajax_' . Get_Paginated_Items_Endpoint::ACTION_NAME, function () use ( $container ) {
$container->get( self::GET_PAGINATED_ITEMS_ENDPOINT )->handle();
} );
add_action( 'wp_ajax_' . Get_Paginated_Debug_Log_Items_Endpoint::ACTION_NAME, function () use ( $container ) {
$container->get( self::GET_PAGINATED_DEBUG_LOG_ITEMS_ENDPOINT )->handle();
} );
add_action( 'wp_ajax_' . Delete_Debug_Logs_Endpoint::ACTION_NAME, function () use ( $container ) {
$container->get( self::DELETE_DEBUG_LOGS_ENDPOINT )->handle();
} );
add_action( 'wp_ajax_' . Delete_Email_Endpoint::ACTION_NAME, function () use ( $container ) {
$container->get( self::DELETE_EMAIL_ENDPOINT )->handle();
} );
add_action( 'wp_ajax_' . Delete_Events_Endpoint::ACTION_NAME, function () use ( $container ) {
$container->get( self::DELETE_EVENTS_ENDPOINT )->handle();
} );
add_action( 'wp_ajax_' . Get_Email_Message_Endpoint::ACTION_NAME, function () use ( $container ) {
$container->get( self::GET_EMAIL_MESSAGE_ENDPOINT )->handle();
} );
add_action( 'wp_ajax_' . Log_Item_Endpoint::ACTION_NAME, function () use ( $container ) {
$container->get( self::LOG_ITEM_ENDPOINT )->handle();
} );
add_action( 'wp_ajax_' . View_Log_Endpoint::ACTION_NAME, function () use ( $container ) {
$container->get( self::VIEW_DEBUG_LOG_ENDPOINT )->handle();
} );
add_action( 'wp_ajax_nopriv_' . View_Log_Endpoint::ACTION_NAME, function () use ( $container ) {
$container->get( self::VIEW_DEBUG_LOG_ENDPOINT )->handle();
} );
add_action( self::RETENTION_ACTION_NAME, function () use ( $container ) {
return $container->get( self::SCHEDULING_HANDLER )->run_log_retention();
} );
if ( ! Mail_Handler::is_minimally_configured() ) {
add_filter( 'wp_mail', function ( $mail_info ) use ( $container ) {
$container->get( self::WP_MAIL_LOGGER )->create_log( $mail_info );
return $mail_info;
} );
add_action( 'wp_mail_failed', function ( $wp_error ) use ( $container ) {
$container->get( self::WP_MAIL_LOGGER )->handle_failed( $wp_error );
} );
}
if ( ! wp_next_scheduled( self::RETENTION_ACTION_NAME ) ) {
wp_schedule_event( time(), 'daily', self::RETENTION_ACTION_NAME );
}
add_action( 'gravitysmtp_save_plugin_setting', function ( $setting, $value ) use ( $container ) {
$container->get( self::DEBUG_LOG_EVENT_HANDLER )->on_setting_update( $setting, $value );
}, 10, 2 );
if ( ! wp_next_scheduled( self::DEBUG_LOG_RETENTION_CRON_HOOK ) ) {
wp_schedule_event( time(), 'daily', self::DEBUG_LOG_RETENTION_CRON_HOOK );
}
add_action( self::DEBUG_LOG_RETENTION_CRON_HOOK, function () use ( $container ) {
$container->get( self::DEBUG_LOG_EVENT_HANDLER )->on_retention_cron();
} );
}
}
@@ -0,0 +1,102 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Logging\Config;
use Gravity_Forms\Gravity_SMTP\Logging\Endpoints\Delete_Debug_Logs_Endpoint;
use Gravity_Forms\Gravity_SMTP\Logging\Endpoints\Delete_Email_Endpoint;
use Gravity_Forms\Gravity_SMTP\Logging\Endpoints\Delete_Events_Endpoint;
use Gravity_Forms\Gravity_SMTP\Logging\Endpoints\Get_Email_Message_Endpoint;
use Gravity_Forms\Gravity_SMTP\Logging\Endpoints\Get_Paginated_Debug_Log_Items_Endpoint;
use Gravity_Forms\Gravity_SMTP\Logging\Endpoints\Get_Paginated_Items_Endpoint;
use Gravity_Forms\Gravity_SMTP\Logging\Endpoints\Log_Item_Endpoint;
use Gravity_Forms\Gravity_Tools\Config;
class Logging_Endpoints_Config extends Config {
protected $script_to_localize = 'gravitysmtp_scripts_admin';
protected $name = 'gravitysmtp_admin_config';
public function should_enqueue() {
return is_admin();
}
public function data() {
return array(
'common' => array(
'endpoints' => array(
Delete_Email_Endpoint::ACTION_NAME => array(
'action' => array(
'value' => Delete_Email_Endpoint::ACTION_NAME,
'default' => 'mock_endpoint',
),
'nonce' => array(
'value' => wp_create_nonce( Delete_Email_Endpoint::ACTION_NAME ),
'default' => 'nonce',
),
),
Delete_Events_Endpoint::ACTION_NAME => array(
'action' => array(
'value' => Delete_Events_Endpoint::ACTION_NAME,
'default' => 'mock_endpoint',
),
'nonce' => array(
'value' => wp_create_nonce( Delete_Events_Endpoint::ACTION_NAME ),
'default' => 'nonce',
),
),
Get_Email_Message_Endpoint::ACTION_NAME => array(
'action' => array(
'value' => Get_Email_Message_Endpoint::ACTION_NAME,
'default' => 'mock_endpoint',
),
'nonce' => array(
'value' => wp_create_nonce( Get_Email_Message_Endpoint::ACTION_NAME ),
'default' => 'nonce',
),
),
'activity_log_page' => array(
'action' => array(
'value' => Get_Paginated_Items_Endpoint::ACTION_NAME,
'default' => 'mock_endpoint',
),
'nonce' => array(
'value' => wp_create_nonce( Get_Paginated_Items_Endpoint::ACTION_NAME ),
'default' => 'nonce',
),
),
'debug_log_page' => array(
'action' => array(
'value' => Get_Paginated_Debug_Log_Items_Endpoint::ACTION_NAME,
'default' => 'mock_endpoint',
),
'nonce' => array(
'value' => wp_create_nonce( Get_Paginated_Debug_Log_Items_Endpoint::ACTION_NAME ),
'default' => 'nonce',
),
),
Delete_Debug_Logs_Endpoint::ACTION_NAME => array(
'action' => array(
'value' => Delete_Debug_Logs_Endpoint::ACTION_NAME,
'default' => 'mock_endpoint',
),
'nonce' => array(
'value' => wp_create_nonce( Delete_Debug_Logs_Endpoint::ACTION_NAME ),
'default' => 'nonce',
),
),
Log_Item_Endpoint::ACTION_NAME => array(
'action' => array(
'value' => Log_Item_Endpoint::ACTION_NAME,
'default' => 'mock_endpoint',
),
'nonce' => array(
'value' => wp_create_nonce( Log_Item_Endpoint::ACTION_NAME ),
'default' => 'nonce',
),
),
),
),
);
}
}
@@ -0,0 +1,78 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Logging\Debug;
use Gravity_Forms\Gravity_SMTP\Apps\Config\Tools_Config;
use Gravity_Forms\Gravity_SMTP\Data_Store\Data_Store_Router;
use Gravity_Forms\Gravity_SMTP\Gravity_SMTP;
use Gravity_Forms\Gravity_SMTP\Logging\Endpoints\View_Log_Endpoint;
use Gravity_Forms\Gravity_SMTP\Logging\Logging_Service_Provider;
class Debug_Log_Event_Handler {
const DEBUG_LOG_ENABLE_TIME = 'debug_log_enable_time';
/**
* @var Debug_Logger
*/
protected $debug_logger;
/**
* @var Data_Store_Router
*/
protected $data;
public function __construct( Debug_Logger $debug_logger, Data_Store_Router $data ) {
$this->debug_logger = $debug_logger;
$this->data = $data;
}
public function on_setting_update( $setting, $value ) {
if ( $setting !== Tools_Config::SETTING_DEBUG_LOG_ENABLED ) {
return;
}
// Delete verification key when disabled.
if ( $value === false || $value === 0 || $value === '0' || $value === 'false' ) {
delete_option( View_Log_Endpoint::OPTION_VERIFICATION_KEY );
delete_option( self::DEBUG_LOG_ENABLE_TIME );
$delete_log_on_deactivate = apply_filters( 'gravitysmtp_delete_log_on_deactivate', false );
if ( $delete_log_on_deactivate ) {
$this->debug_logger->delete_log();
}
return;
}
// Refresh verficiation key when enabled.
$bytes = random_bytes( 12 );
$random = bin2hex( $bytes );
update_option( View_Log_Endpoint::OPTION_VERIFICATION_KEY, $random );
update_option( self::DEBUG_LOG_ENABLE_TIME, time() );
}
public function on_retention_cron() {
$enabled = get_option( self::DEBUG_LOG_ENABLE_TIME );
if ( empty( $enabled ) ) {
return;
}
$period_in_days = $this->data->get_plugin_setting( Tools_Config::SETTING_DEBUG_LOG_RETENTION, 7 );
$now = date_create( 'now' );
$enabled = date_create( date( 'Y-m-d H:i:s', $enabled ) );
$interval = date_diff( $now, $enabled );
$diff = $interval->format( '%a' );
if ( (int) $diff < (int) $period_in_days ) {
return;
}
$this->debug_logger->delete_log();
}
}
@@ -0,0 +1,73 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Logging\Debug;
use Gravity_Forms\Gravity_SMTP\Apps\Config\Tools_Config;
use Gravity_Forms\Gravity_SMTP\Connectors\Connector_Service_Provider;
use Gravity_Forms\Gravity_SMTP\Gravity_SMTP;
use Gravity_Forms\Gravity_SMTP\Logging\Logging_Service_Provider;
use Gravity_Forms\Gravity_Tools\Logging\DB_Logging_Provider;
use Gravity_Forms\Gravity_Tools\Logging\Logger;
use Gravity_Forms\Gravity_Tools\Logging\Logging_Provider;
class Debug_Logger extends Logger {
protected $log_level;
protected $priority_map = array(
'debug' => DB_Logging_Provider::DEBUG,
'info' => DB_Logging_Provider::INFO,
'warning' => DB_Logging_Provider::WARN,
'error' => DB_Logging_Provider::ERROR,
'fatal' => DB_Logging_Provider::FATAL,
);
public function __construct( Logging_Provider $provider, $log_level ) {
parent::__construct( $provider );
$this->log_level = $log_level;
}
public static function log_message( $message, $priority ) {
$container = Gravity_SMTP::$container;
/**
* @var self $logger
*/
$logger = $container->get( Logging_Service_Provider::DEBUG_LOGGER );
$logger->log( $message, $priority );
}
public function should_log( $log_level = 'all' ) {
$container = Gravity_SMTP::container();
$data = $container->get( Connector_Service_Provider::DATA_STORE_ROUTER );
$enabled = $data->get_plugin_setting( Tools_Config::SETTING_DEBUG_LOG_ENABLED, false );
if ( $enabled === false || $enabled === 0 || $enabled === '0' || $enabled === 'false' ) {
return false;
}
if ( $log_level === 'all' ) {
return true;
}
$level_prio = $this->map_priority_string( $log_level );
return $level_prio >= $this->log_level;
}
public function delete_log() {
$this->provider->delete_log();
}
public function map_priority_string( $priority_string ) {
if ( isset( $this->priority_map[ $priority_string ] ) ) {
return $this->priority_map[ $priority_string ];
}
return DB_Logging_Provider::DEBUG;
}
public function get_log_items() {
return $this->provider->get_lines();
}
}
@@ -0,0 +1,17 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Logging\Debug;
use Gravity_Forms\Gravity_Tools\Logging\Logger;
class Null_Logger extends Logger {
protected function should_log() {
return false;
}
protected function delete_log() {
return;
}
}
@@ -0,0 +1,44 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Logging\Debug;
use Gravity_Forms\Gravity_Tools\Logging\Logging_Provider;
class Null_Logging_Provider implements Logging_Provider {
public function log_info( $line ) {
return;
}
public function log_debug( $line ) {
return;
}
public function log_warning( $line ) {
return;
}
public function log_error( $line ) {
return;
}
public function log_fatal( $line ) {
return;
}
public function log( $line, $priority ) {
return;
}
public function delete_log() {
return;
}
public function write_line_to_log( $line ) {
return;
}
public function get_lines() {
return;
}
}
@@ -0,0 +1,48 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Logging\Endpoints;
use Gravity_Forms\Gravity_SMTP\Models\Debug_Log_Model;
use Gravity_Forms\Gravity_SMTP\Users\Roles;
use Gravity_Forms\Gravity_Tools\Endpoints\Endpoint;
class Delete_Debug_Logs_Endpoint extends Endpoint {
const PARAM_ALL_LOGS = 'all_logs';
const ACTION_NAME = 'delete_debug_logs';
protected $minimum_cap = Roles::DELETE_DEBUG_LOG;
/**
* @var Debug_Log_Model
*/
protected $logs;
protected $required_params = array(
self::PARAM_ALL_LOGS,
);
public function __construct( Debug_Log_Model $logs ) {
$this->logs = $logs;
}
protected function get_nonce_name() {
return self::ACTION_NAME;
}
public function handle() {
if ( ! $this->validate() ) {
wp_send_json_error( __( 'Missing required parameters.', 'gravitysmtp' ), 400 );
}
$delete_all_logs = filter_input( INPUT_POST, self::PARAM_ALL_LOGS );
$delete_all_logs = htmlspecialchars( $delete_all_logs );
if ( $delete_all_logs == '1' ) {
$this->logs->clear();
wp_send_json_success( array( 'message' => __( 'All logs deleted successfully', 'gravitysmtp' ) ), 200 );
}
}
}
@@ -0,0 +1,54 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Logging\Endpoints;
use Gravity_Forms\Gravity_SMTP\Models\Event_Model;
use Gravity_Forms\Gravity_SMTP\Users\Roles;
use Gravity_Forms\Gravity_Tools\Endpoints\Endpoint;
class Delete_Email_Endpoint extends Endpoint {
const PARAM_EVENT_ID = 'event_id';
const ACTION_NAME = 'delete_email';
protected $minimum_cap = Roles::DELETE_EMAIL_LOG;
/**
* @var Event_Model
*/
protected $emails;
public function __construct( Event_Model $emails ) {
$this->emails = $emails;
}
protected function get_nonce_name() {
return self::ACTION_NAME;
}
public function handle() {
if ( ! $this->validate() ) {
wp_send_json_error( __( 'Missing required parameters.', 'gravitysmtp' ), 400 );
}
$event_id = filter_input( INPUT_POST, self::PARAM_EVENT_ID, FILTER_SANITIZE_NUMBER_INT );
$this->emails->delete( $event_id );
wp_send_json_success( array( 'message' => __( 'Event deleted successfully', 'gravitysmtp' ) ), 200 );
}
protected function validate() {
if ( ! parent::validate() ) {
return false;
}
if ( empty( $_REQUEST[ self::PARAM_EVENT_ID ] ) ) {
return false;
}
return true;
}
}
@@ -0,0 +1,70 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Logging\Endpoints;
use Gravity_Forms\Gravity_SMTP\Models\Event_Model;
use Gravity_Forms\Gravity_SMTP\Users\Roles;
use Gravity_Forms\Gravity_Tools\Endpoints\Endpoint;
class Delete_Events_Endpoint extends Endpoint {
const PARAM_EVENT_IDS = 'event_ids';
const PARAM_ALL_EVENTS = 'all_events';
const PARAM_MAX_DATE = 'max_date';
const ACTION_NAME = 'delete_events';
protected $minimum_cap = Roles::DELETE_EMAIL_LOG;
/**
* @var Event_Model
*/
protected $events;
protected $required_params = array(
self::PARAM_EVENT_IDS,
self::PARAM_ALL_EVENTS,
);
public function __construct( Event_Model $events ) {
$this->events = $events;
}
protected function get_nonce_name() {
return self::ACTION_NAME;
}
public function handle() {
if ( ! $this->validate() ) {
wp_send_json_error( __( 'Missing required parameters.', 'gravitysmtp' ), 400 );
}
$delete_all_events = filter_input( INPUT_POST, self::PARAM_ALL_EVENTS );
$delete_all_events = htmlspecialchars( $delete_all_events );
$max_date = filter_input( INPUT_POST, self::PARAM_MAX_DATE );
if ( ! empty( $max_date ) ) {
$max_date = htmlspecialchars( $max_date );
}
if ( ! empty( $max_date ) && $delete_all_events == '1' ) {
$this->events->delete_before( $max_date );
wp_send_json_success( array( 'message' => __( 'Events deleted successfully', 'gravitysmtp' ) ), 200 );
}
if ( $delete_all_events == '1' ) {
$this->events->delete_all();
wp_send_json_success( array( 'message' => __( 'All events deleted successfully', 'gravitysmtp' ) ), 200 );
}
$event_ids = filter_input( INPUT_POST, self::PARAM_EVENT_IDS, FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
foreach( $event_ids as $id ) {
$id_to_delete = filter_var( $id, FILTER_SANITIZE_NUMBER_INT );
$this->events->delete( $id_to_delete );
}
wp_send_json_success( array( 'message' => $event_ids ), 200 );
}
}
@@ -0,0 +1,181 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Logging\Endpoints;
use Gravity_Forms\Gravity_SMTP\Models\Event_Model;
use Gravity_Forms\Gravity_SMTP\Users\Roles;
use Gravity_Forms\Gravity_Tools\Endpoints\Endpoint;
class Get_Email_Message_Endpoint extends Endpoint {
const PARAM_EVENT_ID = 'event_id';
const ACTION_NAME = 'get_email_message';
protected $minimum_cap = Roles::VIEW_EMAIL_LOG_DETAILS;
/**
* @var Event_Model
*/
protected $emails;
public function __construct( Event_Model $emails ) {
$this->emails = $emails;
}
protected function get_nonce_name() {
return self::ACTION_NAME;
}
public function handle() {
if ( ! $this->validate() ) {
wp_send_json_error( __( 'Missing required parameters.', 'gravitysmtp' ), 400 );
}
$event_id = filter_input( INPUT_GET, self::PARAM_EVENT_ID, FILTER_SANITIZE_NUMBER_INT );
$email = $this->emails->find( array( array( 'id', '=', $event_id ) ) );
if ( empty( $email[0] ) ) {
header( 'Content-Type: text/html' );
/* translators: %d: email ID */
echo sprintf( __( 'Could not get content for email ID: %d.', 'gravitysmtp' ), $email );
wp_die();
}
header( 'Content-Type: text/html' );
echo $this->format_email_content( $email[0]['message'] );
wp_die();
}
protected function format_email_content( $content ) {
if ( $content !== strip_tags( $content ) ) {
// Open links in a new tab (target) and harden with rel=noopener noreferrer where needed.
$content = preg_replace_callback(
'/<a\s([^>]*?)>/i',
function ( $matches ) {
$attrs = $matches[1];
$trimmed = trim( $attrs );
if ( '' === $trimmed ) {
return $matches[0];
}
$attrs = $this->ensure_anchor_target_blank( $attrs );
$attrs = $this->ensure_anchor_rel_noopener_noreferrer( $attrs );
return '<a ' . trim( $attrs ) . '>';
},
$content
);
return $content;
} else {
return '<pre style="white-space: pre-wrap; word-break: break-all; color: #242748; padding: 20px 25px; font-size: 13px; font-family: inter, -apple-system, blinkmacsystemfont, \'Segoe UI\', roboto, oxygen-sans, ubuntu, cantarell, \'Helvetica Neue\';">' . htmlspecialchars( $content ) . '</pre><style>body { margin: 0; background: #fff; }</style>';
}
}
/**
* Ensures anchor tags open in a new tab when attributes are present.
*
* @param string $attrs Raw attribute string from the opening &lt;a&gt; tag.
*
* @return string
*/
protected function ensure_anchor_target_blank( $attrs ) {
if ( preg_match( '/\btarget\s*=\s*(["\']?)_blank\1/i', $attrs ) ) {
return $attrs;
}
if ( preg_match( '/\btarget\s*=\s*("|\')(.*?)\1/is', $attrs ) ) {
return preg_replace( '/\btarget\s*=\s*("|\')(.*?)\1/is', 'target="_blank"', $attrs, 1 );
}
if ( preg_match( '/\btarget\s*=\s*[^\s>]+/i', $attrs ) ) {
return preg_replace( '/\btarget\s*=\s*[^\s>]+/i', 'target="_blank"', $attrs, 1 );
}
return rtrim( $attrs ) . ' target="_blank"';
}
/**
* Ensures rel includes noopener and noreferrer (safe external links with target _blank).
*
* @param string $attrs Raw attribute string from the opening &lt;a&gt; tag.
*
* @return string
*/
protected function ensure_anchor_rel_noopener_noreferrer( $attrs ) {
$rel_quoted = '/\brel\s*=\s*(["\'])(.*?)\1/is';
if ( preg_match( $rel_quoted, $attrs, $rel_match ) ) {
$tokens = preg_split( '/\s+/', trim( $rel_match[2] ), -1, PREG_SPLIT_NO_EMPTY );
if ( $this->rel_has_noopener_and_noreferrer( $tokens ) ) {
return $attrs;
}
$tokens = $this->merge_rel_noopener_noreferrer_tokens( $tokens );
$new_rel = implode( ' ', $tokens );
return preg_replace( $rel_quoted, 'rel="' . $new_rel . '"', $attrs, 1 );
}
if ( preg_match( '/\brel\s*=\s*([^\s>]+)/i', $attrs, $rel_match ) ) {
$tokens = preg_split( '/\s+/', trim( $rel_match[1] ), -1, PREG_SPLIT_NO_EMPTY );
if ( $this->rel_has_noopener_and_noreferrer( $tokens ) ) {
return $attrs;
}
$tokens = $this->merge_rel_noopener_noreferrer_tokens( $tokens );
$new_rel = implode( ' ', $tokens );
return preg_replace( '/\brel\s*=\s*[^\s>]+/i', 'rel="' . $new_rel . '"', $attrs, 1 );
}
return rtrim( $attrs ) . ' rel="noopener noreferrer"';
}
/**
* @param array $tokens rel attribute tokens.
*
* @return bool
*/
protected function rel_has_noopener_and_noreferrer( array $tokens ) {
$lower = array_map( 'strtolower', $tokens );
return in_array( 'noopener', $lower, true ) && in_array( 'noreferrer', $lower, true );
}
/**
* @param array $tokens rel attribute tokens.
*
* @return array
*/
protected function merge_rel_noopener_noreferrer_tokens( array $tokens ) {
$lower = array_map( 'strtolower', $tokens );
if ( ! in_array( 'noopener', $lower, true ) ) {
$tokens[] = 'noopener';
}
if ( ! in_array( 'noreferrer', $lower, true ) ) {
$tokens[] = 'noreferrer';
}
return $tokens;
}
protected function validate() {
if ( ! parent::validate() ) {
return false;
}
if ( empty( $_REQUEST[ self::PARAM_EVENT_ID ] ) ) {
return false;
}
return true;
}
}
@@ -0,0 +1,156 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Logging\Endpoints;
use Gravity_Forms\Gravity_SMTP\Models\Debug_Log_Model;
use Gravity_Forms\Gravity_SMTP\Users\Roles;
use Gravity_Forms\Gravity_Tools\Endpoints\Endpoint;
class Get_Paginated_Debug_Log_Items_Endpoint extends Endpoint {
const PARAM_PER_PAGE = 'per_page';
const PARAM_REQUESTED_PAGE = 'requested_page';
const PARAM_MAX_DATE = 'max_date';
const PARAM_SEARCH_TERM = 'search_term';
const PARAM_SEARCH_TYPE = 'search_type';
const PARAM_PRIORITY = 'priority';
const ACTION_NAME = 'get_paginated_debug_log_items';
protected $minimum_cap = Roles::VIEW_DEBUG_LOG;
/**
* @var Debug_Log_Model
*/
protected $events;
public function __construct( Debug_Log_Model $event_model ) {
$this->events = $event_model;
}
protected function get_nonce_name() {
return self::ACTION_NAME;
}
public function handle() {
if ( ! $this->validate() ) {
wp_send_json_error( __( 'Missing required parameters.', 'gravitysmtp' ), 400 );
}
$per_page = filter_input( INPUT_POST, 'per_page', FILTER_SANITIZE_NUMBER_INT );
$requested_page = filter_input( INPUT_POST, 'requested_page', FILTER_SANITIZE_NUMBER_INT );
$max_date = filter_input( INPUT_POST, 'max_date' );
$search_term = filter_input( INPUT_POST, 'search_term' );
$search_type = filter_input( INPUT_POST, 'search_type' );
$priority = filter_input( INPUT_POST, 'priority' );
if ( ! empty( $max_date ) ) {
$max_date = htmlspecialchars( $max_date );
}
if ( ! empty( $search_term ) ) {
$search_term = htmlspecialchars( $search_term );
}
if ( ! empty( $search_type ) ) {
$search_type = htmlspecialchars( $search_type );
}
if ( ! empty( $priority ) ) {
$priority = htmlspecialchars( $priority );
}
$requested_page = intval( $requested_page );
$offset = ( $requested_page - 1 ) * $per_page;
if ( ! $max_date ) {
$max_date = date( 'Y-m-d H:i:s', time() );
}
if ( empty( $per_page ) ) {
$per_page = 20;
}
$rows = $this->events->paginate( $requested_page, $per_page, $max_date, $search_term, $search_type, $priority );
$count = $this->events->count( $search_term, $search_type, $priority );
$data = array(
'rows' => $this->get_formatted_data_rows( $rows ),
'total' => $count,
'row_count' => count( $rows ),
);
wp_send_json_success( $data );
}
private function get_formatted_data_rows( $data ) {
return $this->events->lines_as_data_grid( $data );
}
private function get_grid_actions( $event_id ) {
$actions = array(
'component' => 'Box',
'components' => array(
array(
'component' => 'Button',
'props' => array(
'action' => 'view',
'customAttributes' => array(
'title' => esc_html__( 'View email log', 'gravitysmtp' ),
),
'customClasses' => array( 'gravitysmtp-data-grid__action' ),
'icon' => 'information-circle',
'iconPrefix' => 'gravity-component-icon',
'spacing' => [ 0, 2, 0, 0 ],
'size' => 'size-height-s',
'type' => 'icon-white',
'data' => array(
'event_id' => $event_id,
),
'disabled' => ! current_user_can( Roles::VIEW_EMAIL_LOG_DETAILS ),
),
),
array(
'component' => 'Button',
'props' => array(
'action' => 'preview',
'customAttributes' => array(
'title' => esc_html__( 'View email', 'gravitysmtp' ),
),
'customClasses' => array( 'gravitysmtp-data-grid__action' ),
'icon' => 'eye',
'iconPrefix' => 'gravity-admin-icon',
'spacing' => [ 0, 2, 0, 0 ],
'size' => 'size-height-s',
'type' => 'icon-white',
'data' => array(
'event_id' => $event_id,
),
'disabled' => ! current_user_can( Roles::VIEW_EMAIL_LOG_PREVIEW ),
),
),
array(
'component' => 'Button',
'props' => array(
'action' => 'delete',
'customAttributes' => array(
'title' => esc_html__( 'Delete email log', 'gravitysmtp' ),
),
'customClasses' => array( 'gravitysmtp-data-grid__action' ),
'icon' => 'trash',
'iconPrefix' => 'gravity-admin-icon',
'size' => 'size-height-s',
'type' => 'icon-white',
'data' => array(
'event_id' => $event_id,
),
'disabled' => ! current_user_can( Roles::DELETE_EMAIL_LOG ),
),
),
),
);
return apply_filters( 'gravitysmtp_debug_log_actions', $actions );
}
}
@@ -0,0 +1,309 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Logging\Endpoints;
use Gravity_Forms\Gravity_SMTP\Enums\Integration_Enum;
use Gravity_Forms\Gravity_SMTP\Enums\Status_Enum;
use Gravity_Forms\Gravity_SMTP\Models\Event_Model;
use Gravity_Forms\Gravity_SMTP\Users\Roles;
use Gravity_Forms\Gravity_SMTP\Utils\Recipient_Parser;
use Gravity_Forms\Gravity_Tools\Endpoints\Endpoint;
class Get_Paginated_Items_Endpoint extends Endpoint {
const PARAM_PER_PAGE = 'per_page';
const PARAM_REQUESTED_PAGE = 'requested_page';
const PARAM_MAX_DATE = 'max_date';
const PARAM_SEARCH_TERM = 'search_term';
const PARAM_SEARCH_TYPE = 'search_type';
const PARAM_SORT_BY = 'sort_by';
const PARAM_SORT_ORDER = 'sort_order';
const PARAM_FILTERS = 'filters';
const ACTION_NAME = 'get_paginated_items';
protected $minimum_cap = Roles::VIEW_EMAIL_LOG;
/**
* @var Event_Model
*/
protected $events;
/**
* @var Recipient_Parser
*/
protected $parser;
public function __construct( Event_Model $event_model, Recipient_Parser $parser ) {
$this->events = $event_model;
$this->parser = $parser;
}
protected function get_nonce_name() {
return self::ACTION_NAME;
}
public function handle() {
if ( ! $this->validate() ) {
wp_send_json_error( __( 'Missing required parameters.', 'gravitysmtp' ), 400 );
}
$per_page = filter_input( INPUT_POST, self::PARAM_PER_PAGE, FILTER_SANITIZE_NUMBER_INT );
$requested_page = filter_input( INPUT_POST, self::PARAM_REQUESTED_PAGE, FILTER_SANITIZE_NUMBER_INT );
$max_date = filter_input( INPUT_POST, self::PARAM_MAX_DATE );
$search_term = filter_input( INPUT_POST, self::PARAM_SEARCH_TERM );
$search_type = filter_input( INPUT_POST, self::PARAM_SEARCH_TYPE );
$sort_by = filter_input( INPUT_POST, self::PARAM_SORT_BY );
$sort_order = filter_input( INPUT_POST, self::PARAM_SORT_ORDER );
$filters = filter_input( INPUT_POST, self::PARAM_FILTERS, FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
if ( ! empty( $max_date ) ) {
$max_date = htmlspecialchars( $max_date );
}
if ( ! empty( $search_term ) ) {
$search_term = htmlspecialchars( $search_term );
}
if ( ! empty( $search_type ) ) {
$search_type = htmlspecialchars( $search_type );
}
if ( ! empty( $sort_by ) ) {
$sort_by = htmlspecialchars( $sort_by );
}
if ( ! empty( $sort_order ) ) {
$sort_order = htmlspecialchars( $sort_order );
}
$requested_page = intval( $requested_page );
$offset = ( $requested_page - 1 ) * $per_page;
if ( ! $max_date ) {
$max_date = date( 'Y-m-d H:i:s', time() );
}
if ( empty( $per_page ) ) {
$per_page = 20;
}
if ( ! is_array( $filters ) || empty( $filters ) ) {
$filters = array();
}
$rows = $this->events->paginate( $requested_page, $per_page, $max_date, $search_term, $search_type, $sort_by, $sort_order, $filters );
$count = $this->events->count( $search_term, $search_type, $filters );
$data = array(
'rows' => $this->get_formatted_data_rows( $rows ),
'total' => $count,
'row_count' => count( $rows ),
);
wp_send_json_success( $data );
}
private function get_formatted_data_rows( $data ) {
$rows = array();
foreach ( $data as $row ) {
$grid_actions = $this->get_grid_actions( $row );
$extra = strpos( $row['extra'], '{' ) === 0 ? json_decode( $row['extra'], true ) : unserialize( $row['extra'] );
$to = isset( $extra['to'] ) ? $extra['to'] : '';
$to_address = $this->parser->parse( $to )->first()->email();
$more_count = max( 0, $row['email_counts'] - 1 );
$rows[] = array(
'id' => $row['id'],
'subject' => array(
'component' => 'Button',
'props' => array(
'action' => 'view',
'customClasses' => array( 'gravitysmtp-data-grid__subject' ),
'label' => $row['subject'],
'type' => 'unstyled',
'data' => array(
'event_id' => $row['id'],
),
),
),
'status' => array(
'component' => 'StatusIndicator',
'props' => array(
'label' => Status_Enum::label( $row['status'] ),
'status' => Status_Enum::indicator( $row['status'] ),
'hasDot' => false,
),
),
'to' => array(
'component' => 'Box',
'props' => array(
'customClasses' => array( 'gravitysmtp-activity-log-app__activity-log-table-recipient' ),
'display' => 'flex',
),
'components' => array(
array(
'component' => 'Box',
'props' => array(
'customClasses' => array( 'gravitysmtp-activity-log-app__activity-log-table-recipient-meta' ),
'display' => 'flex',
),
'components' => array(
array(
'component' => 'Gravatar',
'props' => array(
'circular' => true,
'customClasses' => array( 'gravitysmtp-activity-log-app__activity-log-table-recipient-gravatar' ),
'defaultImage' => 'mp',
'emailHash' => hash( 'sha256', $to_address ),
'height' => 24,
'width' => 24,
),
),
array(
'component' => $more_count > 0 ? 'Text' : null,
'props' => array(
'content' => '+' . (string) $more_count,
'customClasses' => array( 'gravitysmtp-activity-log-app__activity-log-table-recipient-more' ),
'size' => 'text-xxs',
),
),
),
),
array(
'component' => 'Text',
'props' => array(
'content' => $to_address,
'customClasses' => array( 'gravitysmtp-activity-log-app__activity-log-table-recipient-email' ),
'size' => 'text-sm',
),
),
),
),
'source' => array(
'component' => 'Text',
'props' => array(
'content' => $row['source'],
'size' => 'text-sm',
),
),
'integration' => array(
'external' => true,
'key' => $row['service'] . '_logo',
'props' => array(
'height' => 24,
'title' => Integration_Enum::svg_title( $row['service'] ),
'width' => 24,
),
),
'date' => array(
'component' => 'Text',
'props' => array(
'content' => $this->convert_dates_to_timezone( $row['date_updated'] ),
'size' => 'text-sm',
),
),
'actions' => $grid_actions,
);
}
return $rows;
}
private function convert_dates_to_timezone( $date ) {
$gmt_time = new \DateTimeZone( 'UTC' );
$local_time = new \DateTimeZone( wp_timezone_string() );
$datetime = new \DateTime( $date, $gmt_time );
$datetime->setTimezone( $local_time );
return $datetime->format( 'F d, Y \a\t h:ia' );
}
private function get_grid_actions( $row ) {
$actions = array(
'component' => 'Box',
'components' => array(
array(
'component' => 'Button',
'props' => array(
'action' => 'view',
'customAttributes' => array(
'title' => esc_html__( 'View email log', 'gravitysmtp' ),
),
'customClasses' => array( 'gravitysmtp-data-grid__action' ),
'icon' => 'information-circle',
'iconPrefix' => 'gravity-component-icon',
'spacing' => [ 0, 2, 0, 0 ],
'size' => 'size-height-s',
'type' => 'icon-white',
'data' => array(
'event_id' => $row['id'],
),
'disabled' => ! current_user_can( Roles::VIEW_EMAIL_LOG_DETAILS ),
),
),
array(
'component' => 'Button',
'props' => array(
'action' => 'preview',
'customAttributes' => array(
'title' => esc_html__( 'View email', 'gravitysmtp' ),
),
'customClasses' => array( 'gravitysmtp-data-grid__action' ),
'icon' => 'eye',
'iconPrefix' => 'gravity-admin-icon',
'spacing' => [ 0, 2, 0, 0 ],
'size' => 'size-height-s',
'type' => 'icon-white',
'data' => array(
'event_id' => $row['id'],
),
'disabled' => ! current_user_can( Roles::VIEW_EMAIL_LOG_PREVIEW ),
),
),
array(
'component' => 'Button',
'props' => array(
'action' => 'resend',
'customAttributes' => array(
'title' => esc_html__( 'Resend email', 'gravitysmtp' ),
),
'customClasses' => array( 'gravitysmtp-data-grid__action' ),
'icon' => 'paper-plane',
'iconPrefix' => 'gravity-admin-icon',
'spacing' => [ 0, 2, 0, 0 ],
'size' => 'size-height-s',
'type' => 'icon-white',
'data' => array(
'event_id' => $row['id'],
),
'disabled' => ! current_user_can( Roles::VIEW_EMAIL_LOG_PREVIEW ) || ! $row['can_resend'],
// @todo: Add resend permission?
),
),
array(
'component' => 'Button',
'props' => array(
'action' => 'delete',
'customAttributes' => array(
'title' => esc_html__( 'Delete email log', 'gravitysmtp' ),
),
'customClasses' => array( 'gravitysmtp-data-grid__action' ),
'icon' => 'trash',
'iconPrefix' => 'gravity-admin-icon',
'size' => 'size-height-s',
'type' => 'icon-white',
'data' => array(
'event_id' => $row['id'],
),
'disabled' => ! current_user_can( Roles::DELETE_EMAIL_LOG ),
),
),
),
);
return apply_filters( 'gravitysmtp_email_log_actions', $actions );
}
}
@@ -0,0 +1,60 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Logging\Endpoints;
use Gravity_Forms\Gravity_SMTP\Logging\Debug\Debug_Logger;
use Gravity_Forms\Gravity_SMTP\Users\Roles;
use Gravity_Forms\Gravity_Tools\Endpoints\Endpoint;
class Log_Item_Endpoint extends Endpoint {
const PARAM_LOG_MESSAGE = 'message';
const PARAM_PRIORITY = 'priority';
const ACTION_NAME = 'log_debug_item';
protected $minimum_cap = Roles::EDIT_EMAIL_LOG;
/**
* @var Debug_Logger
*/
protected $logger;
public function __construct( Debug_Logger $logger ) {
$this->logger = $logger;
}
protected function get_nonce_name() {
return self::ACTION_NAME;
}
public function handle() {
if ( ! $this->validate() ) {
wp_send_json_error( __( 'Missing required parameters.', 'gravitysmtp' ), 400 );
}
$message = filter_input( INPUT_POST, self::PARAM_LOG_MESSAGE );
$priority = filter_input( INPUT_POST, self::PARAM_PRIORITY );
if ( ! empty( $message ) ) {
$message = htmlspecialchars( $message );
}
$this->logger->log( $message, $priority );
wp_send_json_success( array( 'message' => __( 'Message logged', 'gravitysmtp' ) ), 200 );
}
protected function validate() {
if ( ! parent::validate() ) {
return false;
}
if ( empty( $_REQUEST[ self::PARAM_LOG_MESSAGE ] ) ) {
return false;
}
return true;
}
}
@@ -0,0 +1,94 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Logging\Endpoints;
use Gravity_Forms\Gravity_SMTP\Apps\Config\Tools_Config;
use Gravity_Forms\Gravity_SMTP\Data_Store\Data_Store_Router;
use Gravity_Forms\Gravity_SMTP\Logging\Debug\Debug_Logger;
use Gravity_Forms\Gravity_SMTP\Models\Debug_Log_Model;
use Gravity_Forms\Gravity_SMTP\Users\Roles;
use Gravity_Forms\Gravity_Tools\Endpoints\Endpoint;
class View_Log_Endpoint extends Endpoint {
const PARAM_LOG_KEY = 'key';
const OPTION_VERIFICATION_KEY = 'gravitysmtp_log_verification_key';
const ACTION_NAME = 'view_debug_log';
protected $minimum_cap = Roles::VIEW_DEBUG_LOG;
/**
* @var Data_Store_Router
*/
protected $data;
/**
* @var Debug_Logger $debug_logger
*/
protected $debug_logger;
/**
* @var Debug_Log_Model $model
*/
protected $model;
public function __construct( Data_Store_Router $data, $debug_logger, $debug_model ) {
$this->data = $data;
$this->debug_logger = $debug_logger;
$this->model = $debug_model;
}
protected function get_nonce_name() {
return self::ACTION_NAME;
}
public function handle() {
if ( ! $this->validate() ) {
echo __( 'Unauthorized', 'gravitysmtp' );
die();
}
$lines = $this->debug_logger->get_log_items();
echo '<pre style="white-space: pre-wrap; word-wrap: break-word; overflow-wrap: break-word;">';
foreach ( $lines as $index => $item ) {
printf( "%s %s - %s --> %s", str_pad( '[' . $item->id() . ']', 8, ' ' ), $item->timestamp(), strtoupper( str_pad( $item->priority(), 7, ' ' ) ), esc_html( $item->line() ) );
if ( $index < count( $lines ) - 1 ) {
echo '</pre><hr><pre style="white-space: pre-wrap; word-wrap: break-word; overflow-wrap: break-word;">';
}
}
echo '</pre>';
die();
}
protected function validate() {
// Ensure logging is enabled.
$enabled = $this->data->get_plugin_setting( Tools_Config::SETTING_DEBUG_LOG_ENABLED, false );
if ( ! $enabled ) {
return false;
}
if ( is_user_logged_in() ) {
return current_user_can( Roles::VIEW_DEBUG_LOG );
}
// Get the passed verficiation key; bail if empty.
$key = filter_input( INPUT_GET, self::PARAM_LOG_KEY );
if ( empty( $key ) ) {
return false;
}
// Get the stored verification key; if it is empty or does not match the provided key, bail.
$key = htmlspecialchars( $key );
$check = get_option( self::OPTION_VERIFICATION_KEY );
if ( empty( $check ) || $check !== $key ) {
return false;
}
return true;
}
}
@@ -0,0 +1,23 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Logging\Log;
use Gravity_Forms\Gravity_SMTP\Models\Log_Details_Model;
class Logger {
/**
* @var Log_Details_Model
*/
protected $logs;
public function __construct( $logs ) {
$this->logs = $logs;
}
public function log( $email_id, $action_name, $log_value ) {
return $this->logs->create( $email_id, $action_name, $log_value );
}
}
@@ -0,0 +1,115 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Logging\Log;
use Gravity_Forms\Gravity_SMTP\Models\Event_Model;
use Gravity_Forms\Gravity_SMTP\Utils\Header_Parser;
use Gravity_Forms\Gravity_SMTP\Utils\Source_Parser;
class WP_Mail_Logger {
/**
* @var Logger
*/
protected $logger;
/**
* @var Event_Model
*/
protected $events;
/**
* @var Source_Parser
*/
protected $source_parser;
/**
* @var Header_Parser
*/
protected $header_parser;
public function __construct( $logger, $events, $source_parser, $header_parser ) {
$this->logger = $logger;
$this->events = $events;
$this->source_parser = $source_parser;
$this->header_parser = $header_parser;
}
public function create_log( $mail_info ) {
$source = $this->source_parser->get_source_from_trace( debug_backtrace() );
$test_mode = isset( $mail_info['test_mode'] ) ? $mail_info['test_mode'] : false;
if ( empty( $mail_info['headers'] ) ) {
$mail_info['headers'] = array();
} elseif ( ! is_array( $mail_info['headers'] ) ) {
$mail_info['headers'] = explode( "\n", str_replace( "\r\n", "\n", $mail_info['headers'] ) );
}
$from_header = isset( $mail_info['headers']['From'] ) ? $mail_info['headers']['From'] : '';
if ( empty( $from_header ) ) {
$from_header = isset( $mail_info['headers']['from'] ) ? $mail_info['headers']['from'] : '';
}
$from = '';
if ( ! empty( $from_header ) ) {
$froms = $this->header_parser->get_email_from_header( 'From', $from_header );
$from = $froms->first()->mailbox();
}
$email_id = $this->events->create(
'wp_mail',
'sent',
$mail_info['to'],
$from,
$mail_info['subject'],
$mail_info['message'],
array(
'headers' => $mail_info['headers'],
'attachments' => $mail_info['attachments'],
'source' => $source,
)
);
if ( $test_mode ) {
$this->log( $email_id, 'sandboxed', __( 'Email sandboxed.', 'gravitysmtp' ) );
$this->events->update( array( 'status' => 'sandboxed' ), $email_id );
} else {
$this->log( $email_id, 'sent', __( 'Email successfully sent.', 'gravitysmtp' ) );
}
}
public function handle_failed( $wp_error ) {
if ( ! is_wp_error( $wp_error ) ) {
return;
}
$error_data = $wp_error->get_error_data( 'wp_mail_failed' );
$error_message = $wp_error->get_error_message( 'wp_mail_failed' );
if ( ! isset( $error_data['subject'] ) ) {
return;
}
$params = array(
array( 'service', '=', 'wp_mail' ),
array( 'subject', '=', $error_data['subject'] ),
array( 'status', '=', 'sent' ),
);
$events = $this->events->find( $params );
if ( empty( $events[0] ) ) {
return;
}
$email_id = $events[0]['id'];
$this->events->update( array( 'status' => 'failed' ), $email_id );
$this->log( $email_id, 'failed', $error_message );
}
public function log( $email_id, $action_name, $log_value ) {
$this->logger->log( $email_id, $action_name, $log_value );
}
}
@@ -0,0 +1,116 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Logging\Scheduling;
use Gravity_Forms\Gravity_SMTP\Connectors\Endpoints\Save_Plugin_Settings_Endpoint;
use Gravity_Forms\Gravity_SMTP\Data_Store\Data_Store_Router;
use Gravity_Forms\Gravity_SMTP\Data_Store\Plugin_Opts_Data_Store;
use Gravity_Forms\Gravity_SMTP\Models\Event_Model;
use Gravity_Forms\Gravity_SMTP\Models\Log_Details_Model;
use Gravity_Forms\Gravity_SMTP\Utils\Booliesh;
class Handler {
/**
* @var Data_Store_Router
*/
protected $plugin_data;
/**
* @var Event_Model
*/
protected $emails;
/**
* @var Log_Details_Model
*/
protected $logs;
public function __construct( $plugin_data_store, $email_model, $log_model ) {
$this->plugin_data = $plugin_data_store;
$this->emails = $email_model;
$this->logs = $log_model;
}
/**
* Run the log retention functions. Currently called by a cron job.
*
* @since 1.0
*
* @return void
*/
public function run_log_retention() {
$retention = $this->plugin_data->get_plugin_setting( Save_Plugin_Settings_Endpoint::PARAM_EVENT_LOG_RETENTION, 0 );
$max_records = $this->plugin_data->get_plugin_setting( Save_Plugin_Settings_Endpoint::PARAM_MAX_EVENT_RECORDS, 0 );
// Retention is set to never delete, or we have a missing value, Bail.
if ( ! Booliesh::get( $retention ) && ! Booliesh::get( $max_records ) ) {
return;
}
$to_delete = $this->get_items_to_delete( $retention, $max_records );
// No items to delete, bail.
if ( empty( $to_delete ) ) {
return;
}
$this->delete_expired_items( $to_delete );
}
/**
* Get the items to delete by the retention date.j
*
* @since 1.0
*
* @param int $retention
*
* @return array
*/
private function get_items_to_delete( $retention, $max_records ) {
if ( Booliesh::get( $max_records ) ) {
$items = $this->emails->get_records_over_limit( $max_records );
} else {
$interval_string = sprintf( ' - %d days', $retention );
$newDate = gmdate( 'Y-m-d H:i:s', strtotime( $interval_string ) );
$params = array(
array(
'date_created',
'<=',
$newDate
)
);
$items = $this->emails->find( $params );
}
$ids = wp_list_pluck( $items, 'id' );
return $ids;
}
/**
* Delete expired items by id.
*
* @since 1.0
*
* @param array $items
*
* @return true|\WP_Error
*/
private function delete_expired_items( $items ) {
try {
foreach ( $items as $id ) {
$this->emails->delete( $id );
$this->logs->delete_by_event_id( $id );
}
return true;
} catch ( \Exception $e ) {
return new \WP_Error( 'delete_failed', $e->getMessage() );
}
}
}