Skip to content

Commit 7e9cd77

Browse files
committed
v2.1.2: Slack alert if wp_mail_failed
- fix #25: Webhook field to use for hook
1 parent 0990e40 commit 7e9cd77

File tree

6 files changed

+362
-4
lines changed

6 files changed

+362
-4
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
# Changelog
22
All notable changes to TNC Toolbox for WordPress will be documented in this file.
33

4+
## [2.1.2] - 2026-01-13
5+
6+
### 🚀 Feature
7+
- **Slack Alerts for Mail Failures**: Receive Slack notifications when `wp_mail` fails
8+
- New "Slack Webhook URL" field in plugin settings
9+
- Alerts include site name, recipient, subject, and error details
10+
- Uses WordPress `wp_mail_failed` hook for reliable detection
11+
412
## [2.1.1] - 2026-01-10
513

614
### 🐛 Bug Fix

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ https://wordpress.org/plugins/tnc-toolbox
1313
- For any action, redirects you back to the page you requested it from
1414
- Shows you whether or not the API is working via diagnostic quota info
1515
- Selective cache purging with `ea-nginx-cache-purge` module (optional)
16+
- Slack alert (via Webhook) if WordPress fails to send an email to you
1617

1718
## 🖥️ (PLUGIN) System Requirements
1819

tnc-toolbox/core/settings.php

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ public function __construct() {
5050
$this->plugin_name = TNCTOOLBOX_NAME;
5151
add_action('init', array($this, 'init_settings'));
5252
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_styles'));
53+
add_action('wp_ajax_tnc_test_slack_webhook', array($this, 'ajax_test_slack_webhook'));
5354
}
5455

5556
// Enqueue admin styles for settings page
@@ -126,11 +127,15 @@ private function save_settings() {
126127
$api_key = sanitize_text_field($_POST['tnc_toolbox_api_key'] ?? '');
127128
$username = sanitize_text_field($_POST['tnc_toolbox_username'] ?? '');
128129
$hostname = sanitize_text_field($_POST['tnc_toolbox_server_hostname'] ?? '');
130+
$slack_webhook = sanitize_url($_POST['tnc_toolbox_slack_webhook'] ?? '');
129131

130132
// Handle selective purge setting - use the POST value directly to avoid race conditions
131133
$selective_purge_enabled = isset($_POST['tnc_selective_purge']);
132134
TNC_Cache_Purge::set_enabled($selective_purge_enabled);
133135

136+
// Save Slack webhook URL
137+
TNC_Slack_Alerts::store_webhook_url($slack_webhook);
138+
134139
// Try to save the configuration even if empty to ensure options exist
135140
TNC_cPanel_UAPI::store_config($username, $api_key, $hostname);
136141

@@ -229,6 +234,21 @@ class="regular-text" />
229234
</label>
230235
</td>
231236
</tr>
237+
<tr>
238+
<th scope="row">
239+
<label for="tnc_toolbox_slack_webhook">Slack Webhook URL</label>
240+
<p class="description">For mail failure alerts.<br><a href="https://api.slack.com/messaging/webhooks" target="_blank">Create Webhook</a>.</p>
241+
</th>
242+
<td>
243+
<input type="url" id="tnc_toolbox_slack_webhook" name="tnc_toolbox_slack_webhook"
244+
value="<?php echo esc_attr(TNC_Slack_Alerts::get_webhook_url()); ?>"
245+
placeholder="https://hooks.slack.com/services/..."
246+
class="regular-text" />
247+
<button type="button" id="tnc_test_slack_webhook" class="button button-secondary">Test Webhook</button>
248+
<span id="tnc_slack_test_result" style="margin-left: 10px;"></span>
249+
<p class="description">Receive alerts when WordPress fails to send emails.</p>
250+
</td>
251+
</tr>
232252
</table>
233253

234254
<p class="submit">
@@ -254,6 +274,72 @@ class="regular-text" />
254274
<?php endif; ?>
255275
</div>
256276
</div>
277+
<script type="text/javascript">
278+
jQuery(document).ready(function($) {
279+
$('#tnc_test_slack_webhook').on('click', function() {
280+
var $button = $(this);
281+
var $result = $('#tnc_slack_test_result');
282+
var webhookUrl = $('#tnc_toolbox_slack_webhook').val();
283+
284+
if (!webhookUrl) {
285+
$result.html('<span style="color: #dc3232;">Please enter a webhook URL first.</span>');
286+
return;
287+
}
288+
289+
$button.prop('disabled', true).text('Testing...');
290+
$result.html('');
291+
292+
$.post(ajaxurl, {
293+
action: 'tnc_test_slack_webhook',
294+
webhook_url: webhookUrl,
295+
nonce: '<?php echo wp_create_nonce('tnc_test_slack_webhook'); ?>'
296+
}, function(response) {
297+
if (response.success) {
298+
$result.html('<span style="color: #46b450;">✓ ' + response.data.message + '</span>');
299+
} else {
300+
$result.html('<span style="color: #dc3232;">✗ ' + response.data.message + '</span>');
301+
}
302+
}).fail(function() {
303+
$result.html('<span style="color: #dc3232;">✗ Request failed</span>');
304+
}).always(function() {
305+
$button.prop('disabled', false).text('Test Webhook');
306+
});
307+
});
308+
});
309+
</script>
257310
<?php
258311
}
312+
313+
/**
314+
* AJAX handler for testing Slack webhook
315+
*/
316+
public function ajax_test_slack_webhook() {
317+
// Verify nonce
318+
if (!wp_verify_nonce($_POST['nonce'] ?? '', 'tnc_test_slack_webhook')) {
319+
wp_send_json_error(array('message' => 'Invalid nonce'));
320+
}
321+
322+
// Check permissions
323+
if (!current_user_can('manage_options')) {
324+
wp_send_json_error(array('message' => 'Permission denied'));
325+
}
326+
327+
// Get and validate webhook URL
328+
$webhook_url = sanitize_url($_POST['webhook_url'] ?? '');
329+
if (empty($webhook_url)) {
330+
wp_send_json_error(array('message' => 'No webhook URL provided'));
331+
}
332+
333+
// Temporarily store the URL for testing
334+
TNC_Slack_Alerts::store_webhook_url($webhook_url);
335+
336+
// Run the test
337+
$result = TNC_Slack_Alerts::test_webhook();
338+
339+
if ($result['success']) {
340+
wp_send_json_success(array('message' => $result['message']));
341+
} else {
342+
wp_send_json_error(array('message' => $result['message']));
343+
}
344+
}
259345
}

tnc-toolbox/readme.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Donate link:
55
Contributors:
66
Tags: NGINX, Cache Purge, Web Performance, Automatic Purge, Freeware
77
Tested up to: 6.9
8-
Stable tag: 2.1.1
8+
Stable tag: 2.1.2
99
License: GPLv3
1010
License URI: https://www.gnu.org/licenses/gpl-3.0.html
1111

@@ -152,6 +152,9 @@ _(* Change to main plugin file name may result in deactivation)_
152152

153153
== Changelog ==
154154

155+
= 2.1.2: Jan 13, 2026 =
156+
* Feature: Slack alerts when wp_mail fails (Webhook field)
157+
155158
= 2.1.1: Jan 10, 2026 =
156159
* Bug Fix: Fix false positive cache-purge module detection
157160

tnc-toolbox/tnc-toolbox.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
* @package TNCTOOLBOX
66
* @author The Network Crew Pty Ltd (Merlot Digital)
77
* @license gplv3
8-
* @version 2.1.1
8+
* @version 2.1.2
99
*
1010
* @wordpress-plugin
1111
* Plugin Name: TNC Toolbox: Web Performance
1212
* Plugin URI: https://merlot.digital
1313
* Description: Designed for ea-NGINX (Cache/Proxy) on cPanel+WHM. Now with selective cache purging support!
14-
* Version: 2.1.1
14+
* Version: 2.1.2
1515
* Author: The Network Crew Pty Ltd (Merlot Digital)
1616
* Author URI: https://tnc.works
1717
* Domain Path: /locale
@@ -29,7 +29,7 @@
2929
define('TNCTOOLBOX_NAME', 'TNC Toolbox');
3030

3131
// Plugin version
32-
define('TNCTOOLBOX_VERSION', '2.1.0');
32+
define('TNCTOOLBOX_VERSION', '2.1.2');
3333

3434
// Plugin Root File
3535
define('TNCTOOLBOX_PLUGIN_FILE', __FILE__);
@@ -48,6 +48,7 @@
4848
require_once TNCTOOLBOX_PLUGIN_DIR . 'core/settings.php';
4949
require_once TNCTOOLBOX_PLUGIN_DIR . 'vendor/cpanel-uapi.php';
5050
require_once TNCTOOLBOX_PLUGIN_DIR . 'vendor/cache-purge.php';
51+
require_once TNCTOOLBOX_PLUGIN_DIR . 'vendor/alerts-slack.php';
5152

5253
/**
5354
* Main plugin class for initialisation and hooks

0 commit comments

Comments
 (0)