Install
This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/sadecewp/swpmail/archive/refs/heads/main.zipSWPMail - WordPress SMTP & Subscription Plugin
🇬🇧 English · 🇹🇷 Türkçe · 🇩🇪 Deutsch · 🇪🇸 Español · 🇫🇷 Français · 🇮🇹 Italiano · 🇯🇵 日本語 · 🇳🇱 Nederlands · 🇧🇷 Português
SWPMail is a fully customizable email subscription, notification, and sending infrastructure plugin that integrates with WordPress sites, supports 18 professional mail services, applies the configured SMTP/API setting to all WordPress emails sent via wp_mail(), and features enterprise-grade capabilities such as smart routing, failover, OAuth 2.0, email tracking & analytics, alarm system, DNS verification, and multilingual support (9 languages).
Table of Contents
- Features
- Tech Stack
- System Requirements
- Installation
- Quick Start (Setup Wizard)
- Supported Mail Services (18 Providers)
- wp_mail Override System
- Smart Routing
- Connection Management & Failover
- OAuth 2.0 Integration
- Subscription System
- Shortcode Usage
- HTML Email Templates
- Trigger System
- Queue & Cron System
- Email Tracking & Analytics
- Alarm System
- DNS Checker (SPF / DKIM / DMARC)
- REST API
- WP-CLI Commands
- Admin Panel
- Security
- GDPR & Legal Compliance
- Multilingual Support (i18n)
- Theme Developer Guide
- Hooks Reference (Developer API)
- File Structure
- Database Design
- Diagnostics & Repair Tools
- Testing
- FAQ (Frequently Asked Questions)
- License
Tech Stack
| Layer | Technology | Details |
|---|---|---|
| Backend | PHP 7.4+ | 24,000+ lines — OOP with Factory, Strategy & Template Method patterns |
| Frontend | JavaScript (jQuery) | 1,900+ lines — AJAX-driven admin UI, multi-step setup wizard |
| Styling | CSS3 (Custom Properties) | 4,000+ lines — 570+ CSS variables, "Parchment & Forest" design system |
| Typography | Google Fonts | Cormorant Garamond (display), Nunito (body), JetBrains Mono (code) |
| Editor | CodeMirror | Built-in HTML template editor via WordPress code editor API |
| Database | MySQL / MariaDB | 4 custom InnoDB tables with optimized indexes |
| CLI | WP-CLI | 16 subcommands for full terminal management |
| API | WordPress REST API | 3 endpoints + 32 AJAX handlers |
| Testing | PHPUnit 9 + Brain\Monkey | WordPress-aware unit testing |
| Linting | PHPCS + WPCS | WordPress Coding Standards enforced |
| i18n | WordPress L10n | 9 languages with .po / .mo files |
| Dependencies | None (runtime) | Zero external libraries — pure WordPress HTTP API |
At a Glance
📦 30,000+ lines of code 🗂️ 67 PHP classes 🎨 570+ CSS variables
📮 18 mail providers 🔌 48 extensibility hooks 🗄️ 4 custom DB tables
🌍 9 languages ⚡ 16 WP-CLI commands 📡 3 REST + 32 AJAX endpoints
🔔 5 alarm channels 📋 10 email templates 🔄 6 cron events
Features
Sending Infrastructure
- 18 Mail Service Providers: PHP Mail, Generic SMTP, SendLayer, SMTP.com, Gmail, Outlook, Mailgun, SendGrid, Postmark, Brevo, Amazon SES, Resend, Elastic Email, Mailjet, MailerSend, SMTP2GO, SparkPost, Zoho Mail
- Global wp_mail Override: All WordPress emails (WooCommerce, Contact Form 7, password reset, etc.) are sent through the selected provider
- Smart Routing: Rule-based conditional email routing — different providers can be used based on criteria such as recipient, subject, source
- Failover & Health Check: Automatic fallback to backup provider when the primary provider fails, with health check mechanism
- OAuth 2.0: Full OAuth 2.0 flow for Gmail and Outlook, with automatic token refresh
Subscription & Notification
- Subscription System: Instant, daily digest, and weekly digest options
- Double Opt-in: Double confirmation mechanism enabled by default
- 5 Built-in Triggers: New post, new user, user login, new comment, password reset
- Extensible Trigger System: Custom trigger support for third-party plugins
- Queue System: WP-Cron based asynchronous email queue with retry mechanism
Templates & Content
- HTML Mail Templates: Fully customizable responsive email templates with theme override support
- Template Editor: CodeMirror-based HTML template editing in the admin panel
- Variable System: Dynamic variables like
{{post_title}},{{site_name}}in templates
Monitoring & Analytics
- Email Tracking: Open (open pixel) and click (click redirect) tracking
- Analytics Dashboard: Total/unique opens, total/unique clicks, rate calculations
- Alarm System: Instant error notifications via Slack, Discord, Microsoft Teams, Twilio SMS, and custom webhooks
- DNS Checker: Automatic verification of SPF, DKIM, DMARC records
Developer & Management
- REST API: Programmatic subscriber management
- WP-CLI: Full management via terminal with 16+ commands
- Setup Wizard: Step-by-step configuration on first activation
- Conflict Detector: Detection of 18+ known conflicting plugins
- Database Repair: Table/column/index deficiency diagnostics and automatic repair
- Email Logs: Detailed sending records and filtering
Security & Compliance
- AES-256-CBC Encryption: API keys are stored encrypted in the database with HMAC-SHA256 verification
- Rate Limiting: IP-based request limiting and bot protection (honeypot)
- GDPR Compliant: WordPress Privacy API integration, unsubscribe links
- Multilingual (9 Languages): English, Türkçe, Deutsch, Español, Français, Italiano, 日本語, Nederlands, Português (BR)
- Zero External Dependencies: No external libraries required; uses WordPress HTTP API
System Requirements
| Requirement | Minimum | Recommended |
|---|---|---|
| PHP | 7.4 | 8.1+ |
| WordPress | 6.0 | 6.7+ |
| MySQL | 5.7 | 8.0+ |
| MariaDB | 10.3 | 10.6+ |
| cURL | Enabled | Enabled |
| OpenSSL | Enabled | Enabled |
Installation
Via WordPress Admin Panel
- Go to Plugins > Add New
- Upload the
swpmailfolder as a ZIP file - Click the Activate button
Manual Installation
- Upload the
swpmailfolder to the/wp-content/plugins/directory:# Extract the zip file unzip swpmail.zip -d /path/to/wp-content/plugins/ - Activate it from the Plugins page in the WordPress admin panel
After Activation
When the plugin is activated, it automatically:
- Creates 4 database tables (
swpm_subscribers,swpm_queue,swpm_logs,swpm_tracking) - Saves default settings
- Schedules WP-Cron tasks (6 tasks)
- Sets up the setup wizard redirect (
swpm_activation_redirecttransient)
Quick Start (Setup Wizard)
When the plugin is activated for the first time, the Setup Wizard opens automatically and guides you through the configuration process step by step.
Wizard Steps
- Provider Selection — Choose your mail provider from 18 providers
- Credentials — Enter API key or SMTP credentials
- Test Send — Send a test email to verify the connection
- Complete —
swpm_setup_completeis marked, and you are redirected to the dashboard
Manual Configuration
If you skipped the wizard or want to change settings later:
- Go to the SWPMail > Mail Settings page
- Select your mail service provider (e.g., SMTP, Mailgun, SendGrid)
- Enter the required information (API key, host, port, etc.)
- Click the Send Test Email button to verify the connection
- Add the
[swpmail_subscribe]shortcode to any page on your site - Choose which events will send emails from the SWPMail > Triggers page
Supported Mail Services (18 Providers)
SMTP-Based Providers
| # | Service | Method | Description |
|---|---|---|---|
| 1 | PHP Mail | PHP mail() |
Server default, no configuration required |
| 2 | Generic SMTP | PHPMailer / SMTP | Any SMTP server |
| 3 | Gmail | SMTP / OAuth 2.0 | Google account, App Password or OAuth |
| 4 | Outlook | SMTP / OAuth 2.0 | Microsoft 365 / Outlook.com |
| 5 | Zoho Mail | SMTP | Zoho Mail account |
HTTP API-Based Providers
| # | Service | Method | Free Quota |
|---|---|---|---|
| 6 | Mailgun | HTTP API | 100/day |
| 7 | SendGrid | HTTP API | 100/day (trial only) |
| 8 | Postmark | HTTP API | 100/month (test) |
| 9 | Brevo (Sendinblue) | HTTP API | 300/day |
| 10 | Amazon SES | HTTP API (SDK-less) | 3,000/month |
| 11 | Resend | HTTP API | 3,000/month |
| 12 | Elastic Email | HTTP API | 100/day |
| 13 | Mailjet | HTTP API | 200/day |
| 14 | MailerSend | HTTP API | 3,000/month |
| 15 | SendLayer | HTTP API | Paid only |
| 16 | SMTP.com | HTTP API | Paid only |
| 17 | SMTP2GO | HTTP API | 1,000/month |
| 18 | SparkPost | HTTP API | 500/month (test) |
Provider Configuration
Required information for each provider:
- PHP Mail: No configuration required (server default)
- Generic SMTP: Host, Port, Username, Password, Encryption (TLS/SSL/None)
- Gmail: Email, App Password or OAuth 2.0 (Client ID + Secret)
- Outlook: Email, Password or OAuth 2.0 (Client ID + Secret + Tenant)
- Zoho Mail: Email, App Password
- Mailgun: API Key, Domain, Region (US/EU)
- SendGrid: API Key
- Postmark: Server Token, Message Stream
- Brevo: API Key
- Amazon SES: Access Key, Secret Key, Region
- Resend: API Key
- Elastic Email: API Key
- Mailjet: API Key, Secret Key
- MailerSend: API Token
- SendLayer: API Key
- SMTP.com: API Key, Sender ID
- SMTP2GO: API Key
- SparkPost: API Key
- Zoho Mail: Email, App Password
Note: All API keys and passwords are encrypted with AES-256-CBC + HMAC-SHA256 and stored in the database. WordPress salt keys are used as the encryption key.
wp_mail Override System
When the plugin is active and a provider is configured, all wp_mail() calls in the system are automatically sent through the selected provider.
How It Works
- SMTP Providers: PHPMailer is configured via the
phpmailer_inithook - API Providers: Sending is fully taken over via the
pre_wp_mailfilter
From Address Priority Order
1. From Email / Name in SWPMail settings (highest priority)
2. wp_mail_from / wp_mail_from_name filters
3. WordPress default (wordpress@domain.com)
Disabling the Override
// Skip the override for a specific wp_mail call
add_filter( 'swpm_skip_override', '__return_true' );
wp_mail( $to, $subject, $body );
remove_filter( 'swpm_skip_override', '__return_true' );
Or disable the SWPMail > Settings > Override wp_mail option from the admin panel.
Smart Routing
SWPMail allows you to send different emails through different providers using the conditional email routing engine.
Rule Structure
Each routing rule consists of the following components:
| Component | Description |
|---|---|
| Name | Descriptive name for the rule |
| Priority | Lower number = evaluated first |
| Provider | Which provider to use for emails matching this rule |
| Conditions | Matching criteria (AND logic) |
Condition Fields
| Field | Description |
|---|---|
to |
Recipient email address |
subject |
Email subject |
from |
Sender address |
header |
Any header value |
source |
Source that triggered the email (plugin, etc.) |
Condition Operators
contains, not_contains, equals, not_equals, starts_with, ends_with, matches (regex)
Example Scenarios
Rule: "WooCommerce Orders via Postmark"
Condition: subject contains "Order"
Provider: postmark
Priority: 10
Rule: "Bulk Mail via SendGrid"
Condition: source equals "swpmail_trigger"
Provider: sendgrid
Priority: 20
Emails that don't match any rule are sent through the default (primary) provider.
Rules are stored in JSON format in the swpm_routing_rules option and managed from the SWPMail > Smart Routing page.
Connection Management & Failover
SWPMail provides an automatic failover mechanism to prevent service interruptions when the primary provider goes down.
How It Works
Email Sending
↓
Primary Provider → Successful? → Sent ✓
↓ (Failed)
Failure Counter +1
↓
Threshold Exceeded? (3 consecutive errors)
YES → Switch to Backup Provider → Send
NO → Retry
↓
Health Check after 5 minutes → Return to primary if healthy
Features
- Automatic Failover: Backup provider activates after 3 consecutive failures
- Health Check: Primary provider status monitored via lightweight test sends
- Cooldown Period: Health checks performed at 5-minute intervals
- AJAX Status:
swpm_health_check,swpm_get_connection_statusendpoints
OAuth 2.0 Integration
OAuth 2.0 authorization flow is supported for Gmail and Outlook providers.
Supported Services
| Service | Auth Endpoint | Token Endpoint |
|---|---|---|
| Gmail | accounts.google.com/o/oauth2/v2/auth |
oauth2.googleapis.com/token |
| Outlook | login.microsoftonline.com/common/oauth2/v2.0/auth |
login.microsoftonline.com/common/oauth2/v2.0/token |
OAuth Flow
- Click the Authorize button in the admin panel
- Sign in with your Google/Microsoft account and grant permissions
- Token is received via the callback URL and stored encrypted
- Automatic refresh when the token expires
AJAX Endpoints
swpm_oauth_start— Start OAuth flowswpm_oauth_callback— Callback processingswpm_oauth_disconnect— Disconnect OAuth
Note: If OAuth is not configured, SMTP connection with App Password is used for Gmail and standard password for Outlook.
Subscription System
Subscription Flow
Form Submission → AJAX (nonce + rate limit + honeypot + GDPR)
↓
Double Opt-in Enabled?
YES → status: pending → Confirmation email → Token verification → confirmed
NO → status: confirmed → Welcome email
↓
Frequency: instant / daily / weekly
Subscription Statuses
| Status | Description |
|---|---|
pending |
Awaiting confirmation (double opt-in) |
confirmed |
Active subscriber |
unsubscribed |
Unsubscribed |
bounced |
Email bounced |
Subscription Frequencies
| Frequency | Description |
|---|---|
instant |
Immediately (on every new post) |
daily |
Daily digest (configurable hour) |
weekly |
Weekly digest (configurable day) |
Shortcode Usage
Basic Usage
[swpmail_subscribe]
All Parameters
| Parameter | Default | Description |
|---|---|---|
title |
From settings | Form title |
show_name |
false |
Show name field |
frequency |
From settings | Show frequency selection (true/false) |
frequency_default |
instant |
Default frequency |
style |
default |
Form style (default/minimal) |
button_text |
"Subscribe" | Button text |
Examples
<!-- With name field -->
[swpmail_subscribe show_name="true" title="Subscribe to Newsletter"]
<!-- With specific frequency -->
[swpmail_subscribe frequency_default="weekly" frequency="false"]
<!-- Minimal style -->
[swpmail_subscribe style="minimal" button_text="Join"]
HTML Email Templates
Built-in Templates
| Template ID | Usage | Variables |
|---|---|---|
base |
Base layout for all emails | {{content}} |
confirm-subscription |
Double opt-in email | {{confirm_url}}, {{subscriber_name}} |
welcome |
Welcome email | {{subscriber_name}}, {{site_name}} |
new-post |
New post notification | {{post_title}}, {{post_url}}, {{post_excerpt}}, {{post_thumbnail}}, {{author_name}} |
new-user |
New user registration notification | {{username}}, {{login_url}} |
new-comment |
New comment notification | {{commenter_name}}, {{comment_excerpt}}, {{post_title}} |
user-login |
User login notification | {{username}}, {{ip_address}}, {{login_time}} |
password-reset |
Password reset notification | {{username}}, {{reset_link}} |
digest-daily |
Daily digest | {{post_list}}, {{date}} |
digest-weekly |
Weekly digest | {{post_list}}, {{week_start}}, {{week_end}} |
Global Variables (Available in All Templates)
| Variable | Description |
|---|---|
{{site_name}} |
Site name |
{{site_url}} |
Site URL |
{{site_logo}} |
Site logo URL |
{{year}} |
Current year |
{{from_name}} |
Sender name |
{{privacy_url}} |
Privacy policy URL |
{{unsubscribe_text}} |
"Unsubscribe" text |
{{visit_site_text}} |
"Visit Site" text |
Template Loading Priority
1. swpm_template_path filter (highest)
2. Theme: /swpmail/templates/{id}.html
3. Database (saved via admin editor)
4. Plugin: /templates/default/{id}.html (lowest)
Theme Override
You can override templates in your theme folder:
your-theme/
└── swpmail/
└── templates/
├── new-post.html
└── welcome.html
Trigger System
Built-in Triggers
| Trigger | WordPress Hook | Template |
|---|---|---|
| New Post Published | transition_post_status |
new-post |
| New User Registered | user_register |
new-user |
| User Login | wp_login |
user-login |
| New Comment | comment_post |
new-comment |
| Password Reset | retrieve_password |
password-reset |
Creating Custom Triggers
Third-party plugins or theme developers can add their own triggers:
class My_Custom_Trigger extends SWPM_Trigger_Base {
public function get_key(): string { return 'my_custom_event'; }
public function get_label(): string { return 'My Custom Event'; }
public function get_hook(): string { return 'my_plugin_event_fired'; }
public function get_template_id(): string { return 'my-custom-template'; }
public function get_subject( array $data ): string {
return 'Custom event: ' . $data['title'];
}
public function get_recipients( array $data ): array {
return swpm( 'subscriber' )->get_confirmed_by_frequency( 'instant' );
}
protected function prepare_data( ...$args ): array {
return [
'title' => $args[0],
'content' => $args[1] ?? '',
];
}
}
// Register the trigger
add_action( 'swpm_register_triggers', function( SWPM_Trigger_Manager $manager ) {
$manager->register( new My_Custom_Trigger() );
} );
Trigger Control Filters
// Conditionally stop a specific trigger
add_filter( 'swpm_trigger_should_send_new_post', function( $proceed, $data ) {
// Skip posts published from draft (custom logic)
if ( $data['post_id'] && get_post_meta( $data['post_id'], '_skip_notification', true ) ) {
return false;
}
return $proceed;
}, 10, 2 );
// Extend triggerable post types
add_filter( 'swpm_trigger_new_post_types', function( $types ) {
$types[] = 'product'; // Also trigger for WooCommerce products
return $types;
} );
Queue & Cron System
Queue Operation
- Emails are added to the
swpm_queuetable - Processed by WP-Cron every 5 minutes
- Failed sends are retried with a maximum of 3 attempts
- Items stuck in "sending" status for more than 10 minutes are automatically reset
Scheduled Tasks
| Task | Interval | Description |
|---|---|---|
swpm_process_queue |
5 min | Queue processing (batch: 50 items) |
swpm_send_daily_digest |
Daily | Daily digest sending (default: 09:00) |
swpm_send_weekly_digest |
Weekly | Weekly digest sending (default: Monday) |
swpm_cleanup_logs |
Daily | Clean up old log records |
swpm_cleanup_queue |
Daily | Clean up sent/failed queue items |
swpm_cleanup_tracking |
Daily | Clean up old tracking data |
Configuration Options
swpm_daily_send_hour— Hour for daily digest sending (default: 9)swpm_weekly_send_day— Day for weekly digest sending (default: monday)- Cron tasks are automatically rescheduled when settings change
Queue Settings
// Customize batch size (for shared hosting)
add_filter( 'swpm_queue_batch_size', fn() => 10 );
REST API
Namespace: swpmail/v1
Endpoints
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/swpmail/v1/subscribe |
Public | Create new subscriber |
GET |
/swpmail/v1/subscribers |
Admin | Subscriber list (paged) |
DELETE |
/swpmail/v1/subscribers/{id} |
Admin | Delete subscriber |
Usage Examples
New Subscriber:
curl -X POST https://site.com/wp-json/swpmail/v1/subscribe \
-H "Content-Type: application/json" \
-d '{"email": "example@email.com", "name": "Name", "frequency": "instant"}'
Subscriber List (Admin):
curl https://site.com/wp-json/swpmail/v1/subscribers \
-H "X-WP-Nonce: {nonce}" \
--cookie "wordpress_logged_in_xxx=..."
Response Formats
Successful Subscription (201):
{
"message": "Subscription successful.",
"id": 42
}
Error (422):
{
"message": "This email is already subscribed."
}
Email Tracking & Analytics
Email Tracking System
SWPMail automatically adds tracking mechanisms to sent HTML emails:
| Feature | Method | Description |
|---|---|---|
| Open Tracking | 1×1 invisible pixel | Sends request to swpm_open endpoint when email opened |
| Click Tracking | Link proxy redirect | Links are rewritten through swpm_click |
- Tracking data is stored in the
swpm_trackingtable with hash, queue_id, IP, and user agent information - Rewrite rules are registered in the
inithook (priority 5)
Analytics Dashboard
Metrics displayed on the SWPMail > Dashboard page:
- Total Opens / Unique Opens counts
- Total Clicks / Unique Clicks counts
- Open Rate and Click Rate
- 30-day retrospective analysis (configurable)
Alarm System
5 different alarm channels are supported to receive instant notifications when sending errors occur.
Alarm Channels
| Channel | Key | Method | Configuration |
|---|---|---|---|
| Slack | slack |
Webhook | Incoming Webhook URL |
| Discord | discord |
Webhook | Discord Webhook URL |
| Microsoft Teams | teams |
Webhook | Teams Incoming Webhook URL |
| Twilio SMS | twilio |
REST API | Account SID, Auth Token, Phone |
| Custom | custom |
HTTP POST | Target URL, Payload format |
Triggering
- Notifications are sent to active alarm channels when the
swpm_mail_failedhook fires - Each channel is configured and can be tested from the SWPMail > Alarms page
- AJAX endpoint:
swpm_test_alarm_channel
DNS Checker (SPF / DKIM / DMARC)
Verifying domain DNS records is critical for improving email deliverability.
Verified Records
| Record | Description |
|---|---|
| SPF | Specifies which servers can send mail on behalf of the domain |
| DKIM | Ensures the authenticity of the email signature |
| DMARC | Defines what to do when SPF/DKIM fails |
Features
- Verification using the
dns_get_record()PHP function - Automatically runs when mail settings are saved
- 15-minute transient caching (
swpm_dns_+ md5(domain)) - Analysis based on deliverability best practices
- Accessible from the SWPMail > DNS Checker page
WP-CLI Commands
SWPMail offers comprehensive CLI commands under the wp swpmail namespace.
General Commands
# General status and health report
wp swpmail status
# Send test email
wp swpmail test --to=example@email.com
# Reset all plugin settings
wp swpmail reset --yes
Provider Management
# Active provider info
wp swpmail provider
# List available providers
wp swpmail provider list
# Switch provider
wp swpmail provider switch sendgrid
Queue Management
# List queue items
wp swpmail queue list --status=pending --limit=20
# Process queue
wp swpmail queue process --limit=50
# Flush sent/failed items
wp swpmail queue flush --status=sent --older-than="7 days"
Logs & Diagnostics
# Show recent log records
wp swpmail log --level=error --limit=50
# Database diagnostics
wp swpmail db diagnose
# Database repair (dry run)
wp swpmail db repair --dry-run
# Conflict detection
wp swpmail conflicts
Cron & Subscriber Management
# List scheduled cron events
wp swpmail cron list
# Manually trigger cron event
wp swpmail cron run swpm_process_queue
# List subscribers
wp swpmail subscriber list --status=confirmed --limit=100
Admin Panel
Menu Structure
SWPMail (dashicon: email)
├── Dashboard → Statistics, analytics, queue status, recent logs
├── Subscribers → Subscriber management with WP_List_Table (search/filter/delete)
├── Email Templates → CodeMirror-based HTML template editor
├── Triggers → Enable/disable triggers, create custom triggers
├── Mail Settings → 18 provider selection and configuration, test sending
├── DNS Checker → SPF, DKIM, DMARC record verification
├── Smart Routing → Rule-based conditional email routing
├── Email Logs → Detailed sending records, filtering
├── Alarms → Slack, Discord, Teams, Twilio, Custom alarm configuration
├── Settings → General settings, GDPR, subscription, override settings
└── Tools → Database repair, conflict detection, system info
Dashboard
- Total / confirmed / pending / unsubscribed subscriber counts
- Active provider info and failover status
- Queue status (pending/sent/failed)
- Open / Click analytics metrics
- Last cron execution time
- DNS verification status
- Last 10 log records
Subscriber Management
- Search: By email or name
- Filter: Status-based (pending, confirmed, unsubscribed, bounced)
- Sort: Email, status, registration date
- Bulk Action: Bulk delete selected subscribers
- Single Delete: Via row action
Template Editor
- CodeMirror HTML editor
- Available variables list
- Save / Reset (restore to default)
- AJAX-based saving
Security
| Topic | Method |
|---|---|
| CSRF | wp_create_nonce() + check_ajax_referer() / wp_verify_nonce() |
| XSS | esc_html(), esc_attr(), esc_url(), wp_kses_post() |
| SQL Injection | $wpdb->prepare() — in all queries |
| Direct File Access | if ( ! defined( 'ABSPATH' ) ) exit; in every PHP file |
| Permission Check | current_user_can( 'manage_options' ) in all admin operations |
| Rate Limiting | Transient API with 5 requests per IP / 10 minutes |
| Bot Protection | Hidden honeypot field (swpm_website) |
| Token Security | random_bytes(32) + bin2hex() (64 characters) |
| API Key Encryption | AES-256-CBC + HMAC-SHA256 + WordPress salt |
| IP Validation | FILTER_VALIDATE_IP (IPv4 + IPv6) |
| OAuth Token Storage | Encrypted token storage, automatic refresh |
| Conflict Detection | wp_mail override analysis via ReflectionFunction |
| Origin/Referer | Origin/referer validation in REST API |
GDPR & Legal Compliance
- Double Opt-in: Enabled by default
- Unsubscribe: Unsubscribe link in every email
- GDPR Consent Checkbox: Personal data collection consent (with privacy policy link)
- WordPress Privacy API: Data export and deletion integration
- IP Logging: IP address recorded for KVKK/GDPR compliance
- Log Cleanup: Logs older than 30 days are automatically cleaned up (configurable)
- Token Expiration: Confirmation tokens expire after 48 hours (configurable)
WordPress Privacy API
The plugin provides full integration with WordPress Privacy API:
- Data Export: Tools > Export Personal Data → Subscriber data is included
- Data Deletion: Tools > Erase Personal Data → Subscriber records are removed
Multilingual Support (i18n)
- Text domain:
swpmail - Language files:
languages/folder - Built-in languages (9):
| Language | Locale |
|---|---|
| English | default |
| Türkçe | tr_TR |
| Deutsch | de_DE |
| Español | es_ES |
| Français | fr_FR |
| Italiano | it_IT |
| 日本語 | ja |
| Nederlands | nl_NL |
| Português (Brasil) | pt_BR |
Adding Translations
- Open the
languages/swpmail.potfile with Poedit or a similar tool - Create your translations
- Save the
.poand.mofiles to thelanguages/folder - File name format:
swpmail-{locale}.po(e.g.,swpmail-de_DE.po)
Theme Developer Guide
Shortcode Template Override
// Load subscribe-form.php template from theme folder
add_filter( 'swpm_subscribe_template', function( $path, $atts ) {
$theme_path = get_stylesheet_directory() . '/swpmail/subscribe-form.php';
return file_exists( $theme_path ) ? $theme_path : $path;
}, 10, 2 );
Email Template Override
Copy email templates as HTML files to the your-theme/swpmail/templates/ directory. Templates in this directory are loaded before the plugin's default templates.
Service Container Access
// Global helper function
$mailer = swpm( 'mailer' );
$subscriber = swpm( 'subscriber' );
$provider = swpm( 'provider' );
$queue = swpm( 'queue' );
$engine = swpm( 'template_engine' );
$router = swpm( 'router' );
$tracker = swpm( 'tracker' );
$analytics = swpm( 'analytics' );
$connections = swpm( 'connections_manager' );
// Or static access
$mailer = SWPMail::get( 'mailer' );
Hooks Reference (Developer API)
Action Hooks
| Hook | Parameters | Description |
|---|---|---|
swpm_subscriber_created |
$id, $email, $frequency |
When a new subscriber is created |
swpm_subscriber_confirmed |
$id, $email |
When a subscriber is confirmed |
swpm_subscriber_unsubscribed |
$id, $email |
When a subscription is cancelled |
swpm_register_triggers |
$trigger_manager |
Custom trigger registration point |
swpm_mail_sent |
$result, $recipient, $mail_data |
When an email is sent successfully |
swpm_mail_failed |
$result, $recipient, $mail_data |
When sending fails (triggers alarms) |
swpm_auth_failure |
$provider_key |
API authentication failure |
swpm_smtp_exception |
$exception, $friendly_msg |
When an SMTP error occurs |
Filter Hooks
| Hook | Returns | Description |
|---|---|---|
swpm_provider_registry |
array |
Add new provider to the provider list |
swpm_subscribe_template |
string |
Change shortcode form template path |
swpm_template_path |
string |
Change email template path |
swpm_trigger_should_send_{key} |
bool |
Stop/allow trigger sending |
swpm_trigger_new_post_types |
array |
Extend triggerable post types |
swpm_pre_send |
bool |
Pre-send filter |
swpm_mail_headers |
array |
Modify mail headers |
swpm_skip_override |
bool |
Skip wp_mail override |
swpm_queue_batch_size |
int |
Queue batch size (default: 50) |
swpm_api_timeout |
int |
HTTP request timeout (default: 20s) |
swpm_confirm_token_expiry |
int |
Token expiry (default: 172800s / 48 hours) |
swpm_blocked_email_domains |
array |
Blocked email domains |
swpm_log_retention_days |
int |
Log retention period (default: 30 days) |
Usage Examples
// 1. Add custom provider
add_filter( 'swpm_provider_registry', function( $registry ) {
$registry['sparkpost'] = 'My_SparkPost_Provider';
return $registry;
} );
// 2. Stop sending to specific recipient
add_filter( 'swpm_pre_send', function( $send, $recipient, $mail_data ) {
if ( 'skip@example.com' === $recipient ) {
return false;
}
return $send;
}, 10, 3 );
// 3. Increase API timeout
add_filter( 'swpm_api_timeout', fn() => 30 );
// 4. Add Reply-To header
add_filter( 'swpm_mail_headers', function( $headers ) {
$headers[] = 'Reply-To: support@example.com';
return $headers;
} );
// 5. Reduce token expiry to 24 hours
add_filter( 'swpm_confirm_token_expiry', fn() => DAY_IN_SECONDS );
// 6. Notify Slack about sending errors
add_action( 'swpm_mail_failed', function( $result, $recipient ) {
wp_remote_post( SLACK_WEBHOOK_URL, [
'body' => wp_json_encode( [
'text' => "Mail failed: {$recipient} — " . $result->get_error_message(),
] ),
] );
}, 10, 2 );
File Structure
swpmail/
├── swpmail.php ← Main file (header + bootstrap)
├── readme.txt ← WordPress.org readme
├── README.md ← Detailed project documentation
├── uninstall.php This README is longer than the copy stored here. Read the rest on GitHub →