plugin = $plugin;
add_action('advaipbl_send_summary_email', [$this, 'send_summary_email']);
add_action('advaipbl_send_signature_summary_email', [$this, 'send_signature_summary_email']);
add_action('advaipbl_abuseipdb_limit_email', [$this, 'send_abuseipdb_limit_email']);
}
/**
* Processes and sends the daily/weekly security summary email.
*/
/**
* Processes and sends the daily/weekly security summary email (Standard Blocks).
*/
public function send_summary_email()
{
global $wpdb;
$table_name = $wpdb->prefix . 'advaipbl_notifications_queue';
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
$notifications = $wpdb->get_results("SELECT * FROM $table_name WHERE block_type != 'signature' ORDER BY timestamp ASC");
if (empty($notifications)) {
return;
}
$options = $this->plugin->options;
$to = !empty($options['notification_email']) && is_email($options['notification_email']) ? $options['notification_email'] : get_option('admin_email');
$this->send_grouped_summary_email($notifications, $to, 'standard');
$ids = array_map(function ($n) {
return (int) $n->id;
}, $notifications);
if (!empty($ids)) {
$ids_placeholder = implode(',', $ids);
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
$wpdb->query("DELETE FROM $table_name WHERE id IN ($ids_placeholder)");
}
}
/**
* Processes and sends the daily/weekly security summary email (Signatures).
*/
public function send_signature_summary_email()
{
global $wpdb;
$table_name = $wpdb->prefix . 'advaipbl_notifications_queue';
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
$notifications = $wpdb->get_results("SELECT * FROM $table_name WHERE block_type = 'signature' ORDER BY timestamp ASC");
if (empty($notifications)) {
return;
}
$options = $this->plugin->options;
$recipient_type = $options['signature_notification_recipient'] ?? 'default';
$to = get_option('admin_email');
if ($recipient_type === 'default') {
$to = !empty($options['notification_email']) ? $options['notification_email'] : get_option('admin_email');
} elseif ($recipient_type === 'custom') {
$to = !empty($options['signature_notification_custom_email']) ? $options['signature_notification_custom_email'] : get_option('admin_email');
}
if (!is_email($to)) {
$to = get_option('admin_email');
}
$this->send_grouped_summary_email($notifications, $to, 'signature');
$ids = array_map(function ($n) {
return (int) $n->id;
}, $notifications);
if (!empty($ids)) {
$ids_placeholder = implode(',', $ids);
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
$wpdb->query("DELETE FROM $table_name WHERE id IN ($ids_placeholder)");
}
}
/**
* Helper to send a grouped summary email.
*/
private function send_grouped_summary_email($notifications, $to, $type)
{
$site_name = get_bloginfo('name');
$total_blocks = count($notifications);
if ($type === 'signature') {
/* translators: %s is a placeholder */
$email_subject = sprintf(__('[%1$s] Security Digest: %2$d Attack Signatures', 'advanced-ip-blocker'), $site_name, $total_blocks);
/* translators: %s is a placeholder */
$template_title = sprintf(__('Attack Signature Digest (%d)', 'advanced-ip-blocker'), $total_blocks);
$intro_text = esc_html__('Here is the summary of attack signatures detected and blocked in the last period.', 'advanced-ip-blocker');
} else {
/* translators: %s is a placeholder */
$email_subject = sprintf(__('[%1$s] Security Summary: %2$d New Blocks', 'advanced-ip-blocker'), $site_name, $total_blocks);
/* translators: %s is a placeholder */
$template_title = sprintf(_n('%d New Block', '%d New Blocks', $total_blocks, 'advanced-ip-blocker'), $total_blocks);
$intro_text = esc_html__('Here is your security summary for the last period.', 'advanced-ip-blocker');
}
$blocks_by_type = [];
foreach ($notifications as $notification) {
$blocks_by_type[$notification->block_type][] = $notification;
}
$summary_html = '
' . $intro_text . '
';
$summary_html .= '' . esc_html__('Summary by Block Type', 'advanced-ip-blocker') . '
';
foreach ($blocks_by_type as $block_type => $blocks) {
$type_capitalized = ucfirst($block_type);
$block_count = count($blocks);
/* translators: %s is a placeholder */
$summary_html .= '- ' . esc_html($type_capitalized) . ': ' . sprintf(esc_html(_n('%d item', '%d items', $block_count, 'advanced-ip-blocker')), $block_count) . '
';
}
$summary_html .= '
';
$summary_html .= '' . esc_html__('Recent Details', 'advanced-ip-blocker') . '
';
$col_1 = ($type === 'signature') ? esc_html__('Hash', 'advanced-ip-blocker') : esc_html__('Blocked IP', 'advanced-ip-blocker');
$summary_html .= '' .
'| ' . esc_html__('Time', 'advanced-ip-blocker') . ' | ' .
'' . $col_1 . ' | ' .
'' . esc_html__('Reason', 'advanced-ip-blocker') . ' | ' .
'
';
$details_limit = 20;
$limited_notifications = array_slice($notifications, -$details_limit);
foreach ($limited_notifications as $notification) {
$formatted_time = date_i18n(get_option('date_format') . ' ' . get_option('time_format'), strtotime($notification->timestamp));
$col_1_val = $notification->ip;
if ($type === 'signature') {
$col_1_val = substr($col_1_val, 0, 8) . '...';
}
$summary_html .= '' .
'| ' . esc_html($formatted_time) . ' | ' .
'' . esc_html($col_1_val) . ' | ' .
'' . esc_html($notification->reason) . ' | ' .
'
';
}
$summary_html .= '
';
$button_url = admin_url('admin.php?page=advaipbl_settings_page&tab=ip_management&sub-tab=blocked_ips');
if ($type === 'signature') {
$button_url = admin_url('admin.php?page=advaipbl_settings_page&tab=ip_management&sub-tab=blocked_signatures');
}
$button_text = ($type === 'signature') ? __('Manage Signatures', 'advanced-ip-blocker') : __('Manage All Blocked IPs', 'advanced-ip-blocker');
$summary_html .= '';
$body = $this->get_html_email_template($template_title, $summary_html);
add_filter('wp_mail_content_type', [$this, 'set_html_mail_content_type']);
$sent = wp_mail($to, $email_subject, $body);
remove_filter('wp_mail_content_type', [$this, 'set_html_mail_content_type']);
if ($sent) {
/* translators: %s is a placeholder */
$this->plugin->log_event(sprintf(__('Security summary (%1$s) sent to %2$s.', 'advanced-ip-blocker'), $type, $to), 'info');
} else {
/* translators: %s is a placeholder */
$this->plugin->log_event(sprintf(__('FAILED to send security summary (%1$s) to %2$s.', 'advanced-ip-blocker'), $type, $to), 'error');
}
}
/**
* Sends an instant block notification (Email/Push) or queues it.
*/
public function notify_block($ip, $type, $reason, $reason_label = '', $extra_data = [])
{
$options = $this->plugin->options;
if (empty($reason_label)) {
$reason_label = ucwords(str_replace('_', ' ', $type));
}
$location_data = $this->plugin->geolocation_manager->fetch_location($ip);
if (!empty($options['enable_push_notifications'])) {
$is_critical_block = !in_array($type, ['404', '403', 'login'], true);
$send_this_push = empty($options['push_critical_only']) || ($options['push_critical_only'] === '1' && $is_critical_block);
if ($send_this_push) {
$site_name = get_bloginfo('name');
$message_lines = [ sprintf('*:shield: [%s] Security Alert*', $site_name) ];
$message_lines[] = sprintf('> • *Blocked Entry:* `%s`', $ip);
if ($location_data && empty($location_data['error'])) {
$location_str = ($location_data['city'] ?? '') . ', ' . ($location_data['country'] ?? '');
$message_lines[] = sprintf('> • *Location:* %s (%s)', trim($location_str, ', '), $location_data['country_code'] ?? 'N/A');
}
$message_lines[] = sprintf('> • *Reason:* %s', $reason_label);
$message_lines[] = sprintf('> • *Details:* %s', $reason);
$duration_minutes = 0;
if (isset($extra_data['duration_seconds'])) {
$duration_minutes = $extra_data['duration_seconds'] > 0 ? round($extra_data['duration_seconds'] / 60) : 0;
} elseif ($type === 'aib_network') {
$duration_minutes = (int) ($options['duration_aib_network'] ?? 1440);
} elseif ($type === 'manual') {
$duration_minutes = 0;
} else {
$duration_minutes = (int) ($options['duration_' . $type] ?? 1440);
}
/* translators: %s is a placeholder */
$duration_text = ($duration_minutes <= 0 || $duration_minutes > 525600) ? __('Permanent', 'advanced-ip-blocker') : sprintf(__('%d min', 'advanced-ip-blocker'), $duration_minutes);
$message_lines[] = sprintf('> • *Duration:* %s', $duration_text);
$request_uri = $extra_data['uri'] ?? $this->plugin->get_current_request_uri();
if (!empty($request_uri)) {
$message_lines[] = sprintf('> • *URI:* `%s`', $request_uri);
}
// Note: user_agent could be passed in extra_data or fetched from main.
$ua = $extra_data['user_agent'] ?? $this->plugin->get_user_agent();
if ($ua) {
$message_lines[] = sprintf('> • *User Agent:* `%s`', $ua);
}
$this->execute_webhook_send(implode("\n", $message_lines));
}
}
$frequency = $options['notification_frequency'] ?? 'disabled';
if (empty($options['enable_email_notifications']) || '1' !== $options['enable_email_notifications'] || 'disabled' === $frequency) {
return;
}
if ($frequency === 'instant') {
$to = !empty($options['notification_email']) && is_email($options['notification_email']) ? $options['notification_email'] : get_option('admin_email');
$site_name = get_bloginfo('name');
/* translators: %s is a placeholder */
$email_subject = sprintf(__('[%s] Security Alert: Entry Automatically Blocked', 'advanced-ip-blocker'), $site_name);
$template_title = __('Security Alert: Entry Blocked', 'advanced-ip-blocker');
$duration_minutes = 0;
if (isset($extra_data['duration_seconds'])) {
$duration_minutes = $extra_data['duration_seconds'] > 0 ? round($extra_data['duration_seconds'] / 60) : 0;
} elseif ($type !== 'manual') {
$duration_minutes = (int) ($options['duration_' . $type] ?? 1440);
}
/* translators: %s is a placeholder */
$duration_text = ($duration_minutes <= 0 || $duration_minutes > 525600) ? __('Permanent', 'advanced-ip-blocker') : sprintf(__('%d minutes', 'advanced-ip-blocker'), $duration_minutes);
$button_url = admin_url('admin.php?page=advaipbl_settings_page-ip-management&sub-tab=blocked_ips');
$content_html = '' . esc_html__("An entry has been automatically blocked on your website.", 'advanced-ip-blocker') . '
' .
'' .
'| ' . esc_html__('Blocked Entry', 'advanced-ip-blocker') . ' | ' . esc_html($ip) . ' |
' .
'| ' . esc_html__('Date and Time', 'advanced-ip-blocker') . ' | ' . esc_html(date_i18n(get_option('date_format') . ' ' . get_option('time_format'))) . ' |
' .
'| ' . esc_html__('Reason', 'advanced-ip-blocker') . ' | ' . esc_html($reason) . ' |
' .
'| ' . esc_html__('Block Duration', 'advanced-ip-blocker') . ' | ' . esc_html($duration_text) . ' |
' .
'
' .
'' . esc_html__('No action is required on your part. This is just a notification.', 'advanced-ip-blocker') . '
'.
'';
$body = $this->get_html_email_template($template_title, $content_html);
add_filter('wp_mail_content_type', [ $this, 'set_html_mail_content_type' ]);
wp_mail($to, $email_subject, $body);
remove_filter('wp_mail_content_type', [ $this, 'set_html_mail_content_type' ]);
} else {
global $wpdb;
$table_name = $wpdb->prefix . 'advaipbl_notifications_queue';
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
@$wpdb->insert($table_name, [ 'timestamp' => current_time('mysql', 1), 'ip' => $ip, 'block_type' => $type, 'reason' => $reason ]);
}
}
/**
* Sends Auto Quarantine Notification (Email + Push).
*/
public function send_auto_quarantine_notification($file_path, $malware_type)
{
$options = $this->plugin->options;
$site_name = get_bloginfo('name');
if (!empty($options['enable_push_notifications'])) {
$message_lines = [
sprintf('*:warning: [%s] Malware Auto-Quarantined*', $site_name),
'> The File Integrity Monitor has automatically quarantined a malicious file.',
sprintf('> *File Path:* `%s`', $file_path),
sprintf('> *Malware Signature:* `%s`', $malware_type),
];
$this->execute_webhook_send(implode("\n", $message_lines));
}
if (!empty($options['enable_email_notifications'])) {
// Check if alert email is specifically configured for FIM
$to = !empty($options['fim_alert_email']) ? $options['fim_alert_email'] : (!empty($options['notification_email']) ? $options['notification_email'] : get_option('admin_email'));
/* translators: %s is a placeholder */
$email_subject = sprintf(__('[%1$s] Security Alert: Malware Auto-Quarantined', 'advanced-ip-blocker'), $site_name);
$template_title = __('Malware Auto-Quarantined', 'advanced-ip-blocker');
$button_url = admin_url('admin.php?page=advaipbl_settings_page&tab=integrity&sub-tab=fim_dashboard');
$content_html =
'' . esc_html__("The File Integrity Monitor has detected an exact malware signature match (MD5 or SHA256) and has automatically moved the malicious file to the quarantine vault to protect your site.", 'advanced-ip-blocker') . '
' .
'' .
'| ' . esc_html__('Quarantined File', 'advanced-ip-blocker') . ' | ' . esc_html($file_path) . ' |
' .
'| ' . esc_html__('Malware Signature', 'advanced-ip-blocker') . ' | ' . esc_html($malware_type) . ' |
' .
'
' .
'' . esc_html__('The file is safely disabled. You can review and delete it from the Quarantine Vault in the plugin dashboard.', 'advanced-ip-blocker') . '
'.
'';
$fim_settings_url = admin_url('admin.php?page=advaipbl_settings_page&tab=settings&sub-tab=general_settings#section-internal_security');
$body = $this->get_html_email_template($template_title, $content_html, $fim_settings_url);
add_filter('wp_mail_content_type', [$this, 'set_html_mail_content_type']);
wp_mail($to, $email_subject, $body);
remove_filter('wp_mail_content_type', [$this, 'set_html_mail_content_type']);
}
}
/**
* Sends Lockdown Notification (Email + Push).
*/
public function send_lockdown_notification($endpoint_key, $duration_minutes, $threshold)
{
$options = $this->plugin->options;
$site_name = get_bloginfo('name');
$endpoint_name = strtoupper($endpoint_key);
if (!empty($options['enable_push_notifications'])) {
$message_lines = [
sprintf('*:lock: [%s] Endpoint Lockdown Activated*', $site_name),
'> An automated defense system has been activated due to a sustained attack.',
sprintf('> • *Protected Endpoint:* `%s`', $endpoint_name),
sprintf('> • *Reason:* More than %d suspicious blocks detected recently.', $threshold),
sprintf('> • *Action:* All new traffic to this endpoint will be challenged for the next %d minutes.', $duration_minutes),
];
$this->execute_webhook_send(implode("\n", $message_lines));
}
if (!empty($options['enable_email_notifications']) && isset($options['notification_frequency']) && $options['notification_frequency'] === 'instant') {
$to = !empty($options['notification_email']) ? $options['notification_email'] : get_option('admin_email');
/* translators: %s is a placeholder */
$email_subject = sprintf(__('[%1$s] Security Alert: Endpoint Lockdown Activated for %2$s', 'advanced-ip-blocker'), $site_name, $endpoint_name);
$template_title = __('Endpoint Lockdown Activated', 'advanced-ip-blocker');
$button_url = admin_url('admin.php?page=advaipbl_settings_page&tab=logs&sub-tab=security_log');
$content_html =
'' . esc_html__("An automated defense mechanism, Endpoint Lockdown, has been activated on your website due to a sustained attack.", 'advanced-ip-blocker') . '
' .
'' .
'| ' . esc_html__('Protected Endpoint', 'advanced-ip-blocker') . ' | ' . esc_html($endpoint_name) . ' |
' .
/* translators: %s is a placeholder */
'| ' . esc_html__('Reason for Activation', 'advanced-ip-blocker') . ' | ' . sprintf(esc_html__('More than %d suspicious IP blocks were detected in a short period.', 'advanced-ip-blocker'), $threshold) . ' |
' .
/* translators: %s is a placeholder */
'| ' . esc_html__('Protective Action', 'advanced-ip-blocker') . ' | ' . sprintf(esc_html__('For the next %d minutes, all new, non-whitelisted traffic to this endpoint will be challenged with a JavaScript verifier to filter out bots.', 'advanced-ip-blocker'), $duration_minutes) . ' |
' .
'
' .
'' . esc_html__('This is an automated response to protect your site. No immediate action is required on your part.', 'advanced-ip-blocker') . '
'.
'';
$body = $this->get_html_email_template($template_title, $content_html);
add_filter('wp_mail_content_type', [$this, 'set_html_mail_content_type']);
wp_mail($to, $email_subject, $body);
remove_filter('wp_mail_content_type', [$this, 'set_html_mail_content_type']);
}
}
/**
* Sends AbuseIPDB Limit Notification.
*/
public function send_abuseipdb_limit_email()
{
$options = $this->plugin->options;
if (empty($options['enable_email_notifications']) || '1' !== $options['enable_email_notifications']) {
return;
}
$to = !empty($options['notification_email']) ? $options['notification_email'] : get_option('admin_email');
$site_name = get_bloginfo('name');
/* translators: %s is a placeholder */
$email_subject = sprintf(__('[%s] Security Alert: AbuseIPDB API Limit Reached', 'advanced-ip-blocker'), $site_name);
$template_title = __('AbuseIPDB API Limit Reached', 'advanced-ip-blocker');
$settings_url = admin_url('admin.php?page=advaipbl_settings_page&tab=settings&sub-tab=threat_intelligence');
$content_html =
'' . esc_html__("This is an automated notification to inform you that your website has reached the daily request limit for the AbuseIPDB API.", 'advanced-ip-blocker') . '
' .
'' . esc_html__("As a result, the real-time IP reputation checking has been temporarily paused. The system will automatically resume checks when the quota resets (typically at 00:00 UTC).", 'advanced-ip-blocker') . '
' .
'' . esc_html__('What this means:', 'advanced-ip-blocker') . '
' .
'' .
'- ' . esc_html__('Your site remains protected by all other security layers (WAF, Advanced Rules, etc.).', 'advanced-ip-blocker') . '
' .
'- ' . esc_html__('This is often an indicator of high bot traffic or a distributed attack.', 'advanced-ip-blocker') . '
' .
'
' .
'' . esc_html__('Recommended Actions:', 'advanced-ip-blocker') . '
' .
'' .
/* translators: %s is a placeholder */
'- ' . sprintf(wp_kses(__('Consider verifying your domain with AbuseIPDB to increase your free daily limit from 1,000 to 3,000 checks. Learn how.', 'advanced-ip-blocker'), ['a' => ['href' => [], 'target' => []]]), 'https://advaipbl.com/docs/abuseipdb-integration-guide/') . '
' .
/* translators: %s is a placeholder */
'- ' . sprintf(wp_kses(__('For high-traffic sites, consider upgrading to a paid AbuseIPDB plan for a higher limit.', 'advanced-ip-blocker'), ['a' => ['href' => [], 'target' => []]]), 'https://www.abuseipdb.com/pricing') . '
' .
'
' .
'';
$body = $this->get_html_email_template($template_title, $content_html);
add_filter('wp_mail_content_type', [$this, 'set_html_mail_content_type']);
wp_mail($to, $email_subject, $body);
remove_filter('wp_mail_content_type', [$this, 'set_html_mail_content_type']);
if (!empty($options['enable_push_notifications'])) {
$doc_link = 'https://advaipbl.com/docs/abuseipdb-integration-guide/';
$pricing_link = 'https://www.abuseipdb.com/pricing';
$message_lines = [
sprintf('*:warning: [%s] %s*', $site_name, __('Security Alert: AbuseIPDB API Limit Reached', 'advanced-ip-blocker')),
'> ' . __('Your website has reached its daily request limit for the AbuseIPDB API.', 'advanced-ip-blocker'),
'> ' . __('Real-time IP reputation checking will be temporarily paused.', 'advanced-ip-blocker'),
sprintf(
'> • *Action Required:* Consider <%1$s|verifying your domain> to triple your free quota or <%2$s|upgrading your plan>.',
$doc_link,
$pricing_link
),
];
$this->execute_webhook_send(implode("\n", $message_lines));
}
}
/**
* Executes webhook send.
*/
public function execute_webhook_send($message)
{
$options = $this->plugin->options;
if (empty($options['enable_push_notifications'])) {
return false;
}
$raw_urls = $options['push_webhook_urls'] ?? '';
if (empty(trim($raw_urls))) {
return false;
}
$urls = array_filter(array_map('trim', explode("\n", $raw_urls)));
if (empty($urls)) {
return false;
}
$payload = [
'content' => $message,
'text' => $message,
];
$args = [
'body' => wp_json_encode($payload),
'headers' => [
'Content-Type' => 'application/json',
],
'timeout' => 10,
];
$success = false;
foreach ($urls as $url) {
$response = wp_remote_post($url, $args);
if (is_wp_error($response)) {
$this->plugin->log_event('Failed to send push notification: ' . $response->get_error_message(), 'error', ['webhook_url' => $url]);
} elseif (wp_remote_retrieve_response_code($response) >= 300) {
$this->plugin->log_event('Push notification sent, but received an error response code: ' . wp_remote_retrieve_response_code($response), 'warning', ['webhook_url' => $url]);
} else {
$success = true;
}
}
return $success;
}
/**
* Standard HTML Email Template (Premium Design).
*/
public function get_html_email_template($title, $content, $custom_settings_url = null)
{
$logo_url = plugin_dir_url(dirname(__FILE__)) . 'assets/img/logo-email.png';
ob_start();
?>
plugin->options['enable_push_notifications'])) {
$message_lines = [
sprintf('*:dna: [%s] New Attack Signature Identified*', $site_name),
'> A new attack pattern has been automatically identified and is now being challenged.',
sprintf('> • *Signature Hash:* `%s`', $short_hash),
sprintf('> • *Reason:* %s', $reason),
sprintf('> • *Sample User-Agent:* `%s`', $user_agent),
];
$this->execute_webhook_send(implode("\n", $message_lines));
}
if (!empty($this->plugin->options['enable_email_notifications'])) {
$options = $this->plugin->options;
$to = !empty($options['notification_email']) ? $options['notification_email'] : get_option('admin_email');
/* translators: %s is a placeholder */
$email_subject = sprintf(__('[%s] Security Alert: New Attack Signature Identified', 'advanced-ip-blocker'), $site_name);
$template_title = __('New Attack Signature Identified', 'advanced-ip-blocker');
$button_url = admin_url('admin.php?page=advaipbl_settings_page&tab=ip_management&sub-tab=blocked_signatures');
$content_html =
'' . esc_html__("The plugin's analysis engine has automatically identified a new distributed attack pattern. Requests matching this signature will now be challenged.", 'advanced-ip-blocker') . '
' .
'' .
'| ' . esc_html__('Signature Hash', 'advanced-ip-blocker') . ' | ' . esc_html($short_hash) . ' |
' .
'| ' . esc_html__('Reason', 'advanced-ip-blocker') . ' | ' . esc_html($reason) . ' |
' .
'| ' . esc_html__('Sample User-Agent', 'advanced-ip-blocker') . ' | ' . esc_html($user_agent) . ' |
' .
'
' .
'' . esc_html__('You can view and manage all active signatures from the dashboard.', 'advanced-ip-blocker') . '
'.
'';
$body = $this->get_html_email_template($template_title, $content_html);
add_filter('wp_mail_content_type', [$this, 'set_html_mail_content_type']);
wp_mail($to, $email_subject, $body);
remove_filter('wp_mail_content_type', [$this, 'set_html_mail_content_type']);
}
}
/**
* Handles sending a test email.
*/
public function send_test_email($to)
{
$site_name = get_bloginfo('name');
$settings_url = admin_url('admin.php?page=advaipbl_settings_page&tab=dashboard&sub-tab=status');
/* translators: %s is a placeholder */
$email_subject = sprintf(__('[%s] Welcome & Quick Setup Guide for Advanced IP Blocker', 'advanced-ip-blocker'), $site_name);
$template_title = __('Welcome & Quick Setup Guide', 'advanced-ip-blocker');
$content_html =
'' . esc_html__('Thank you for using Advanced IP Blocker! This email confirms your email settings are working. Here is a quick guide to get the most out of the plugin:', 'advanced-ip-blocker') . '
' .
'' . esc_html__('Step 1: Verify Whitelisted IPs', 'advanced-ip-blocker') . '
' .
'' .
sprintf(
/* translators: %s is a placeholder */
wp_kses(__('This is the most important step. Go to the Status & Debug tab to confirm your IP is whitelisted.', 'advanced-ip-blocker'), ['a' => ['href' => []]]),
esc_url($settings_url)
) . '
';
$body = $this->get_html_email_template($template_title, $content_html);
add_filter('wp_mail_content_type', [$this, 'set_html_mail_content_type']);
$sent = wp_mail($to, $email_subject, $body);
remove_filter('wp_mail_content_type', [$this, 'set_html_mail_content_type']);
return $sent;
}
/**
* Handles sending a test push notification.
*/
public function send_test_push()
{
$options = $this->plugin->options;
$webhook_urls_str = $options['push_webhook_urls'] ?? '';
$webhook_urls = array_filter(array_map('trim', explode("\n", $webhook_urls_str)));
if (empty($webhook_urls)) {
return false;
}
$site_name = get_bloginfo('name');
$message_lines = [
sprintf('*:rocket: [%s] Test Notification*', $site_name),
'> ' . esc_html__('This is a test notification from Advanced IP Blocker.', 'advanced-ip-blocker'),
'> • *Status:* Working successfully.',
'> • *Time:* ' . current_time('mysql'),
];
$message = implode("\n", $message_lines);
return $this->execute_webhook_send($message);
}
/**
* Sends 2FA Activation/Deactivation Notification.
*
* @param string $action 'activated' or 'deactivated'
* @param WP_User $user The user object
*/
public function send_2fa_notification_email($action, $user)
{
$options = $this->plugin->options;
if (empty($options['enable_email_notifications']) || '1' !== $options['enable_email_notifications']) {
return;
}
$to = $user->user_email;
$site_name = get_bloginfo('name');
$subject_action = ($action === 'activated') ? __('Activated', 'advanced-ip-blocker') : __('Deactivated', 'advanced-ip-blocker');
/* translators: %s is a placeholder */
$email_subject = sprintf(__('[%1$s] Security Alert: 2FA %2$s', 'advanced-ip-blocker'), $site_name, $subject_action);
/* translators: %s is a placeholder */
$template_title = sprintf(__('Two-Factor Authentication %s', 'advanced-ip-blocker'), $subject_action);
$date = date_i18n(get_option('date_format') . ' ' . get_option('time_format'));
$content_html = '' .
sprintf(
/* translators: %s is a placeholder */
esc_html__('Hello %1$s, use this email to confirm that Two-Factor Authentication has been %2$s for your account.', 'advanced-ip-blocker'),
esc_html($user->display_name),
'' . esc_html(strtolower($subject_action)) . ''
) . '
';
$content_html .= '' .
'| ' . esc_html__('Account', 'advanced-ip-blocker') . ' | ' . esc_html($user->user_login) . ' |
' .
'| ' . esc_html__('Date', 'advanced-ip-blocker') . ' | ' . esc_html($date) . ' |
' .
'| ' . esc_html__('Status', 'advanced-ip-blocker') . ' | ' . esc_html($subject_action) . ' |
' .
'
';
if ($action === 'deactivated') {
$content_html .= '' . esc_html__('If you did not perform this action, please contact the site administrator immediately and change your password.', 'advanced-ip-blocker') . '
';
}
$body = $this->get_html_email_template($template_title, $content_html);
add_filter('wp_mail_content_type', [$this, 'set_html_mail_content_type']);
wp_mail($to, $email_subject, $body);
remove_filter('wp_mail_content_type', [$this, 'set_html_mail_content_type']);
}
public function set_html_mail_content_type()
{
return 'text/html';
}
/**
* Sends a batch notification for multiple detected signatures.
*/
public function send_signature_batch_notification($signatures)
{
$options = $this->plugin->options;
$frequency = $options['signature_notification_frequency'] ?? 'instant';
if ($frequency === 'disabled') {
return;
}
if ($frequency === 'daily' || $frequency === 'weekly') {
global $wpdb;
$table_name = $wpdb->prefix . 'advaipbl_notifications_queue';
foreach ($signatures as $sig) {
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->insert($table_name, [
'timestamp' => current_time('mysql', 1),
'ip' => $sig['hash'],
'block_type' => 'signature',
'reason' => $sig['reason']
]);
}
return;
}
if ($frequency === 'instant') {
$recipient_type = $options['signature_notification_recipient'] ?? 'default';
$to = get_option('admin_email');
if ($recipient_type === 'default') {
$to = !empty($options['notification_email']) ? $options['notification_email'] : get_option('admin_email');
} elseif ($recipient_type === 'custom') {
$to = !empty($options['signature_notification_custom_email']) ? $options['signature_notification_custom_email'] : get_option('admin_email');
}
if (!is_email($to)) {
$to = get_option('admin_email');
}
$site_name = get_bloginfo('name');
$count = count($signatures);
/* translators: %s is a placeholder */
$email_subject = sprintf(__('[%1$s] Security Alert: %2$d New Attack Signatures Identified', 'advanced-ip-blocker'), $site_name, $count);
/* translators: %s is a placeholder */
$template_title = sprintf(__('Attack Signatures Identified (%d)', 'advanced-ip-blocker'), $count);
$button_url = admin_url('admin.php?page=advaipbl_settings_page&tab=ip_management&sub-tab=blocked_signatures');
$content_html = '' . esc_html__("The plugin's analysis engine has identified new distributed attack patterns. Requests matching these signatures will now be challenged.", 'advanced-ip-blocker') . '
';
$content_html .= '' .
'' .
'| ' . esc_html__('Hash', 'advanced-ip-blocker') . ' | ' .
'' . esc_html__('Reason', 'advanced-ip-blocker') . ' | ' .
'' . esc_html__('Count', 'advanced-ip-blocker') . ' | ' .
'
';
foreach ($signatures as $sig) {
$short_hash = substr($sig['hash'], 0, 8) . '...';
$content_html .= '' .
'' . esc_html($short_hash) . ' | ' .
'' . esc_html($sig['reason']) . ' | ' .
/* translators: %s is a placeholder */
'' . sprintf(esc_html__('%d IPs', 'advanced-ip-blocker'), $sig['count']) . ' | ' .
'
';
}
$content_html .= '
';
$content_html .= '';
$body = $this->get_html_email_template($template_title, $content_html);
add_filter('wp_mail_content_type', [$this, 'set_html_mail_content_type']);
wp_mail($to, $email_subject, $body);
remove_filter('wp_mail_content_type', [$this, 'set_html_mail_content_type']);
}
if (!empty($options['enable_push_notifications'])) {
$site_name = get_bloginfo('name');
$count = count($signatures);
$message_lines = [
sprintf('*:dna: [%s] Attack Signatures Identified*', $site_name),
sprintf('> %d new attack patterns have been identified and challenged.', $count),
];
foreach (array_slice($signatures, 0, 3) as $sig) {
$short_hash = substr($sig['hash'], 0, 8) . '...';
$message_lines[] = sprintf('> • `%s`: %s', $short_hash, $sig['reason']);
}
if ($count > 3) {
$message_lines[] = sprintf('> • ... and %d more.', $count - 3);
}
$this->execute_webhook_send(implode("\n", $message_lines));
}
}
}