Commit inicial - WordPress Análisis de Precios Unitarios

- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,150 @@
<?php
namespace FluentMail\App\Hooks\Handlers;
use FluentMail\Includes\Core\Application;
use FluentMail\App\Hooks\Handlers\AdminMenuHandler;
use FluentMail\App\Hooks\Handlers\SchedulerHandler;
use FluentMail\App\Hooks\Handlers\InitializeSiteHandler;
use WP_REST_Request;
class ActionsRegistrar
{
/**
* Application instance.
*
* @var Application
*/
protected $app;
/**
* Constructor.
*
* @param Application $app
*/
public function __construct(Application $app)
{
$this->app = $app;
}
/**
* Alternative static constructor.
*
* @param Application $app
* @return static
*/
public static function init(Application $app)
{
$instance = new static($app);
$instance->registerHooks();
return $instance;
}
/**
* Register all core hooks and REST routes.
*
* @return void
*/
public function registerHooks()
{
$this->registerAdminMenu();
$this->registerScheduler();
$this->registerSiteInitialization();
$this->registerCustomActions();
$this->registerRestRoutes();
}
/**
* Register admin menu and notices.
*
* @return void
*/
protected function registerAdminMenu()
{
$adminMenuHandler = new AdminMenuHandler($this->app);
$adminMenuHandler->addFluentMailMenu();
$this->app->addAction('admin_notices', 'AdminMenuHandler@maybeAdminNotice');
}
/**
* Register background scheduler hooks.
*
* @return void
*/
protected function registerScheduler()
{
(new SchedulerHandler)->register();
}
/**
* Register site-level initialization logic.
*
* @return void
*/
protected function registerSiteInitialization()
{
(new InitializeSiteHandler)->addHandler();
}
/**
* Register custom application actions.
*
* @return void
*/
protected function registerCustomActions()
{
$this->app->addCustomAction(
'handle_exception', 'ExceptionHandler@handle'
);
}
/**
* Register REST API routes.
*
* @return void
*/
protected function registerRestRoutes()
{
$this->app->addAction('rest_api_init', function () {
register_rest_route('fluent-smtp', '/outlook_callback/', [
'methods' => 'GET',
'callback' => [$this, 'handleOutlookCallback'],
'permission_callback' => [$this, 'verifyOutlookCallbackState'],
]);
});
}
/**
* Handle the Outlook OAuth callback.
*
* @param WP_REST_Request $request
* @return void
*/
public function handleOutlookCallback(WP_REST_Request $request)
{
$code = $request->get_param('code');
$output = $this->app->view->make('admin.html_code', [
'title' => 'Your Access Code',
'body' => sprintf(
'<p>Copy the following code and paste in the fluentSMTP settings</p><textarea readonly>%s</textarea>',
sanitize_textarea_field($code)
),
]);
wp_die($output, 'Access Code');
}
/**
* Verify the 'state' parameter in the OAuth callback.
*
* @return bool
*/
public function verifyOutlookCallbackState()
{
$state = $_REQUEST['state'] ?? null;
return $state === get_option('_fluentmail_last_generated_state');
}
}

View File

@@ -0,0 +1,457 @@
<?php
namespace FluentMail\App\Hooks\Handlers;
use FluentMail\App\Models\Logger;
use FluentMail\App\Models\Settings;
use FluentMail\App\Services\Converter;
use FluentMail\Includes\Core\Application;
use FluentMail\App\Services\Mailer\Manager;
use FluentMail\Includes\Support\Arr;
use FluentMail\App\Services\TransStrings;
class AdminMenuHandler
{
protected $app = null;
public function __construct(Application $application)
{
$this->app = $application;
}
public function addFluentMailMenu()
{
add_action('admin_menu', array($this, 'addMenu'));
if (isset($_GET['page']) && $_GET['page'] == 'fluent-mail' && is_admin()) {
add_action('admin_enqueue_scripts', array($this, 'enqueueAssets'));
if (isset($_REQUEST['sub_action']) && $_REQUEST['sub_action'] == 'slack_success') {
add_action('admin_init', function () {
$nonce = Arr::get($_REQUEST, '_slacK_nonce');
if (!wp_verify_nonce($nonce, 'fluent_smtp_slack_register_site')) {
wp_redirect(admin_url('options-general.php?page=fluent-mail&slack_security_failed=1#/notification-settings'));
die();
}
$settings = (new Settings())->notificationSettings();
$token = Arr::get($_REQUEST, 'site_token');
if ($token && $token == Arr::get($settings, 'slack.token')) {
$settings['slack'] = [
'status' => 'yes',
'token' => sanitize_text_field($token),
'slack_team' => sanitize_text_field(Arr::get($_REQUEST, 'slack_team')),
'webhook_url' => sanitize_url(Arr::get($_REQUEST, 'slack_webhook'))
];
$settings['active_channel'] = 'slack';
update_option('_fluent_smtp_notify_settings', $settings);
}
wp_redirect(admin_url('options-general.php?page=fluent-mail#/notification-settings'));
die();
});
}
}
add_action('admin_bar_menu', array($this, 'addSimulationBar'), 999);
add_action('admin_init', array($this, 'initAdminWidget'));
add_action('install_plugins_table_header', function () {
if (!isset($_REQUEST['s']) || empty($_REQUEST['s']) || empty($_REQUEST['tab']) || $_REQUEST['tab'] != 'search') {
return;
}
$search = str_replace(['%20', '_', '-'], ' ', $_REQUEST['s']);
$search = trim(strtolower(sanitize_text_field($search)));
$searchTerms = ['wp-mail-smtp', 'wp mail', 'wp mail smtp', 'post mailer', 'wp smtp', 'smtp mail', 'smtp', 'post smtp', 'easy smtp', 'easy wp smtp', 'smtp mailer', 'gmail smtp', 'offload ses'];
if (!strpos($search, 'smtp')) {
if (!in_array($search, $searchTerms)) {
return;
}
}
?>
<div
style="background-color: #fff;border: 1px solid #dcdcde;box-sizing: border-box;padding: 20px;margin: 15px 0;"
class="fluent_smtp_box">
<h3 style="margin: 0;"><?php __('For SMTP, you already have FluentSMTP Installed', 'fluent-smtp'); ?></h3>
<p><?php __('You seem to be looking for an SMTP plugin, but there\'s no need for another one — FluentSMTP is already installed on your site. FluentSMTP is a comprehensive, free, and open-source plugin with full features available without any upsell', 'fluent-smtp'); ?>
(<a href="https://fluentsmtp.com/why-we-built-fluentsmtp-plugin/"><?php __('learn why it\'s free', 'fluent-smtp'); ?></a>)<?php __('. It\'s compatible with various SMTP services, including Amazon SES, SendGrid, MailGun, ElasticEmail, SendInBlue, Google, Microsoft, and others, providing you with a wide range of options for your email needs.', 'fluent-smtp'); ?>
</p><a href="<?php echo esc_url(admin_url('options-general.php?page=fluent-mail#/')); ?>"
class="wp-core-ui button button-primary"><?php __('Go To FluentSMTP Settings', 'fluent-smtp'); ?></a>
<p style="font-size: 80%; margin: 15px 0 0;"><?php __('This notice is from FluentSMTP plugin to prevent plugin
conflict.', 'fluent-smtp') ?></p>
</div>
<?php
}, 1);
add_action('wp_ajax_fluent_smtp_get_dashboard_html', function () {
// This widget should be displayed for certain high-level users only.
if (!current_user_can('manage_options') || apply_filters('fluent_mail_disable_dashboard_widget', false)) {
wp_send_json([
'html' => __('You do not have permission to see this data', 'fluent-smtp')
]);
}
wp_send_json([
'html' => $this->getDashboardWidgetHtml()
]);
});
}
public function addMenu()
{
$title = $this->app->applyCustomFilters('admin-menu-title', __('FluentSMTP', 'fluent-smtp'));
add_submenu_page(
'options-general.php',
$title,
$title,
'manage_options',
'fluent-mail',
[$this, 'renderApp'],
16
);
}
public function renderApp()
{
$dailyTaskHookName = 'fluentmail_do_daily_scheduled_tasks';
if (!wp_next_scheduled($dailyTaskHookName)) {
wp_schedule_event(time(), 'daily', $dailyTaskHookName);
}
$this->app->view->render('admin.menu');
}
public function enqueueAssets()
{
add_action('wp_print_scripts', function () {
$isSkip = apply_filters('fluentsmtp_skip_no_conflict', false);
if ($isSkip) {
return;
}
global $wp_scripts;
if (!$wp_scripts) {
return;
}
$themeUrl = content_url('themes');
$pluginUrl = plugins_url();
foreach ($wp_scripts->queue as $script) {
if (empty($wp_scripts->registered[$script]) || empty($wp_scripts->registered[$script]->src)) {
continue;
}
$src = $wp_scripts->registered[$script]->src;
$isMatched = strpos($src, $pluginUrl) !== false && !strpos($src, 'fluent-smtp') !== false;
if (!$isMatched) {
continue;
}
$isMatched = strpos($src, $themeUrl) !== false;
if ($isMatched) {
wp_dequeue_script($wp_scripts->registered[$script]->handle);
}
}
}, 1);
wp_enqueue_script(
'fluent_mail_admin_app_boot',
fluentMailMix('admin/js/boot.js'),
['jquery'],
FLUENTMAIL_PLUGIN_VERSION
);
wp_enqueue_script('fluentmail-chartjs', fluentMailMix('libs/chartjs/Chart.min.js'), [], FLUENTMAIL_PLUGIN_VERSION);
wp_enqueue_script('fluentmail-vue-chartjs', fluentMailMix('libs/chartjs/vue-chartjs.min.js'), [], FLUENTMAIL_PLUGIN_VERSION);
wp_enqueue_script('dompurify', fluentMailMix('libs/purify/purify.min.js'), [], '2.4.3');
wp_enqueue_style(
'fluent_mail_admin_app', fluentMailMix('admin/css/fluent-mail-admin.css'), [], FLUENTMAIL_PLUGIN_VERSION
);
$user = get_user_by('ID', get_current_user_id());
$disable_recommendation = defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS;
$settings = $this->getMailerSettings();
$recommendedSettings = false;
if (empty($settings['connections'])) {
$recommendedSettings = (new Converter())->getSuggestedConnection();
}
$displayName = trim($user->first_name . ' ' . $user->last_name);
if (!$displayName) {
$displayName = $user->display_name;
}
wp_localize_script('fluent_mail_admin_app_boot', 'FluentMailAdmin', [
'slug' => FLUENTMAIL,
'brand_logo' => esc_url(fluentMailMix('images/logo.svg')),
'nonce' => wp_create_nonce(FLUENTMAIL),
'settings' => $settings,
'images_url' => esc_url(fluentMailMix('images/')),
'has_fluentcrm' => defined('FLUENTCRM'),
'has_fluentform' => defined('FLUENTFORM'),
'user_email' => $user->user_email,
'user_display_name' => $displayName,
'require_optin' => $this->isRequireOptin(),
'has_ninja_tables' => defined('NINJA_TABLES_VERSION'),
'disable_recommendation' => apply_filters('fluentmail_disable_recommendation', false),
'disable_installation' => $disable_recommendation,
'plugin_url' => 'https://fluentsmtp.com/?utm_source=wp&utm_medium=install&utm_campaign=dashboard',
'trans' => $this->getTrans(),
'recommended' => $recommendedSettings,
'is_disabled_defined' => defined('FLUENTMAIL_SIMULATE_EMAILS') && FLUENTMAIL_SIMULATE_EMAILS
]);
do_action('fluent_mail_loading_app');
wp_enqueue_script(
'fluent_mail_admin_app',
fluentMailMix('admin/js/fluent-mail-admin-app.js'),
['fluent_mail_admin_app_boot'],
FLUENTMAIL_PLUGIN_VERSION,
true
);
add_filter('admin_footer_text', function ($text) {
return sprintf(
__('%1$s is a free plugin & it will be always free %2$s. %3$s', 'fluent-smtp'),
'<b>FluentSMTP</b>',
'<a href="https://fluentsmtp.com/why-we-built-fluentsmtp-plugin/" target="_blank" rel="noopener noreferrer">'. esc_html__('(Learn why it\'s free)', 'fluent-smtp') .'</a>',
'<a href="https://wordpress.org/support/plugin/fluent-smtp/reviews/?filter=5" target="_blank" rel="noopener noreferrer">'. esc_html__('Write a review ★★★★★', 'fluent-smtp') .'</a>'
);
});
}
protected function getMailerSettings()
{
$settings = $this->app->make(Manager::class)->getMailerConfigAndSettings(true);
if ($settings['mappings'] && $settings['connections']) {
$validMappings = array_keys(Arr::get($settings, 'connections', []));
$settings['mappings'] = array_filter($settings['mappings'], function ($key) use ($validMappings) {
return in_array($key, $validMappings);
});
}
$settings['providers']['outlook']['callback_url'] = rest_url('fluent-smtp/outlook_callback');
$settings = array_merge(
$settings,
[
'user_email' => wp_get_current_user()->user_email
]
);
return $settings;
}
public function maybeAdminNotice()
{
if (!current_user_can('manage_options')) {
return;
}
$connections = $this->app->make(Manager::class)->getConfig('connections');
global $wp_version;
$requireUpdate = version_compare($wp_version, '5.5', '<');
if ($requireUpdate) { ?>
<div class="notice notice-warning">
<p>
<?php echo esc_html(sprintf(__('WordPress version 5.5 or greater is required for FluentSMTP. You are using version %s currently. Please update your WordPress Core to use FluentSMTP Plugin.', 'fluent-smtp'), $wp_version)); ?>
</p>
</div>
<?php } else if (empty($connections)) {
?>
<div class="notice notice-warning">
<p>
<?php esc_html_e('FluentSMTP needs to be configured for it to work.', 'fluent-smtp'); ?>
</p>
<p>
<a href="<?php echo esc_url(admin_url('options-general.php?page=fluent-mail#/')); ?>"
class="button button-primary">
<?php esc_html_e('Configure FluentSMTP', 'fluent-smtp'); ?>
</a>
</p>
</div>
<?php
}
}
public function addSimulationBar($adminBar)
{
if (!current_user_can('manage_options')) {
return;
}
$misc = $this->app->make(Manager::class)->getConfig('misc');
if ((!empty($misc['simulate_emails']) && $misc['simulate_emails'] == 'yes') || (defined('FLUENTMAIL_SIMULATE_EMAILS') && FLUENTMAIL_SIMULATE_EMAILS)) {
$args = [
'parent' => 'top-secondary',
'id' => 'fluentsmtp_simulated',
'title' => __('Email Disabled', 'fluent-smtp'),
'href' => admin_url('options-general.php?page=fluent-mail#/connections'),
'meta' => false
];
echo '<style>li#wp-admin-bar-fluentsmtp_simulated a {background: red; color: white;}</style>';
$adminBar->add_node($args);
}
}
public function isRequireOptin()
{
$opted = get_option('_fluentsmtp_sub_update');
if ($opted) {
return 'no';
}
// check if dismissed
$dismissedStamp = get_option('_fluentsmtp_dismissed_timestamp');
if ($dismissedStamp && (time() - $dismissedStamp) < 30 * 24 * 60 * 60) {
return 'no';
}
return 'yes';
}
public function initAdminWidget()
{
// This widget should be displayed for certain high-level users only.
if (!current_user_can('manage_options') || apply_filters('fluent_mail_disable_dashboard_widget', false)) {
return;
}
add_action('wp_dashboard_setup', function () {
$widget_key = 'fluentsmtp_reports_widget';
wp_add_dashboard_widget(
$widget_key,
esc_html__('Fluent SMTP', 'fluent-smtp'),
[$this, 'dashWidgetContent']
);
});
}
public function dashWidgetContent()
{
?>
<style type="text/css">
td.fstmp_failed {
color: red;
font-weight: bold;
}
</style>
<div id="fsmtp_dashboard_widget_html" class="fsmtp_dash_wrapper">
<h3 style="min-height: 170px;"><?php esc_html_e('Loading data...', 'fluent-smtp'); ?></h3>
</div>
<?php
add_action('admin_footer', function () {
?>
<script type="application/javascript">
document.addEventListener('DOMContentLoaded', function () {
// send an ajax request to ajax url with raw javascript
var xhr = new XMLHttpRequest();
xhr.open('POST', '<?php echo esc_url(admin_url('admin-ajax.php?action=fluent_smtp_get_dashboard_html')); ?>', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var response = JSON.parse(xhr.responseText);
if (response && response.html) {
document.getElementById('fsmtp_dashboard_widget_html').innerHTML = response.html;
} else {
document.getElementById('fsmtp_dashboard_widget_html').innerHTML = '<h3>Failed to load FluentSMTP Reports</h3>';
}
}
};
xhr.send();
});
</script>
<?php
});
}
protected function getDashboardWidgetHtml()
{
$stats = [];
$logModel = new Logger();
$currentTimeStamp = current_time('timestamp');
$startToday = gmdate('Y-m-d 00:00:01', $currentTimeStamp);
$allTime = $logModel->getStats();
$stats['today'] = [
'title' => __('Today', 'fluent-smtp'),
'sent' => ($allTime['sent']) ? $logModel->getTotalCountStat('sent', $startToday) : 0,
'failed' => ($allTime['failed']) ? $logModel->getTotalCountStat('failed', $startToday) : 0
];
$lastWeek = gmdate('Y-m-d 00:00:01', strtotime('-7 days'));
$stats['week'] = [
'title' => __('Last 7 days', 'fluent-smtp'),
'sent' => ($allTime['sent']) ? $logModel->getTotalCountStat('sent', $lastWeek) : 0,
'failed' => ($allTime['failed']) ? $logModel->getTotalCountStat('failed', $lastWeek) : 0,
];
$stats['all_time'] = [
'title' => __('All', 'fluent-smtp'),
'sent' => $allTime['sent'],
'failed' => $allTime['failed'],
];
ob_start();
?>
<table class="fsmtp_dash_table wp-list-table widefat fixed striped">
<thead>
<tr>
<th><?php esc_html_e('Date', 'fluent-smtp'); ?></th>
<th><?php esc_html_e('Sent', 'fluent-smtp'); ?></th>
<th><?php esc_html_e('Failed', 'fluent-smtp'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($stats as $stat): ?>
<tr>
<td><?php echo $stat['title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></td>
<td><?php echo $stat['sent']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></td>
<td class="<?php echo ($stat['failed']) ? 'fstmp_failed' : ''; ?>"><?php echo $stat['failed']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<a style="text-decoration: none; padding-top: 10px; display: block"
href="<?php echo esc_url(admin_url('options-general.php?page=fluent-mail#/')); ?>"
class=""><?php esc_html_e('View All', 'fluent-smtp'); ?></a>
<?php
return ob_get_clean();
}
public function getTrans()
{
return TransStrings::getStrings();
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace FluentMail\App\Hooks\Handlers;
class ExceptionHandler
{
protected $handlers = [
'FluentMail\Includes\Support\ForbiddenException' => 'handleForbiddenException',
'FluentMail\Includes\Support\ValidationException' => 'handleValidationException'
];
public function handle($e)
{
foreach ($this->handlers as $key => $value) {
if ($e instanceof $key) {
return $this->{$value}($e);
}
}
}
public function handleForbiddenException($e)
{
wp_send_json_error([
'message' => $e->getMessage()
], $e->getCode() ?: 403);
}
public function handleValidationException($e)
{
wp_send_json_error([
'message' => $e->getMessage(),
'errors' => $e->errors()
], $e->getCode() ?: 422);
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace FluentMail\App\Hooks\Handlers;
class InitializeSiteHandler
{
public function addHandler()
{
add_action('wp_initialize_site', array($this, 'handle'));
}
public static function handle( $new_site )
{
require_once(FLUENTMAIL_PLUGIN_PATH . 'database/migrations/EmailLogs.php');
$blog_id = $new_site->blog_id;
switch_to_blog((int)$blog_id);
\FluentMailMigrations\EmailLogs::migrate();
restore_current_blog();
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace FluentMail\App\Hooks\Handlers;
class ProviderValidator
{
public function handle($provider, $errors = [])
{
if ($validator = $this->getProviderValidator($provider, $errors)) {
return $validator->validate();
}
return $errors;
}
protected function getProviderValidator($provider, $errors)
{
$key = $provider['provider'];
$path = FluentMail('path.app') . 'Services/Mailer/Providers/' . $key;
$file = $path . '/' . 'Validator.php';
if (file_exists($file)) {
$ns = 'FluentMail\App\Services\Mailer\Providers\\' . $key;
$class = $ns . '\Validator';
if (class_exists($class)) {
return new $class($provider, $errors);
}
}
}
}

View File

@@ -0,0 +1,338 @@
<?php
namespace FluentMail\App\Hooks\Handlers;
use FluentMail\App\Models\Logger;
use FluentMail\App\Models\Settings;
use FluentMail\App\Services\NotificationHelper;
use FluentMail\Includes\Support\Arr;
class SchedulerHandler
{
protected $dailyActionName = 'fluentmail_do_daily_scheduled_tasks';
public function register()
{
add_action($this->dailyActionName, array($this, 'handleScheduledJobs'));
add_filter('fluentmail_email_sending_failed', array($this, 'maybeHandleFallbackConnection'), 10, 4);
add_action('fluentsmtp_renew_gmail_token', array($this, 'renewGmailToken'));
add_action('fluentmail_email_sending_failed_no_fallback', array($this, 'maybeSendNotification'), 10, 3);
}
public function handleScheduledJobs()
{
$this->deleteOldEmails();
$this->sendDailyDigest();
}
private function deleteOldEmails()
{
$settings = fluentMailGetSettings();
$logSaveDays = intval(Arr::get($settings, 'misc.log_saved_interval_days'));
if ($logSaveDays) {
(new \FluentMail\App\Models\Logger())->deleteLogsOlderThan($logSaveDays);
}
}
public function sendDailyDigest()
{
$settings = (new Settings())->notificationSettings();
if ($settings['enabled'] != 'yes' || empty($settings['notify_days']) || empty($settings['notify_email'])) {
return;
}
$currentDay = gmdate('D');
if (!in_array($currentDay, $settings['notify_days'])) {
return;
}
$sendTo = $settings['notify_email'];
$sendTo = str_replace(['{site_admin}', '{admin_email}'], get_option('admin_email'), $sendTo);
$sendToArray = explode(',', $sendTo);
$sendToArray = array_filter($sendToArray, function ($email) {
return is_email($email);
});
if (!$sendToArray) {
return false;
}
// we can send a summary email
$lastDigestSent = get_option('_fluentmail_last_email_digest');
if ($lastDigestSent) {
if ((time() - strtotime($lastDigestSent)) < 72000) {
return false; // we don't want to send another email if sent time within 20 hours
}
} else {
$lastDigestSent = gmdate('Y-m-d', strtotime('-7 days'));
}
// Let's create the stats
$startDate = gmdate('Y-m-d 00:00:01', (strtotime($lastDigestSent) - 86400));
$endDate = gmdate('Y-m-d 23:59:59', strtotime('-1 days'));
$reportingDays = floor((strtotime($endDate) - strtotime($startDate)) / 86400);
$loggerModel = new Logger();
$sentCount = $loggerModel->getTotalCountStat('sent', $startDate, $endDate);
$sentStats = [
'total' => $sentCount,
'subjects' => [],
'unique_subjects' => 0
];
if ($sentCount) {
$sentStats['unique_subjects'] = $loggerModel->getSubjectCountStat('sent', $startDate, $endDate);
$sentStats['subjects'] = $loggerModel->getSubjectStat('sent', $startDate, $endDate, 10);
}
$failedCount = $loggerModel->getTotalCountStat('failed', $startDate, $endDate);
$failedStats = [
'total' => $sentCount,
'subjects' => [],
'unique_subjects' => 0
];
if ($failedCount) {
$failedStats['unique_subjects'] = $loggerModel->getSubjectCountStat('failed', $startDate, $endDate);
$failedStats['subjects'] = $loggerModel->getSubjectStat('failed', $startDate, $endDate);
}
$sentSubTitle = sprintf(
__('Showing %1$s of %2$s different subject lines sent in the past %3$s', 'fluent-smtp'),
number_format_i18n(count($sentStats['subjects'])),
number_format_i18n($sentStats['unique_subjects']),
($reportingDays < 2) ? 'day' : $reportingDays . ' days'
);
$failedSubTitle = sprintf(
__('Showing %1$s of %2$s different subject lines failed in the past %3$s', 'fluent-smtp'),
number_format_i18n(count($failedStats['subjects'])),
number_format_i18n($failedStats['unique_subjects']),
($reportingDays < 2) ? 'day' : $reportingDays . ' days'
);
$sentTitle = __('Emails Sent', 'fluent-smtp');
if ($sentCount) {
$sentTitle .= ' <span style="font-size: 12px; vertical-align: middle;">(' . number_format_i18n($sentCount) . ')</span>';
}
$failedTitle = __('Email Failures', 'fluent-smtp');
if ($failedCount) {
$failedTitle .= ' <span style="font-size: 12px; vertical-align: middle;">(' . number_format_i18n($failedCount) . ')</span>';
}
$reportingDate = gmdate(get_option('date_format'), strtotime($startDate));
$data = [
'sent' => [
'total' => $sentCount,
'title' => $sentTitle,
'subtitle' => $sentSubTitle,
'subject_items' => $sentStats['subjects']
],
'fail' => [
'total' => $failedCount,
'title' => $failedTitle,
'subtitle' => $failedSubTitle,
'subject_items' => $failedStats['subjects']
],
'date_range' => $reportingDate,
'domain_name' => $this->getDomainName()
];
$emailBody = (string)fluentMail('view')->make('admin.digest_email', $data);
$emailSubject = $reportingDate . ' email sending stats for ' . $this->getDomainName();
$headers = array('Content-Type: text/html; charset=UTF-8');
update_option('_fluentmail_last_email_digest', gmdate('Y-m-d H:i:s'));
return wp_mail($sendToArray, $emailSubject, $emailBody, $headers);
}
private function getDomainName()
{
$parts = parse_url(site_url());
$url = $parts['host'] . (isset($parts['path']) ? $parts['path'] : '');
return untrailingslashit($url);
}
public function maybeHandleFallbackConnection($status, $logId, $handler, $data = [])
{
if (defined('FLUENTMAIL_EMAIL_TESTING')) {
return false;
}
$settings = (new \FluentMail\App\Models\Settings())->getSettings();
$fallbackConnectionId = \FluentMail\Includes\Support\Arr::get($settings, 'misc.fallback_connection');
if (!$fallbackConnectionId) {
do_action('fluentmail_email_sending_failed_no_fallback', $logId, $handler, $data);
return false;
}
$fallbackConnection = \FluentMail\Includes\Support\Arr::get($settings, 'connections.' . $fallbackConnectionId);
if (!$fallbackConnection) {
do_action('fluentmail_email_sending_failed_no_fallback', $logId, $handler, $data);
return false;
}
$phpMailer = $handler->getPhpMailer();
$fallbackSettings = $fallbackConnection['provider_settings'];
$phpMailer->setFrom($fallbackSettings['sender_email'], $phpMailer->FromName);
// Trap the fluentSMTPMail mailer here
$phpMailer = new \FluentMail\App\Services\Mailer\FluentPHPMailer($phpMailer);
return $phpMailer->sendViaFallback($logId);
}
public function renewGmailToken()
{
$settings = fluentMailGetSettings();
if (!$settings) {
return;
}
$connections = Arr::get($settings, 'connections', []);
foreach ($connections as $connection) {
if (Arr::get($connection, 'provider_settings.provider') != 'gmail') {
continue;
}
$providerSettings = $connection['provider_settings'];
if (($providerSettings['expire_stamp'] - 480) < time() && !empty($providerSettings['refresh_token'])) {
$this->callGmailApiForNewToken($connection['provider_settings']);
}
}
}
public function callGmailApiForNewToken($settings)
{
if (Arr::get($settings, 'key_store') == 'wp_config') {
$settings['client_id'] = defined('FLUENTMAIL_GMAIL_CLIENT_ID') ? FLUENTMAIL_GMAIL_CLIENT_ID : '';
$settings['client_secret'] = defined('FLUENTMAIL_GMAIL_CLIENT_SECRET') ? FLUENTMAIL_GMAIL_CLIENT_SECRET : '';
}
if (!class_exists('\FluentSmtpLib\Google\Client')) {
require_once FLUENTMAIL_PLUGIN_PATH . 'includes/libs/google-api-client/build/vendor/autoload.php';
}
try {
$client = new \FluentSmtpLib\Google\Client();
$client->setClientId($settings['client_id']);
$client->setClientSecret($settings['client_secret']);
$client->addScope("https://www.googleapis.com/auth/gmail.compose");
$client->setAccessType('offline');
$client->setApprovalPrompt('force');
$tokens = [
'access_token' => $settings['access_token'],
'refresh_token' => $settings['refresh_token'],
'expires_in' => $settings['expire_stamp'] - time()
];
$client->setAccessToken($tokens);
$newTokens = $client->refreshToken($tokens['refresh_token']);
$result = $this->saveNewGmailTokens($settings, $newTokens);
if (!$result) {
return new \WP_Error('api_error', __('Failed to renew the token', 'fluent-smtp'));
}
return true;
} catch (\Exception $exception) {
return new \WP_Error('api_error', $exception->getMessage());
}
}
public function maybeSendNotification($rowId, $handler, $logData = [])
{
$channel = NotificationHelper::getActiveChannelSettings();
if (!$channel) {
return false;
}
$lastNotificationSent = get_option('_fsmtp_last_notification_sent');
if ($lastNotificationSent && (time() - $lastNotificationSent) < 60) {
return false;
}
update_option('_fsmtp_last_notification_sent', time());
$driver = $channel['driver'];
if ($driver == 'telegram') {
$data = [
'token_id' => $channel['token'],
'provider' => $handler->getSetting('provider'),
'error_message' => $this->getErrorMessageFromResponse(maybe_unserialize(Arr::get($logData, 'response')))
];
return NotificationHelper::sendFailedNotificationTele($data);
}
if ($driver == 'slack') {
return NotificationHelper::sendSlackMessage(NotificationHelper::formatSlackMessageBlock($handler, $logData), $channel['webhook_url'], false);
}
if ($driver == 'discord') {
return NotificationHelper::sendDiscordMessage(NotificationHelper::formatDiscordMessageBlock($handler, $logData), $channel['webhook_url'], false);
}
return false;
}
private function saveNewGmailTokens($existingData, $tokens)
{
if (empty($tokens['access_token']) || empty($tokens['refresh_token'])) {
return false;
}
$senderEmail = $existingData['sender_email'];
$existingData['access_token'] = $tokens['access_token'];
$existingData['refresh_token'] = $tokens['refresh_token'];
$existingData['expire_stamp'] = $tokens['expires_in'] + time();
$existingData['expires_in'] = $tokens['expires_in'];
(new Settings())->updateConnection($senderEmail, $existingData);
fluentMailGetProvider($senderEmail, true); // we are clearing the static cache here
wp_schedule_single_event($existingData['expire_stamp'] - 360, 'fluentsmtp_renew_gmail_token');
return true;
}
private function getErrorMessageFromResponse($response)
{
if (!$response || !is_array($response)) {
return '';
}
if (!empty($response['fallback_response']['message'])) {
$message = $response['fallback_response']['message'];
} else {
$message = Arr::get($response, 'message');
}
if (!$message) {
return '';
}
if (!is_string($message)) {
$message = json_encode($message);
}
return $message;
}
}