Title: SendForce Mail SMTP Relay — Free WP SMTP &amp; Email API Plugin for Amazon SES, SendGrid, Mailgun, Brevo, Postmark, Zoho ZeptoMail &amp; Gmail
Author: Shipon Karmakar
Published: <strong>April 30, 2026</strong>
Last modified: May 25, 2026

---

Search plugins

![](https://ps.w.org/sendforce-mail-relay/assets/banner-772x250.jpg?rev=3525954)

![](https://ps.w.org/sendforce-mail-relay/assets/Icon-256x256.gif?rev=3519550)

# SendForce Mail SMTP Relay — Free WP SMTP & Email API Plugin for Amazon SES, SendGrid, Mailgun, Brevo, Postmark, Zoho ZeptoMail & Gmail

 By [Shipon Karmakar](https://profiles.wordpress.org/shiponkarmakar/)

[Download](https://downloads.wordpress.org/plugin/sendforce-mail-relay.1.0.31.zip)

 * [Details](https://vec.wordpress.org/plugins/sendforce-mail-relay/#description)
 * [Reviews](https://vec.wordpress.org/plugins/sendforce-mail-relay/#reviews)
 *  [Installation](https://vec.wordpress.org/plugins/sendforce-mail-relay/#installation)
 * [Development](https://vec.wordpress.org/plugins/sendforce-mail-relay/#developers)

 [Support](https://wordpress.org/support/plugin/sendforce-mail-relay/)

## Description

**SendForce Mail SMTP is a free, open-source WordPress SMTP plugin** that fixes 
the “WordPress emails not being delivered” problem in minutes. Send WooCommerce 
order emails, Contact Form 7 / WPForms / Gravity Forms submissions, password resets,
registration confirmations, and any other `wp_mail()` traffic through Amazon SES,
SendGrid, Mailgun, Brevo (Sendinblue), Postmark, Zoho ZeptoMail, Gmail API, Microsoft
365, or any standard SMTP server — with full email logging, queue, retry, and failure
alerts.

#### Why SendForce Mail SMTP

 * **100% Free, no premium upsell.** Every feature you see is included — no “pro
   version” lock screens, no email-volume cap, no provider unlock paywall. Compare
   with WP Mail SMTP, Easy WP SMTP, Post SMTP, or FluentSMTP and you’ll find SendForce’s
   free tier matches or beats their paid tiers.
 * **24+ providers, one plugin.** Built-in presets and HTTP API integrations for
   the most popular transactional email services — pick what fits your budget, deliverability
   needs, and region.
 * **Built-in debugging.** Live SMTP debug log on test email, raw API request/response
   capture in the email log, “Copy Debug Info” button for support tickets, and WP-
   CLI commands. Designed for developers and agencies who need to diagnose email
   problems fast.
 * **Multiple connections with automatic fallback.** Configure a primary connection(
   e.g. Amazon SES) plus a fallback (e.g. Mailgun). If the primary returns an error,
   the fallback takes over — no email lost.

#### Supported email providers

**HTTP API sending (recommended — faster and more reliable than SMTP):**

 * Amazon SES (AWS Simple Email Service)
 * SendGrid (by Twilio)
 * Mailgun (by Sinch)
 * Brevo (formerly Sendinblue)
 * SparkPost
 * Postmark
 * Zoho ZeptoMail
 * Microsoft 365 / Outlook (Microsoft Graph API)
 * Gmail / Google Workspace (Gmail API)
 * SMTP2GO
 * SMTP.com
 * Elastic Email
 * SocketLabs
 * Moosend
 * SendLayer
 * Mailjet
 * MailerSend
 * Mandrill (by Mailchimp)
 * Resend
 * Netcore Email API (formerly Pepipost)

**SMTP sending (works with any provider, including custom servers):**

 * Gmail / Google Workspace SMTP (smtp.gmail.com)
 * Microsoft 365 / Outlook SMTP (smtp.office365.com)
 * Yahoo Mail SMTP
 * Zoho Mail SMTP
 * Turbo SMTP
 * Any other SMTP server (host, port, username, password)

#### Features

 * **Multiple connections with automatic fallback** — configure a primary connection(
   e.g. Amazon SES) plus a fallback (e.g. Mailgun, SMTP, or PHP mail). If the primary
   returns an error, the fallback is attempted automatically. Both attempts are 
   logged so you have a full audit trail; recovered emails carry a “Recovered via
   fallback” badge in the log detail view.
 * **Smart Routing Rules** — send different emails through different connections
   based on rules you define. Match by recipient domain, recipient pattern (glob),
   sender email or domain, source plugin (auto-detected for WooCommerce, Contact
   Form 7, WPForms, Gravity Forms, Ninja Forms, Fluent Forms, Forminator, Easy Digital
   Downloads, MemberPress, LearnDash, MailPoet, BuddyPress, bbPress and more), subject
   contains, time of day, or weekday. Rules are evaluated top-down (first match 
   wins) and can target a single connection, a round-robin pool, or WordPress phpmail().
   Includes inline rule editor, master enable/disable toggle, “Test Routing” tool,
   and a “via rule:” badge on the Email Log so you can see exactly which rule fired
   for any send.
 * **One-click provider presets** — pre-filled host, port, encryption, and API endpoint
   for every supported provider. Just paste your API key or password.
 * **Email Log** — every outgoing email logged with status, recipient, subject, 
   headers, error message, and timestamp. Filter by status, search by keyword, filter
   by date range, export to CSV or JSON.
 * **Email Queue with retry** — queue mode prevents rate-limit errors and timeouts
   on bulk sends. Failed emails auto-retry on exponential backoff (5 min  15 min
   45 min).
 * **Email Test page** — send a test email with live SMTP debug log output. Diagnose
   connection problems instantly.
 * **Failure alerts** — push delivery failures to Telegram, Slack, Discord, Microsoft
   Teams, Google Chat, Pushover, or any custom webhook.
 * **Sender Identity override** — force every email to use a custom From name and
   From address site-wide.
 * **Conflict detection** — warns you if another SMTP plugin (WP Mail SMTP, FluentSMTP,
   Easy WP SMTP, Post SMTP, etc.) is active so you can deactivate it before things
   break.
 * **Encrypted credential storage** — SMTP passwords and API keys are encrypted 
   at rest using AES-256-CBC with WordPress security salts.
 * **WP-CLI commands** — `wp sendforce test`, `wp sendforce queue process`, `wp 
   sendforce log list`, `wp sendforce sysinfo`.
 * **Developer hooks** — `sendforce_before_send`, `sendforce_after_send`, `sendforce_log_entry`,`
   sendforce_api_request`, `sendforce_api_response` for extending the plugin without
   forking.
 * **`WP_DEBUG_LOG` integration** — optional mirroring of SMTP and API debug output
   to `debug.log`.
 * **Automatic log cleanup** — configurable retention period (default 30 days).
 * **Privacy-friendly** — optional disable of email-body logging for GDPR / privacy
   compliance.
 * **Multisite compatible.**

#### Works with all major WordPress plugins

SendForce Mail SMTP hooks into WordPress’s core `wp_mail()` function, so it works
with **every** plugin that sends email — including WooCommerce, Easy Digital Downloads,
Contact Form 7, WPForms, Gravity Forms, Ninja Forms, Fluent Forms, Forminator, MemberPress,
LearnDash, BuddyPress, bbPress, MailPoet (transactional), and any custom plugin 
or theme that uses `wp_mail()`.

### External Services

SendForce Mail Relay is an email-delivery plugin. It does NOT connect to any external
service automatically. A connection is made ONLY after you explicitly configure 
a provider and either (a) WordPress sends an outgoing email, or (b) you click “Send
Test Email”, or (c) you enable a notification channel and an email-failure alert
is dispatched.

For each configured email provider, the data sent on every send is the same set 
of fields WordPress would otherwise hand to the local mail() function: the recipient
address(es), CC, BCC, Reply-To, From name/address, subject, message body, headers,
and attachments. No additional telemetry or analytics is transmitted by this plugin.

For each configured notification channel (Telegram, Slack, Discord, Microsoft Teams,
Google Chat, Pushover, custom Webhook), the data sent is a short status message 
you compose in the plugin (default: failed-delivery summary or daily summary).

#### Email-delivery providers (configurable in Settings  Connections)

**SendGrid (by Twilio)**
 * Service: https://sendgrid.com * When data is sent: every
WordPress email when SendGrid is the active connection, plus on test-email click.*
Endpoint: https://api.sendgrid.com/v3/mail/send * Privacy Policy: https://www.twilio.
com/en-us/legal/privacy * Terms of Service: https://www.twilio.com/en-us/legal/tos

**Mailgun (by Sinch)**
 * Service: https://www.mailgun.com * When data is sent: 
same as above, but to Mailgun. * Endpoint: https://api.mailgun.net/v3/{domain}/messages(
US) or https://api.eu.mailgun.net/v3/{domain}/messages (EU). * Privacy Policy: https://
www.mailgun.com/legal/privacy-policy/ * Terms of Service: https://www.mailgun.com/
legal/terms/

**Amazon SES (AWS Simple Email Service)**
 * Service: https://aws.amazon.com/ses/*
When data is sent: same. * Endpoint: https://email.{region}.amazonaws.com/v2/email/
outbound-emails (region you select). * Privacy Policy: https://aws.amazon.com/privacy/*
Terms of Service: https://aws.amazon.com/service-terms/

**Brevo (formerly Sendinblue)**
 * Service: https://www.brevo.com * Endpoint: https://
api.brevo.com/v3/smtp/email * Privacy Policy: https://www.brevo.com/legal/privacypolicy/*
Terms of Service: https://www.brevo.com/legal/termsofuse/

**SparkPost**
 * Service: https://www.sparkpost.com * Endpoint: https://api.sparkpost.
com/api/v1/transmissions * Privacy Policy: https://www.sparkpost.com/policies/privacy/*
Terms of Service: https://www.sparkpost.com/policies/tou/

**Postmark**
 * Service: https://postmarkapp.com * Endpoint: https://api.postmarkapp.
com/email * Privacy Policy: https://postmarkapp.com/privacy-policy * Terms of Service:
https://postmarkapp.com/terms-of-service

**Elastic Email**
 * Service: https://elasticemail.com * Endpoint: https://api.elasticemail.
com/v4/emails * Privacy Policy: https://elasticemail.com/legal/privacy-policy * 
Terms of Service: https://elasticemail.com/legal/terms-of-use

**SMTP2GO**
 * Service: https://www.smtp2go.com * Endpoint: https://api.smtp2go.
com/v3/email/send * Privacy Policy: https://www.smtp2go.com/privacy/ * Terms of 
Service: https://www.smtp2go.com/terms/

**Netcore Email API (formerly Pepipost)**
 * Service: https://netcorecloud.com *
Endpoint: https://emailapi.netcorecloud.net/v5/mail/send * Privacy Policy: https://
netcorecloud.com/privacy-policy * Terms of Service: https://netcorecloud.com (request
the latest terms via the contact form on the homepage; Netcore does not publish 
a stable terms-of-use URL).

**SMTP.com**
 * Service: https://www.smtp.com * Endpoint: https://api.smtp.com/v4/
messages * Privacy Policy: https://www.smtp.com/policies/privacy-policy/ * Terms
of Service: https://www.smtp.com/legal/terms/

**SocketLabs**
 * Service: https://www.socketlabs.com * Endpoint: https://inject.
socketlabs.com/api/v1/email * Privacy Policy: https://www.socketlabs.com/legal/privacy-
policy/ * Terms of Service: https://www.socketlabs.com/legal/

**Moosend (by Sitecore)**
 * Service: https://moosend.com * Endpoint: https://api.
moosend.com/v3/ * Privacy Policy: https://moosend.com/privacy-policy/ * Terms of
Service: https://moosend.com/terms/

**SendLayer**
 * Service: https://sendlayer.com * Endpoint: https://console.sendlayer.
com/api/v1/email * Privacy Policy: https://www.sendlayer.com/privacy-policy/ * Terms
of Service: https://www.sendlayer.com/terms-of-service/

**Mailjet (by Sinch)**
 * Service: https://www.mailjet.com * Endpoint: https://api.
mailjet.com/v3.1/send * Privacy Policy: https://www.sinch.com/legal/privacy-notice/*
Terms of Service: https://www.sinch.com/legal/terms-of-service/

**MailerSend**
 * Service: https://www.mailersend.com * Endpoint: https://api.mailersend.
com/v1/email * Privacy Policy: https://www.mailersend.com/legal/privacy-policy *
Terms of Service: https://www.mailersend.com/legal/terms-of-use

**Mandrill (by Mailchimp)**
 * Service: https://mailchimp.com/developer/transactional/*
Endpoint: https://mandrillapp.com/api/1.0/messages/send.json * Privacy Policy: https://
mailchimp.com/legal/privacy/ * Terms of Service: https://mailchimp.com/legal/terms/

**Resend**
 * Service: https://resend.com * Endpoint: https://api.resend.com/emails*
Privacy Policy: https://resend.com/legal/privacy-policy * Terms of Service: https://
resend.com/legal/terms-of-service

**Zoho ZeptoMail**
 * Service: https://www.zoho.com/zeptomail/ * Endpoint: https://
api.zeptomail.com/v1.1/email * Privacy Policy: https://www.zoho.com/privacy.html*
Terms of Service: https://www.zoho.com/zeptomail/terms.html

**Microsoft 365 / Outlook (Microsoft Graph API and SMTP)**
 * Service: https://www.
microsoft.com/microsoft-365 * Endpoint (API): https://graph.microsoft.com/v1.0/users/{
user}/sendMail (OAuth token from https://login.microsoftonline.com/{tenant}/oauth2/
v2.0/token) * Endpoint (SMTP): smtp.office365.com:587 * Privacy Policy: https://
privacy.microsoft.com/en-US/privacystatement * Terms of Service: https://www.microsoft.
com/en-us/servicesagreement/

**Gmail / Google Workspace (Gmail API and SMTP)**
 * Service: https://workspace.
google.com * Endpoint (API): https://gmail.googleapis.com/gmail/v1/users/me/messages/
send (OAuth token from https://oauth2.googleapis.com/token) * Endpoint (SMTP): smtp.
gmail.com:587 * Privacy Policy: https://policies.google.com/privacy * Terms of Service:
https://policies.google.com/terms

#### Notification channels (configurable in Settings  Alerts)

These services are contacted ONLY when a notification channel is enabled AND a delivery
failure (or daily-summary) event triggers an alert. The data sent is the short status
text shown in the plugin’s alert preview.

**Telegram (Bot API)**
 * Service: https://telegram.org * When data is sent: when
a Telegram channel is enabled, a failed-delivery alert or daily-summary alert is
generated. * Endpoint: https://api.telegram.org/bot{token}/sendMessage * Privacy
Policy: https://telegram.org/privacy * Terms of Service: https://telegram.org/tos

**Pushover**
 * Service: https://pushover.net * Endpoint: https://api.pushover.net/
1/messages.json * Privacy Policy: https://pushover.net/privacy * Terms of Service:
https://pushover.net/terms

**Slack (Incoming Webhooks)**
 * Service: https://slack.com * Endpoint: the webhook
URL you paste (https://hooks.slack.com/services/…). * Privacy Policy: https://slack.
com/trust/privacy/privacy-policy * Terms of Service: https://slack.com/legal

**Discord (Webhooks)**
 * Service: https://discord.com * Endpoint: the webhook URL
you paste (https://discord.com/api/webhooks/…). * Privacy Policy: https://discord.
com/privacy * Terms of Service: https://discord.com/terms

**Microsoft Teams (Incoming Webhooks)**
 * Service: https://www.microsoft.com/microsoft-
teams/ * Endpoint: the Teams webhook URL you paste. * Privacy Policy: https://privacy.
microsoft.com/en-US/privacystatement * Terms of Service: https://www.microsoft.com/
en-us/servicesagreement/

**Google Chat (Incoming Webhooks)**
 * Service: https://chat.google.com * Endpoint:
the Google Chat webhook URL you paste. * Privacy Policy: https://policies.google.
com/privacy * Terms of Service: https://workspace.google.com/terms/premier_terms.
html

**Custom Webhook**
 * When data is sent: when a custom Webhook channel is enabled
and an alert is generated, a JSON payload is POSTed to the URL you paste. * Endpoint:
the URL you paste. * Privacy Policy / Terms: governed by the operator of the URL
you provide.

#### Bundled third-party libraries (no network call)

**Chart.js (https://www.chartjs.org)** — bundled locally at assets/js/chart.umd.
min.js (v4.5.0). Used to render the email-stats chart on the dashboard. Loaded entirely
from your own server; no CDN call is made.

### Privacy Policy

SendForce Mail Relay stores the following data in your WordPress database:

 * **Email logs** (if logging is enabled): recipient email address, subject, headers,
   email body (optional), sent status, error messages, and timestamps.
 * **Email queue** (if queue is enabled): same data as above, plus retry attempt
   count and next retry time.
 * **Plugin settings**: your SMTP host, port, username, and encrypted password or
   API key.

Email body logging can be disabled in **Settings > Queue & Logging**. Log entries
are automatically deleted after the configured retention period (default: 30 days).
All data is deleted when the plugin is uninstalled.

We recommend adding a note to your site’s privacy policy if you log email content,
informing users that outgoing email metadata may be stored.

## Screenshots

 * [[
 * Modern dashboard with connection status, email statistics, and 7-day send chart.
 * [[
 * Settings page with visual provider grid and SMTP/API tab switcher.
 * [[
 * Email Log with status filters, keyword search, and date range filtering.
 * [[
 * Email Test page with live SMTP debug log output.
 * [[
 * Email Queue management with retry statistics.
 * [[

## Installation

 1. Upload the `sendforce-mail-relay` folder to the `/wp-content/plugins/` directory,
    or install directly through the WordPress plugin installer.
 2. Activate the plugin through the **Plugins** menu in WordPress.
 3. Go to **SendForce Mail Relay > Settings** to configure your SMTP server or API 
    credentials.
 4. Select your email provider from the provider grid.
 5. Enter your credentials and click **Save Settings**.
 6. Go to **SendForce Mail Relay > Email Test** and send a test email to verify your
    configuration.

## FAQ

### Do I need an SMTP server or API account?

Yes. You need access to an SMTP server or a transactional email provider account.
Most providers (Gmail, Outlook, etc.) offer SMTP access. Transactional services 
like SendGrid, Mailgun, or Amazon SES offer both SMTP and HTTP API access.

### Is my SMTP password or API key stored securely?

Yes. All credentials are encrypted using AES-256-CBC encryption with a key derived
from your WordPress security salts before being stored in the database.

### What does the email queue do?

When enabled, emails are stored in a database queue instead of being sent immediately.
A WP-Cron job processes the queue every 5 minutes, sending emails in batches. Failed
emails are retried with exponential backoff (5 min  15 min  45 min).

### Will SendForce Mail Relay send ALL WordPress emails including WooCommerce?

Yes. SendForce Mail Relay hooks into WordPress’s `phpmailer_init` action (SMTP mode)
or `pre_wp_mail` filter (API mode). Since every plugin — including WooCommerce, 
contact form plugins, and membership plugins — sends email via WordPress’s `wp_mail()`
function, SendForce Mail Relay will handle 100% of outgoing emails.

### Will this plugin conflict with other SMTP plugins?

You should only use one SMTP plugin at a time. Please deactivate any other SMTP 
or email plugins (FluentSMTP, WP Mail SMTP, etc.) before activating SendForce Mail
Relay.

### What data is logged?

By default, SendForce Mail Relay logs: recipient email, subject, headers, status(
sent/failed), error message if any, and timestamp. Email body logging is optional
and can be disabled in Settings > Queue & Logging for privacy compliance.

### What happens to my data when I uninstall the plugin?

All plugin data (database tables, settings, and scheduled events) is completely 
removed when you delete the plugin through the WordPress admin.

### Does this plugin track me or phone home?

No. SendForce Mail Relay does not collect any data, make any analytics calls, or
communicate with any external server except when sending emails through your configured
provider.

## Reviews

![](https://secure.gravatar.com/avatar/247026693fa0ebfa5950303219c9b3865f4c133dfa2114c26a7fd228a85945d3?
s=60&d=retro&r=g)

### 󠀁[Finally, No More Spam Folder Issues with PHP Mail!](https://wordpress.org/support/topic/finally-no-more-spam-folder-issues-with-php-mail/)󠁿

 [Wyarej Ali](https://profiles.wordpress.org/wyarejali/) May 1, 2026 1 reply

As a freelance web developer working with a marketing agency, I need to set up SMTP
for every website I build. However, my clients aren’t always ready to provide SMTP
credentials, which forces me to fall back on PHP mail — and that almost always ends
up sending emails straight to the spam folder. This plugin completely solved that
problem. I can now use PHP Mail instead, and it works perfectly. Honestly, this 
is a game-changer for my workflow.

![](https://secure.gravatar.com/avatar/a07c9ece6f39869d04a969625275698d046f1388760c88ea56c70ba1f473aa23?
s=60&d=retro&r=g)

### 󠀁[Its very easy and helpful plugin for SMTP mail for WordPress](https://wordpress.org/support/topic/its-very-easy-and-helpful-plugin-for-smtp-mail-for-wordpress/)󠁿

 [adisweden](https://profiles.wordpress.org/adisweden/) May 1, 2026 1 reply

Its very easy and helpful plugin for SMTP mail for WordPress. I love this plugin
and its really awesome plugin.

 [ Read all 2 reviews ](https://wordpress.org/support/plugin/sendforce-mail-relay/reviews/)

## Contributors & Developers

“SendForce Mail SMTP Relay — Free WP SMTP & Email API Plugin for Amazon SES, SendGrid,
Mailgun, Brevo, Postmark, Zoho ZeptoMail & Gmail” is open source software. The following
people have contributed to this plugin.

Contributors

 *   [ Shipon Karmakar ](https://profiles.wordpress.org/shiponkarmakar/)

[Translate “SendForce Mail SMTP Relay — Free WP SMTP & Email API Plugin for Amazon SES, SendGrid, Mailgun, Brevo, Postmark, Zoho ZeptoMail & Gmail” into your language.](https://translate.wordpress.org/projects/wp-plugins/sendforce-mail-relay)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/sendforce-mail-relay/),
check out the [SVN repository](https://plugins.svn.wordpress.org/sendforce-mail-relay/),
or subscribe to the [development log](https://plugins.trac.wordpress.org/log/sendforce-mail-relay/)
by [RSS](https://plugins.trac.wordpress.org/log/sendforce-mail-relay/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

For the **complete** release history with full detail on every change, see [CHANGELOG.md](https://plugins.svn.wordpress.org/sendforce-mail-relay/trunk/CHANGELOG.md)(
also bundled with the plugin) or open the **What’s New** tab inside SendForce in
your WordPress admin. The section below is condensed to fit within WordPress.org’s
5,000-word changelog limit.

#### 1.0.31

 * Fix: **Email Log “Connection” filter was dropped when paginating or exporting**(
   regression introduced with the new dropdown in 1.0.30). Picking a connection,
   then clicking page 2 or “Export CSV/JSON”, silently reset the filter and returned
   all providers. Both the pagination base URL and the export URL now preserve the
   active provider value, so paging through SendGrid-only results stays SendGrid-
   only and “Export CSV” of a filtered view exports just the filtered rows.
 * Polish: Accessibility — icon-only **View** button on the Email Log row and the**
   Retry** / **Delete** buttons on the Queue row now expose an `aria-label` so screen
   readers announce them correctly (was relying on `title` alone, which most assistive
   tech ignores).
 * Polish: Bulk action counter on the Email Log (“X item(s)”) now uses proper plural
   forms via `_n()`, so non-English locales can translate the singular and plural
   cases separately instead of inheriting the awkward English “(s)” suffix.
 * Polish: Settings  Developer Debug toggle label changed from “Mirror SMTP & API
   debug output” to “Mirror SMTP and API debug output” (a literal `&` in a translation
   string is a portability gotcha for some PO editors).
 * Polish: Alerts tab — added `viewBox` (camelCase) to the SVG `wp_kses` whitelist
   alongside the existing lowercase `viewbox`, so channel-logo SVGs render correctly
   regardless of which casing the source file uses.
 * Internal: Renamed `$current_user` to `$sendforce_current_user` in the Email Test
   template for prefix consistency with the rest of the file (avoids accidentally
   shadowing WP’s globally-scoped `$current_user` in deeply included contexts).

#### 1.0.30

 * New: **Filter Email Log by connection.** A new “Connection” dropdown in the Email
   Log filter bar lets you narrow the table down to emails sent through a specific
   provider (Amazon SES, SendGrid, Microsoft 365, etc.). Useful when you run several
   connections side-by-side and want to audit just one — e.g. “show me everything
   WooCommerce sent via SendGrid this week”. Options are populated from connections
   that actually have log entries (no empty dropdown choices). Existing log rows
   from before 1.0.30 don’t carry a provider value and stay visible under the “All
   connections” default.
 * New: **“Copy diagnostic snapshot” button** on the Email Log detail modal. Bundles
   the log ID, timestamp, status, error, headers, attachments, and the (already-
   redacted) raw API request/response into one clipboard-friendly text block — pre-
   formatted for pasting straight into a support ticket. Plugin / WordPress / PHP
   versions are included automatically. No more copy-paste-merge of six different
   fields when reporting an issue.
 * Internal: Added `provider` column to `wp_sendforce_logs` (varchar(50), indexed).
   Populated automatically going forward from the captured debug payload (when available)
   or the active connection’s configured provider. Existing rows are not back-filled;
   only new log entries get the column populated. dbDelta handles the schema migration
   on plugin upgrade.

#### 1.0.29

 * Fix: **Stray gray “pill” elements rendering on the What’s New tab** (introduced
   in 1.0.28). The changelog accordion’s markdown-to-HTML converter wrapped backtick-
   delimited text in `<code>` tags but didn’t escape the inner content first — so
   when a bullet contained literal `<tag>` text inside backticks (very common in
   technical changelogs), the browser interpreted the embedded text as a real HTML
   tag and produced floating empty `<code>` elements that rendered as gray pills
   against the page background. Fix: `esc_html()` the raw line before applying the
   markdown transformations. The two regex rules (`**bold**`  `<strong>` and backtick`
   <code>`) now run on already-escaped text, guaranteeing balanced tags and no HTML
   injection from bullet content. Affects 1.0.28 only.
 * Fix: **WordPress 6.7+ “Translation loading triggered too early” notice** caused
   by the custom cron schedule’s display label being translated inside the `cron_schedules`
   filter. The filter fires whenever WP looks up scheduled events (which can happen
   before `init`, during plugins_loaded or even setup_theme), so calling `__( …,'
   sendforce-mail-relay' )` there ran the translation function before the textdomain
   was loaded. Both filter callbacks (in the activator and the mailer) now use a
   literal English string for the cron schedule’s `display` label — that label is
   only shown in dev tools like WP Crontrol or `wp-cli cron list`, never user-facing,
   so leaving it untranslated is harmless. Resolves the deprecation notice on sites
   running WP_DEBUG with WP 6.7 or newer.

#### 1.0.28

 * New: **Test send now shows the full provider response inline** on the Email Test
   page. When a test fails the headline shows the short reason (“Failed to send 
   via Microsoft 365 API”) and a new “Provider response” panel below it shows the
   raw HTTP response body — pretty-printed when it’s JSON, with a one-click Copy
   button for support tickets. Previously the full Graph/SES/Mailgun response was
   only visible by clicking into the Email Log; users debugging a misconfiguration
   now see everything they need without leaving the test page.
 * New: **HTTPS warning on webhook URL fields** (Slack, Discord, Microsoft Teams,
   Google Chat, generic Webhook). As soon as you paste/type a URL starting with `
   http://` an inline red warning appears explaining that the alert message (site
   name, failed recipient, error details) would be sent unencrypted. Catches typos
   and homemade webhook receivers before save.
 * New: **“Welcome to v{X.Y.Z}” admin notice** after the plugin updates, with a 
   one-click button to the in-admin “What’s New” tab. Per-user dismissible, only
   shows once per version, never on fresh installs or on SendForce’s own settings
   pages (where the tab is already visible). Helps users discover what changed without
   having to read the wp.org changelog page.
 * New: **Failure-alert rate limiting**, default 5-minute window per channel. A 
   burst of failed sends (e.g. WooCommerce sending 100 order emails through an expired
   API key) no longer floods Slack/Telegram/Discord/Teams with 100 identical pings—
   within the window the first one fires, the rest are counted and rolled up into
   a “(+N additional failures were suppressed)” note on the next alert after the
   window expires. Filter `sendforce_alerts_throttle_seconds` to change the window
   length, set it to 0 to disable throttling entirely.
 * Docs: Added **CHANGELOG.md** with the complete, full-detail release history for
   every version (no length limit). The condensed Changelog in this readme.txt covers
   the WordPress.org 5,000-word cap; CHANGELOG.md carries the full story for anyone
   who wants it.
 * In-admin: The **What’s New** tab now reads from CHANGELOG.md when present (falls
   back to readme.txt). Browse every release’s full bullet list inline in WordPress
   without going to wp.org or GitHub.
 * Older entries (1.0.0 – 1.0.20) in this readme.txt are now one-line summaries;
   their full detail lives in CHANGELOG.md and the in-admin Changelog accordion.
   Recent releases (1.0.21+) remain fully detailed in both places.

#### 1.0.27

 * Security (defense-in-depth): **Bulk-delete logs and queue retry/delete actions
   now require `manage_options` capability** in addition to the existing nonce check.
   The forms that issued these requests already live on admin-only pages, so a non-
   admin couldn’t normally obtain a valid nonce — but explicit capability checks
   match WordPress.org Plugin Check expectations and protect against any future 
   flow that might mint a nonce in a less-restricted context.
 * Privacy: **Email Log now stores only the filename basenames of attachments** 
   instead of full filesystem paths. Previously rows like `/var/www/example.com/
   wp-content/uploads/woocommerce_uploads/2026/invoice-12345.pdf` were stored verbatim—
   leaking the server directory layout, shared-hosting username paths, and customer
   order IDs from WooCommerce invoice filenames. From 1.0.27 the same row stores
   only `invoice-12345.pdf`. Existing rows are not rewritten; only new log entries
   get basename-only.

#### 1.0.26

**Sending — attachments and multipart_text across all 18 API providers.**

 * New: **Attachments now work in API mode for every supported provider.** 1.0.25
   added it for Amazon SES and Gmail; 1.0.26 closes the gap for the remaining 16:
   SendGrid, Brevo, Mailgun, Postmark, Mailjet, MailerSend, Mandrill, Pepipost /
   Netcore, SocketLabs, SMTP2GO, SMTP.com, SendLayer, SparkPost, Elastic Email, 
   Resend, and Moosend. Plugin-attached files (WooCommerce PDF invoices, Contact
   Form 7 / WPForms / Gravity Forms uploads, LearnDash / LifterLMS certificates,
   anything passed to `wp_mail()`‘s 5th argument) are now base64-encoded into each
   provider’s native JSON schema and delivered through the API.
 * New: **“Multi-Part Plain Text” setting now applies to API-mode sends across the
   board.** When the message is HTML and the toggle is on, the auto-derived `text/
   plain` alternative is included via each provider’s native multipart fields. Improves
   deliverability — Gmail and other inbox providers favour multipart-alternative
   messages, and plain-text-only clients get a readable fallback. Previously this
   setting was silently ignored in API mode for the 16 providers covered here.
 * Known limitation: Moosend’s transactional API has a single `Content` field with
   no `IsContentHtml` companion for both parts, so it can’t represent multipart_text—
   its attachments work, just not the dual-body part.
 * Special-case: Mailgun’s attachment endpoint requires `multipart/form-data` (not
   JSON like the other 17), so a new `build_multipart_form_data()` helper in the
   base class assembles the request body correctly while still capturing the response
   into the debug log.
 * Internal: Two new base-class helpers — `prepare_attachments()` (base64 + MIME-
   type detection + safe file reads) and `get_plain_text_alt()` (HTMLplain conversion
   when multipart_text is on) — give each provider ~5 lines of mapping code instead
   of duplicating the same boilerplate 18 times.

**Email Queue — actual error messages + on-demand processing.**

 * Fix: **Queued emails that fail now record the actual provider error** in the 
   queue row’s `error` column. Previously every failure showed a generic “Failed
   to send email.” message, regardless of whether the cause was an expired OAuth
   token, an unverified sender domain, a wrong API key, or a network glitch. The
   queue processor now hooks `wp_mail_failed` during each send attempt and stores
   the real WP_Error message (e.g. `AADSTS70008: refresh token expired`, `MessageRejected:
   Email address is not verified`, `Domain not found`). Users on the Queue tab can
   finally see WHY a send failed without digging into the Email Log.
 * New: **“Process Queue Now” button** on the Queue tab. Triggers the same processor
   that WP-Cron runs every 5 minutes, but on demand — useful right after fixing 
   a connection or when testing the queue end-to-end. Disabled when there’s nothing
   queued; only visible when the queue is actually enabled in Settings.
 * New: **Queue-disabled info notice** on the Queue tab. Previously visiting the
   tab with the feature off showed an empty table with no explanation; now there’s
   a clear “Queue is disabled — emails are sent immediately. Enable in Settings  
   Email Queue.” banner with a deep link.
 * New: **“Next automatic run” timestamp** shown above the queue list when the queue
   is enabled, formatted using the site’s date/time format. Removes the mystery 
   of “when will my queued emails actually go out”.
 * Fix: **Test sends bypass the queue.** With queue mode enabled, clicking “Send
   Test” used to queue the message and report immediate success — but the actual
   delivery wouldn’t happen until the next cron run, which made the test page useless
   for verifying provider configuration. A new one-shot `SendForce_Queue::$bypass_once`
   flag tells the queue interceptor to skip the next wp_mail call, so test sends
   always go out synchronously regardless of queue mode.

**Admin — release history and roadmap in one place.**

 * New: **“What’s New” tab** combines the upcoming-features roadmap (formerly “What’s
   Next”) and the full release history into one navigation entry. Roadmap cards 
   render at the top as before; the changelog sits below as a collapsible accordion.
 * New: **Collapsible changelog accordion**, FAQ-style. Each release row shows version
   + change count; click to expand the bullets. The current installed version auto-
   expands; everything else stays collapsed by default — ~60% less vertical space
   than rendering everything flat. Uses native HTML `<details>`/`<summary>` so it’s
   keyboard-accessible and works without JavaScript.
 * Renamed: “What’s Next”  “What’s New”. The old `?tab=upcoming` and `?tab=changelog`
   URLs both still resolve as back-compat aliases so any bookmarks or in-plugin 
   links keep working.

#### 1.0.25

 * New: **Email attachments now work with Amazon SES API mode** (and continue to
   work with Gmail API mode). Previously the SES mailer ignored the `$attachments`
   parameter completely — WooCommerce PDF invoices, contact-form file uploads, LMS
   certificates, and similar plugin-generated attachments would silently disappear
   when sent via SES. Now they’re MIME-encoded and delivered correctly via `multipart/
   mixed`. Gmail API mode also routes through the new shared MIME builder so its
   attachment handling matches.
 * New: **“Multi-Part Plain Text” setting now applies to SES and Gmail API modes**.
   When a connection is in API mode, an HTML email is now sent with both `text/html`
   and an auto-derived `text/plain` alternative (via `multipart/alternative`). Improves
   deliverability — Gmail and other inbox providers favour multipart-alternative
   messages, and plain-text-only mail clients (some IT environments, accessibility
   tools) get a readable fallback. Previously this setting was silently ignored 
   in API mode.
 * Fix: **Subjects and From-names containing non-ASCII characters** (Café, résumé,
   François, Müller, 주문, etc.) are now RFC 2047 base64-encoded (`=?UTF-8?B?…?=`)
   before being sent. Without this, strict MTAs would reject the message and lenient
   ones would render the headers as garbage.
 * Refactor: SES and Gmail mailers now share a single `build_raw_mime()` helper 
   in the base API mailer class. Same MIME format, same encoding rules, same attachment
   handling — verified against test fixtures covering single-part, multipart/alternative,
   multipart/mixed (with attachments), Bcc-in-headers (Gmail) vs Bcc-via-API (SES),
   and non-ASCII headers.

#### 1.0.24

 * **Fix (critical for OAuth users): Microsoft 365 / Gmail “Connect with provider”
   no longer fails with `AADSTS50011` / redirect URI mismatch.** Root cause: the
   authorize URL was built with `add_query_arg()`, which does NOT URL-encode the
   values it inserts. The `&` characters inside our `redirect_uri` query value were
   left bare, so Microsoft / Google parsed `&tab=settings&sf_oauth=callback` as 
   additional top-level query parameters and saw the `redirect_uri` truncated at
   the first `&`. The fix uses `http_build_query()` with `PHP_QUERY_RFC3986` so 
   every value is properly percent-encoded. Affects every OAuth setup whose Web 
   Redirect URI contains more than one query parameter (i.e. all current SendForce
   OAuth setups). The `get_redirect_uri()` hardening from 1.0.23 was real but addressed
   a different scenario; this is the actual cause of the AADSTS50011 reports.
 * New: **OAuth consent now opens in a popup window** instead of replacing the settings
   page. Click “Connect with provider”  a centered 600×720 popup opens with the 
   Microsoft / Google sign-in flow  after consent the popup closes itself and the
   settings page refreshes with a success notice. You no longer lose your unsaved
   settings or scroll position.
 * Graceful fallback: if the browser blocks the popup (popup blocker on, or running
   in an embedded frame), SendForce falls back to the previous full-page redirect
   behaviour automatically — no error, no lost flow.
 * The OAuth callback page is now a small branded “Completing connection…” splash
   screen with a spinner that signals the parent window via THREE independent channels
   and closes itself: localStorage event (primary, survives cross-origin opener 
   severance under Cross-Origin-Opener-Policy), `postMessage` (fallback when `window.
   opener` survives), and parent-side popup-closed polling (final safety net — reloads
   the settings tab so the connection panel refreshes from the DB even if both signal
   channels fail). This eliminates the “popup closed but status didn’t update” issue
   some users hit when the browser’s COOP behaviour broke the opener relationship
   after returning from Microsoft / Google.
 * UX: Replaced the remaining native browser `alert()` / `confirm()` dialogs in 
   the OAuth flow (“Save the connection first”, “Disconnect this account?”, error
   toasts) with the styled `sfShowConfirmModal` already used elsewhere in the plugin.
   Consistent look across the admin UI.
 * UX: **Save Connection** button now shows an inline spinner and a “Validating 
   data. Please wait…” status message while the connection save is in flight — same
   pattern FluentSMTP uses. Makes it clear the click registered and the save is 
   in progress, especially on slow networks where the previous “Saving…” text alone
   wasn’t obvious enough.
 * Fix: **Microsoft 365 send failures now show the actual Graph API error** instead
   of a generic “Failed to send email via Microsoft 365 API” message. The Outlook
   mailer was bypassing the base class’s debug-capture helper, so the HTTP status
   and response body from `graph.microsoft.com` were never recorded. It now uses`
   make_request()` so the real error (`ErrorAccessDenied`, `MailboxNotEnabledForRESTAPI`,`
   AADSTS70008` token expired, etc.) is appended to the failure message and stored
   in the Email Log. Also captures token-endpoint failures from the OAuth refresh
   flow (previously silent).
 * Setup help: **Rewrote the Gmail and Microsoft 365 OAuth setup instructions** 
   in the connection editor to cover the steps users keep getting stuck on — the
   OAuth consent screen + Test users requirement for Gmail (without which Google
   returns `access_denied` “App is being tested”), the separate Authorised JavaScript
   origins field (origin-only, no path), and an explicit warning about Azure’s confusing“
   Value vs Secret ID” two-column UI for client secrets (the most common AADSTS7000215
   cause). Includes the format of valid Client IDs/Secrets so users can sanity-check
   what they pasted.
 * Setup help: **Added a “JavaScript origin” copy field** for Gmail setups, alongside
   the existing “Web Redirect URI” field. Google’s OAuth client form has two URL
   fields with different requirements; previously SendForce only documented one 
   of them.
 * Setup help: **Added client-side and server-side rejection of GUID-shaped secrets**
   for OAuth providers — pasting an Azure Secret ID into the Client Secret field
   is now blocked with a clear explanation, both as a live red warning under the
   field and as a hard rejection on save. Prevents the AADSTS7000215 “invalid client
   secret” loop where the user repeatedly pastes the wrong column from Azure.
 * Fix: **Zoho ZeptoMail “Invalid API Token found” (TM_4001 / SERR_157)** when users
   paste the full `Zoho-enczapikey TOKEN` string from ZeptoMail’s docs into the 
   Send Mail Token field. The mailer now strips the `Zoho-enczapikey` prefix automatically
   before constructing the Authorization header, so both pure-token and full-header
   paste styles work.
 * Setup help: **Added a per-provider API-key hint** rendered inline under the API
   Key field (where supplied by the provider config). First use: ZeptoMail and Amazon
   SES fields now explain where to find their credentials, format gotchas, and the
   verified-domain / sandbox requirements.
 * Fix: **Amazon SES send failures now show the actual SES API error** (same fix
   as Outlook). The SES mailer was bypassing the base class’s debug-capture helper,
   so HTTP status and response body from `email.<region>.amazonaws.com` were never
   recorded. It now uses `make_request()` so real errors like `MessageRejected` (
   sandbox, unverified address), `MailFromDomainNotVerifiedException`, `SendingPausedException`,
   or `Throttling` appear in the failure message and the Email Log.
 * Fix: **Gmail API send and token-fetch failures now surface the actual Google 
   error**. Same root cause as Outlook/SES: the Gmail mailer bypassed `make_request()`
   for the send call, and silently swallowed token-endpoint errors during the OAuth
   refresh. Errors like `invalidArgument` (malformed raw email), `failedPrecondition`(
   delegation issue), `quotaExceeded`, or `invalid_grant` (refresh token revoked/
   90-day expiry) are now surfaced. Also captures pre-flight failures (missing client_id/
   client_secret / refresh_token) with a clear explanation.
 * Fix: **Mailgun API send failures now surface the actual Mailgun error**. The 
   Mailgun mailer bypassed `make_request()` so errors like “Domain not found”, 401
   wrong-region, “freemail recipient unsupported”, or “Forbidden” never showed in
   the UI. Switched to `make_request()` with `application/x-www-form-urlencoded`
   body so debug capture works while preserving Mailgun’s required form-encoded 
   body format.
 * Fix: **Tolerate users pasting `Bearer TOKEN` (instead of just `TOKEN`)** into
   the API Key field for SendGrid, Resend, MailerSend, SMTP.com, and SendLayer. 
   Provider docs typically show `Authorization: Bearer xxxxx` in their cURL examples,
   and users frequently copy the whole `Bearer xxxxx` string. The mailer now strips
   a leading `Bearer` if present so both paste styles work. Same auto-strip already
   applies to ZeptoMail’s `Zoho-enczapikey` prefix; refactored to use a shared `
   strip_auth_prefix()` helper in the base API mailer class.
 * Fix: **All API keys are now `trim()`ed automatically** before use. Catches the
   common case where a user copy-pastes a key from a provider dashboard and accidentally
   grabs trailing whitespace or a stray newline. Previously some providers (notably
   SendGrid) would return a generic 401 with no useful explanation when the auth
   header contained non-printable characters.

#### 1.0.23

 * Fix: **Gmail / Microsoft 365 OAuth redirect URI is now constructed defensively**
   so security and caching plugins (e.g. Wordfence, LiteSpeed Cache) that filter`
   admin_url` cannot strip the query string from the path and produce a truncated`
   redirect_uri`. Resolves the intermittent `AADSTS50011` (redirect URI mismatch)
   errors some users hit when clicking “Connect with provider” for Microsoft 365.
   The final URL is unchanged — only the construction is now immune to third-party`
   admin_url` filters.
 * i18n: Email Log “Next run” timestamp now uses the site’s configured **date/time
   format** (Settings  General) instead of a hardcoded English style. Sites running
   in non-English locales will now see the cleanup schedule formatted naturally.
 * Hardening: Expanded the `wp_kses` whitelist used to render channel logos on the
   Alerts tab — adds `xmlns:xlink`, `role`, `aria-label`, `width`, `height`, `fill-
   rule`, `clip-rule`, the `<g>` element, and a few missing path/circle attributes.
   No behaviour change for the bundled icons; future channel logos with these attributes
   will render instead of being silently stripped.
 * Tweak: `ajax_cleanup_logs_now` handler now explicitly `return`s after each `wp_send_json_error()`.`
   wp_send_json_error` already terminates via `wp_die`, so behaviour is unchanged—
   purely a clarity improvement.

#### 1.0.21

 * New: **“Clean Now” button on the Email Log**. Run the auto-clean immediately 
   instead of waiting for the next scheduled cron — useful after lowering retention
   or before exporting logs. Backed by a new `sendforce_cleanup_logs_now` AJAX endpoint(
   capability + nonce protected) that reports how many rows were removed.
 * New: **Auto-clean status row above the Email Log table** — at a glance shows 
   the configured retention period, when the next automatic cleanup is scheduled,
   a deep-link to change the setting, and the “Clean Now” action.
 * New: **“via rule: ” badge on Email Log entries** — when an email was redirected
   by a Smart Routing rule, the log row now shows which rule fired (read from the
   stored debug payload). Makes it trivial to confirm that routing is working as
   intended.
 * New: **“Connection missing” warning** on routing rule cards. When a rule points
   at a connection that has been deleted, the rule card now shows an amber warning
   badge — previously such rules failed silently at runtime and emails fell through
   to the primary connection without explanation.
 * New: **Real channel logos** on the Alerts tab — Slack, Discord, Microsoft Teams,
   Telegram, Google Chat, Pushover, and Webhook now render their actual brand SVG
   icons instead of two-letter initials. Inline-loaded and color-themed via currentColor
   for crisp rendering at any DPI.
 * Improvement: **Test Routing tool parity**. The “Test Routing” tool now evaluates
   rules through the exact same matcher used by the live mailer (shared `rule_matches()`
   + new `build_test_context()` helper), eliminating any drift between what the 
   tool predicts and what actually happens at send time. Side benefit: the test 
   tool now correctly evaluates `time_between`, `weekday`, `to_pattern`, and `from_*`
   conditions (previously partly stubbed in a duplicate local matcher).
 * Improvement: Routing-tab rule cards now render round-robin target lists (“Round-
   robin: SES, SendGrid”) and a friendly “WordPress phpmail()” label for the phpmail
   pseudo-target — round-robin runtime was already supported, this surfaces it correctly
   in the UI.
 * Improvement: A11y — channel icon buttons on the Alerts tab now expose an `aria-
   label` so screen readers announce the channel name instead of empty graphics.
 * Fix: **Alert channels were occasionally wiped when saving the Summary Email form**.
   The settings sanitizer used to ignore the incoming `channels` payload and re-
   load whatever was in the DB; in races between the AJAX channel toggles and the
   Summary Email form save this could clobber channel state. The sanitizer now respects
   the incoming payload when present and only falls back to DB state when the form
   omits `channels`.
 * Tweak: Summary Email body textarea reduced from 3 rows to 2 so the Alerts form
   fits more cleanly on smaller viewports.
 * Internal: Email-log retention cleanup (`SendForce_Logger::cleanup_old_logs()`)
   now returns the number of rows deleted (was void) so callers like the new “Clean
   Now” handler can surface the count to the user.

#### 1.0.20

 * Admin top navigation layout fixes at narrow widths (tablet/mobile, mid-size laptops).
   Tab labels collapse to icon-only below 1340px. Logo gets proper left padding 
   on mobile.

#### 1.0.19

 * New: **Smart Routing Rules** — send different emails through different connections
   by recipient domain/pattern, source plugin (auto-detected for WooCommerce, CF7,
   WPForms, Gravity Forms, Ninja Forms, Fluent Forms, Forminator, EDD, MemberPress,
   LearnDash, MailPoet, BuddyPress, bbPress), subject contains, time of day, weekday.
   Top-down evaluation, first match wins. Includes Routing tab, inline rule editor,
   master enable toggle, `from_email` / `from_domain` conditions, “via rule” badge
   in Email Log, starter presets, “What’s Next” roadmap tab, styled confirm dialogs.

#### 1.0.18

 * Fixed misleading “Connected” status on Gmail / Microsoft 365 OAuth panel — now
   checks API mode + Client ID + Client Secret + refresh token all present (not 
   just any password field value). Added amber “partial credentials” state. Hint
   to switch to API mode when in SMTP. Polished status indicator dot.

#### 1.0.17

 * Initialize `oauth_email` field on newly created connections so the schema is 
   consistent from save time.

#### 1.0.16

 * New: **One-click “Connect with Google” and “Connect with Microsoft” OAuth buttons**
   replace manual refresh-token generation via OAuth Playground / Azure CLI. Refresh
   token captured automatically, stored encrypted, panel shows “Connected as user@example.
   com” with Disconnect button. Bring-your-own-credentials — no third-party OAuth
   proxy. Microsoft 365 supports both delegated and app-only flows. Setup help panel
   with copy-able redirect URI.

#### 1.0.15

 * Audited all 20 provider integrations against current docs. 18 verified spec-compliant.
   Fixed Moosend HTML content-type detection (explicit `IsContentHtml` flag in both
   HTML and plain-text paths).

#### 1.0.14

 * Fixed Email Queue orphan-row bug: rows stuck in “processing” state after cron
   timeout / PHP crash now recover via a 10-minute lease (`next_retry_at`) on the
   next cron run.

#### 1.0.13

 * Security: hardened PHP-mail fallback against header injection (strips CR/LF/null
   from To, Subject, headers). Validated attachment paths against safe roots (prevents
   path traversal). Sanitized fallback-connection label. Server-side `wp_strip_all_tags`
   on provider errors returned to the browser.

#### 1.0.12

 * Renamed “Default Connection”  “Primary Connection” throughout the admin UI (internal
   storage key unchanged). Provider status dot reflects configuration status (not
   brand colour). Fixed fallback flow so `wp_mail()` returns true on fallback success;
   clearer recovery message. Suppressed spurious SMTP-warning when active path was
   API or PHP-Mail.

#### 1.0.11

 * Plugin Name header is now clean brand name “SendForce Mail Relay” (was long SEO
   title); Description is a single-line summary. WordPress.org listing keeps the
   longer SEO title for directory search.

#### 1.0.10

 * New UI controls for **Developer Debug** toggle and **Max Retry Attempts** (1–
   10). Hardened From-email validation (admin notice on invalid). Replaced native`
   <select>` dropdowns with branded styled component (full keyboard support — Arrow/
   Enter/Escape). Default/Fallback selectors auto-refresh after connection save.
   Form-control polish (chevron, focus ring, hover, disabled states).

#### 1.0.9

 * WordPress.org listing title tuned to “SendForce Mail SMTP Relay — Free WP SMTP&
   Email API Plugin for Amazon SES, SendGrid, Mailgun, Brevo, Postmark, Zoho ZeptoMail&
   Gmail” for better directory search. Internal product name unchanged.

#### 1.0.8

 * New: **Automatic fallback connection** — when primary send fails, SendForce retries
   via configured fallback. Works across any API  API, API  SMTP, SMTP  API, SMTP
   SMTP, or any  PHP-mail combination. Both attempts logged; recovered emails get
   a “Recovered via fallback” badge. Improved readme Description for WordPress.org
   discoverability.

#### 1.0.7

 * Public display name updated for WordPress.org search index discoverability. Refreshed
   Tags to highest-volume search terms. Polished connection-row Edit/Delete buttons
   with dashicons. Added Dashboard / Settings / Email Log / Queue / Test / Alerts
   sub-menu entries.

#### 1.0.6

 * Shortened WordPress admin sidebar label to “SF Mail Relay” so it fits one line.
   Added sub-menu entries reachable from sidebar fly-out.

#### 1.0.5

 * Removed accidental `.DS_Store` file from `assets/images/providers/`. Added `phpcs:
   ignore` annotations with rationale to interpolated table-name `$wpdb` queries.
   Restructured WP-CLI log-delete query for proper phpcs handling.

#### 1.0.4

 * Updated bundled Chart.js to 4.5.0. Expanded External Services section in readme.
   Removed inline `<style>`/`<script>` blocks from PHP output (proper enqueue). 
   Surface actual provider HTTP status / response body in failure messages. Added“
   Raw API request / response” panel to Email Log detail modal. Masked-dots placeholder
   for saved password/API-key fields. Hardened secret redaction (covers `client_secret`,
   response bodies, malformed-JSON fallback). Defused CSV formula injection on log
   export. Gated on-load DB schema upgrade to admin/WP-CLI. Added confirmation prompts
   to destructive WP-CLI commands.

#### 1.0.3

 * Added WP-CLI commands (`wp sendforce test`, `queue`, `log`, `sysinfo`). Added
   developer hooks (`sendforce_before_send`, `sendforce_after_send`, `sendforce_log_entry`,`
   sendforce_api_request`, `sendforce_api_response`). Added Developer Debug setting
   to mirror SMTP/API debug to `debug.log`. Added raw API request/response capture
   in new `debug_data` log column (with Authorization redaction). Email Log export
   as CSV/JSON. “Copy Debug Info” button on Email Test screen. Replaced stale “SMTP-
   Manager” User-Agent on Resend with “SendForce-Mail-Relay”.

#### 1.0.1

 * Added Microsoft 365 Graph API and Gmail API support. Added 5 new providers (SendLayer,
   Mailjet, MailerSend, Mandrill, Resend). Added Zoho ZeptoMail API. Added 3 new
   notification channels (Microsoft Teams, Google Chat, Custom Webhook). SVG provider
   logos. Collapsible provider grid. Fixed multiple API mailer bugs (SendLayer field
   names, Pepipost endpoint, SparkPost CC, SES BCC, MailerSend Reply-To). Added 
   CC/BCC/Reply-To to Elastic Email, SMTP2GO, SMTP.com, SocketLabs, Moosend, Pepipost.
   Auto-set first connection as Default. Bundled Chart.js locally. Fixed all Plugin
   Check warnings. Renamed main file to `sendforce-mail-relay.php`.

#### 1.0.0

 * Initial release. SMTP with 18 provider presets. HTTP API for 12 providers (SendGrid,
   Mailgun, SES, Brevo, SparkPost, Postmark, Elastic Email, SMTP2GO, Pepipost, SMTP.
   com, SocketLabs, Moosend). From name/email override. Email logging with search/
   filter. Email queue with exponential backoff retry. Email Test page with live
   SMTP debug. AES-256-CBC encrypted credential storage. Auto log cleanup. Modern
   admin dashboard with 7-day send chart.

## Meta

 *  Version **1.0.31**
 *  Last updated **1 day ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 5.9 or higher **
 *  Tested up to **6.9.4**
 *  PHP version ** 7.4 or higher **
 *  Language
 * [English (US)](https://wordpress.org/plugins/sendforce-mail-relay/)
 * Tags
 * [Email API](https://vec.wordpress.org/plugins/tags/email-api/)[email log](https://vec.wordpress.org/plugins/tags/email-log/)
   [mailer](https://vec.wordpress.org/plugins/tags/mailer/)[smtp](https://vec.wordpress.org/plugins/tags/smtp/)
   [wp smtp](https://vec.wordpress.org/plugins/tags/wp-smtp/)
 *  [Advanced View](https://vec.wordpress.org/plugins/sendforce-mail-relay/advanced/)

## Ratings

 5 out of 5 stars.

 *  [  2 5-star reviews     ](https://wordpress.org/support/plugin/sendforce-mail-relay/reviews/?filter=5)
 *  [  0 4-star reviews     ](https://wordpress.org/support/plugin/sendforce-mail-relay/reviews/?filter=4)
 *  [  0 3-star reviews     ](https://wordpress.org/support/plugin/sendforce-mail-relay/reviews/?filter=3)
 *  [  0 2-star reviews     ](https://wordpress.org/support/plugin/sendforce-mail-relay/reviews/?filter=2)
 *  [  0 1-star reviews     ](https://wordpress.org/support/plugin/sendforce-mail-relay/reviews/?filter=1)

[Your review](https://wordpress.org/support/plugin/sendforce-mail-relay/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/sendforce-mail-relay/reviews/)

## Contributors

 *   [ Shipon Karmakar ](https://profiles.wordpress.org/shiponkarmakar/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/sendforce-mail-relay/)

## Donate

Would you like to support the advancement of this plugin?

 [ Donate to this plugin ](https://profiles.wordpress.org/shiponkarmakar/)