- PHP 95.4%
- CSS 2%
- JavaScript 1.6%
- Shell 1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| .claude | ||
| .forgejo/workflows | ||
| assets | ||
| includes | ||
| tests | ||
| .distignore | ||
| .gitattributes | ||
| .gitignore | ||
| .wp-env.json | ||
| apprise-notifications.php | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| composer.json | ||
| LICENSE | ||
| package-lock.json | ||
| package.json | ||
| patchwork.json | ||
| phpcs.xml.dist | ||
| phpstan.neon | ||
| phpunit.xml | ||
| README.md | ||
| readme.txt | ||
| SECURITY.md | ||
| uninstall.php | ||
Apprise Notifications for WordPress
Send WordPress system events to an Apprise API endpoint.
AI Disclosure
This plugin was completely written by Claude AI.
I (a human) did testing to verify each feature worked and ran the code through Semgrep.dev to see if there was anything blatantly wrong.
Features
- 🔔 Multiple Notification Events: See Supported Events for a full list
- 🔒 Security-First Design: Built following WordPress security best practices and OWASP guidelines, or at least that's what I told the AI Agent to do
- ⚡ Lightweight: Notifications are queued and sent at PHP shutdown, after the page has been delivered, so they don't slow the request down
- 🔧 Highly Configurable: Enable/disable individual events, debug logging, and more
- 🔌 Extensible: Filter hooks for customizing every aspect of notifications
- 🛡️ Privacy-Aware: Configurable IP logging with anonymization options
- 📧 Email Suppression: Prevent duplicate notifications by suppressing WordPress default emails for events handled by Apprise
- 🔄 Update Checker: Optional update checking with one-click updates and Apprise notifications
Requirements
- WordPress 6.1+
- PHP 8.3+
- An Apprise API endpoint
Installation
Install Plugin
- Go to the Releases page
- Download the latest release's
apprise-wordpress-notifications.X.Y.Z.zipfile (not theSource Code (ZIP)archive) - Login to your Wordpress Site
- Click
Plugins - Click
Add Plugin - Click
Upload Plugin - Click
Browseand select ZIP file you downloaded from the Releases page - Click
Install Now - Click
Activate Plugin
Configuration
- Navigate to
SettingsandApprise Notifications - Enter your Apprise API URL (Example:
https://apprise.yourdomain.com/notify/{APIKEY}) - (Optional) Set a default tag for notifications
- Checkmark
Enable Notifications - Review and checkmark which notifications you would like to receive
- Click
Test Connectionto verify your setup - Click
Save Changes
Supported Events
All events except Admin Login and New Comment are off until you enable them.
| Event | Description |
|---|---|
| Admin Login | Triggered when a user with manage_options logs in (on by default) |
| User Registration | Triggered when a new user registers |
| User Role Changed | Triggered when a user's role changes |
| User Deleted | Triggered when a user is deleted |
| Post Published | Triggered when a post is published |
| Post Updated | Triggered when a published post is updated |
| Post Moved to Trash | Triggered when a post is moved to trash |
| Post Permanently Deleted | Triggered when a post is permanently deleted |
| New Comment | Triggered when a comment is posted (on by default) |
| Pingback / Trackback | Triggered when a pingback or trackback is received |
| Core Updated | Triggered when WordPress core is updated |
| Plugin Installed | Triggered when a plugin is installed |
| Plugin Updated | Triggered when a plugin is updated |
| Plugin Deleted | Triggered when a plugin is deleted |
| Theme Installed | Triggered when a theme is installed |
| Theme Changed | Triggered when the active theme changes |
| Theme Updated | Triggered when an installed theme is updated, manually or automatically |
Posts and pages are covered by default; see Add Custom Post Types for others. A separate notice for new versions of this plugin is sent when Update Checking is on.
Email Suppression
To avoid receiving duplicate notifications (one from Apprise and one from WordPress), the Suppress WordPress Emails setting has three modes:
| Mode | Behavior |
|---|---|
| None (default) | WordPress emails are unaffected |
| Matching events only | Suppresses a WordPress email only when the Apprise event that replaces it is enabled: comment notifications (New Comment; pingbacks and trackbacks by Pingback / Trackback), the admin's new-user email (User Registration; the new user still gets their set-password email), and the automatic-update emails (Core Updated, Plugin Updated, Theme Updated) |
| All emails | Blocks all emails sent via wp_mail(), including password resets, which have no Apprise replacement. Use with caution |
Email suppression is only active when the plugin is globally enabled and an Apprise API URL is set. Deactivating or uninstalling the plugin automatically restores all WordPress emails.
Update Checking
Since this plugin is hosted on a self-hosted Forgejo instance rather than wordpress.org, it includes an optional update checker. It is off by default. When Check for Updates is enabled under Settings → Apprise Notifications:
- WordPress reads the releases feed whenever it checks for plugin updates (about twice a day; the result is cached for 12 hours, a failed fetch for 1 hour)
- A newer release shows up on Plugins and Dashboard → Updates like any other plugin update, and Update now installs the release zip from Forgejo
- An Apprise notification is sent once per new version, from a daily WP-Cron job, as long as Enable Notifications is also on
- The request uses an
Apprise-Notifications/<version>user agent, so the site's address isn't sent to the forge
On multisite, the main site's setting applies to the whole network, and only the main site sends the Apprise notification.
The plugin header's Update URI also stops WordPress from offering a wordpress.org plugin with the same slug as an update.
Plugin Architecture
apprise-wordpress-notifications/
├── apprise-notifications.php # Main plugin bootstrap
├── uninstall.php # Cleanup on plugin deletion (multisite-aware)
├── includes/
│ ├── class-apprise-client.php # Apprise API client, SSRF protection
│ ├── class-apprise-event-dispatcher.php # Central event dispatcher, shutdown queue
│ ├── class-apprise-admin-settings.php # Admin settings page
│ ├── class-apprise-email-suppressor.php # WordPress email suppression
│ ├── class-apprise-update-checker.php # Forgejo release update checker
│ ├── class-apprise-logger.php # Secure logging
│ ├── class-apprise-role-utils.php # Role slug → label helpers
│ ├── trait-apprise-event-deduplication.php
│ └── events/
│ ├── class-apprise-comment-events.php
│ ├── class-apprise-login-events.php
│ ├── class-apprise-user-events.php
│ ├── class-apprise-post-events.php
│ ├── class-apprise-plugin-events.php # Also theme install/switch/update
│ └── class-apprise-core-events.php
├── assets/
│ ├── admin.css
│ └── admin.js
├── CHANGELOG.md
├── readme.txt
└── README.md
Developer Documentation
Filter Hooks
Modify Notifications Before Sending
add_filter( 'apprise_notifications_before_dispatch', function( $notification, $event_type, $context ) {
// Add a prefix to all notification titles
$notification['title'] = '[My Site] ' . $notification['title'];
// Change notification type
$notification['type'] = 'warning';
// Cancel the notification by returning false
if ( 'post_update' === $event_type ) {
return false;
}
return $notification;
}, 10, 3 );
Add Custom Post Types
add_filter( 'apprise_notifications_supported_post_types', function( $types ) {
$types[] = 'product';
$types[] = 'event';
return $types;
} );
Send Custom Events
Route your own events through the plugin's dispatcher. Event types that aren't one of the built-in keys are dropped unless you enable them:
add_filter( 'apprise_notifications_unknown_event_enabled', function( $enabled, $event_type ) {
return 'woocommerce_order' === $event_type ? true : $enabled;
}, 10, 2 );
add_action( 'woocommerce_new_order', function( $order_id ) {
$dispatcher = apprise_notifications()->get_component( 'dispatcher' );
if ( $dispatcher ) {
$dispatcher->dispatch( 'woocommerce_order', 'New order', "Order #{$order_id} was placed." );
}
} );
Use apprise_notifications_event_type_map to give your event a notification type other than info:
add_filter( 'apprise_notifications_event_type_map', function( $map ) {
$map['woocommerce_order'] = 'success';
return $map;
} );
Privacy Controls
// Disable IP logging in notifications
add_filter( 'apprise_notifications_include_login_ip', '__return_false' );
// Anonymize IP addresses instead of disabling
add_filter( 'apprise_notifications_anonymize_ip', '__return_true' );
// Leave the user's email out of user notifications
add_filter( 'apprise_notifications_include_user_email', '__return_false' );
// Allow localhost for development
add_filter( 'apprise_notifications_allow_localhost', '__return_true' );
All Hooks
| Hook | Type | Default | Purpose |
|---|---|---|---|
apprise_notifications_before_dispatch |
filter | — | Change a notification's title, body, type or tag, or return false to cancel it |
apprise_notifications_supported_post_types |
filter | ['post', 'page'] |
Post types that trigger post events |
apprise_notifications_event_type_map |
filter | — | Map event keys to info / success / warning / failure |
apprise_notifications_unknown_event_enabled |
filter | false |
Whether an event key with no setting is sent |
apprise_notifications_async_dispatch |
filter | true |
Return false to send synchronously instead of at shutdown (for debugging) |
apprise_notifications_request_args |
filter | — | Modify the HTTP request args; security-critical args are enforced after this filter |
apprise_notifications_allow_localhost |
filter | false |
Allow loopback addresses (the only way to open them) |
apprise_notifications_allow_private_ip |
filter | Allow Private IPs setting | Allow private/reserved addresses; link-local and cloud metadata addresses get false as the default and need a strict true |
apprise_notifications_include_login_ip |
filter | true |
Include the IP address in login notifications |
apprise_notifications_anonymize_ip |
filter | false |
Anonymize that IP address |
apprise_notifications_include_user_email |
filter | true |
Include the user's email in user notifications |
apprise_notifications_queue_flushed |
action | — | Fires after the shutdown queue is sent; receives the number of notifications |
apprise_notifications_log |
action | — | Fires for each log entry; receives level, message and context |
apprise_notifications_uninstalled |
action | — | Fires when the plugin's data is removed on uninstall |
Action Hooks
Custom Log Handler
add_action( 'apprise_notifications_log', function( $level, $message, $context ) {
// Send logs to your custom logging service
my_custom_logger( $level, $message, $context );
}, 10, 3 );
Security Features
- Input Validation: All inputs are sanitized using WordPress sanitization functions
- Output Escaping: All outputs are escaped to prevent XSS
- Nonce Verification: All admin actions use WordPress nonces
- Capability Checks: Admin functions require
manage_optionscapability; on multisite only a super admin can change Allow Private IPs - SSRF Protection: The API URL's host is resolved and pinned for the request, loopback, private, link-local and cloud metadata addresses are blocked (private ranges can be opened with Allow Private IPs), and redirects are not followed
- Secure Logging: Sensitive data (API keys, passwords, tokens) is automatically redacted from logs
- Non-Blocking Failures: Network errors never block WordPress execution