=== APPideas Email Holinator ===
Contributors:      appideasdotcom
Tags:              email, smtp, staging, development, logging
Requires at least: 6.3
Tested up to:      7.1
Stable tag:        1.3.2
Requires PHP:      7.4
License:           GPLv2 or later
License URI:       https://www.gnu.org/licenses/gpl-2.0.html

Hold outbound email before it leaves this site, and keep a log of what was stopped.

== Description ==

APPideas Email Holinator stops this site sending email, and records the messages it
held so you can see exactly what would have gone out.

The two switches that matter — **Block emails** and **Log emails** — are pinned to
the admin toolbar, one hover away from every screen in wp-admin. The toolbar icon
turns orange while mail is being logged and red while it is being held, so you can
tell at a glance what the site is doing with its email.

It adds one wp-admin screen and that toolbar item, and nothing else: no
public-facing frontend, no dashboard widgets, and no changes to the body of any
other admin page.

= Holding =

* Block emails holds everything that goes out through wp_mail(), before it reaches any mail transport — WordPress's own, or an SMTP plugin's.
* On WordPress's own mail path a held message is answered as sent, so a held password reset or order confirmation does not turn into an error message on a site that was never meant to send it.
* Two constants for wp-config.php, AIEH_PERMAHOLE and AIEH_PERMALOG, force a switch on and lock it in the toolbar — for a development site seeded from production data, where forgetting once is once too many.

= The log =

* Log emails records every message sent through wp_mail() — sender, recipients, subject and body — held or not, and the Holinator screen lists them newest first with search, sort and a CSV download.
* Open a message to read it the way it would have arrived, with an HTML body rendered in a sandbox; resend it exactly as it was sent, or open a print-friendly view.
* A message the mail transport rejected is recorded as failed, with the transport's own error, and the log keeps the newest 1,000 messages.

= Tools =

* A status card shows what the two switches are doing right now, and updates the moment a switch is flipped in the toolbar.
* Send a real test message through the current settings and read a step-by-step transcript of what happened to it.

= External services =

This plugin contacts no external service. Nothing is sent to APPideas or to any third
party, and there is no analytics, telemetry, licence check, or update service of any
kind.

= APPideas Email Holinator PRO adds =

* An allow list — the accounts and roles you name still get their mail while everything else stays held.
* A block list — mail goes out as usual, and only the accounts and roles you name are held.
* Forwarding — messages that match are redirected to one address you can read, and the log records where each one actually went.
* Rules are written against the WordPress users and roles you already manage, and act on messages with a single recipient.

PRO installs alongside this plugin rather than replacing it, and adds its controls to
the Tools tab of this plugin's own screen. See https://appideas.com/email-holinator/

== Installation ==

1. Upload the plugin folder to `/wp-content/plugins/`, or install it from the Plugins
   screen in wp-admin.
2. Activate the plugin.
3. Hover the Holinator icon in the admin toolbar for the two switches, or open
   **Tools → Holinator** for the log.

== Frequently Asked Questions ==

= Does this change how my site sends email? =

Only while it is active. Deactivating the plugin restores WordPress's normal
behaviour immediately.

= Does it send anything anywhere? =

No. The plugin makes no outbound requests of any kind.

= Does it work with my SMTP plugin? =

Yes. A message is held before it reaches any mail transport, WordPress's own or a
plugin's. The test suite sends real messages through WP Mail SMTP, Easy WP SMTP and
FluentSMTP, and reproduces the hook orders Post SMTP and Mailgun use.

= What can it not catch? =

A plugin that calls PHP's own mail() function, or talks to a mail service directly,
never goes through wp_mail(), so WordPress offers no hook to hold it. That is rare;
whatever uses wp_mail() — WordPress itself, WooCommerce, form plugins and SMTP
plugins — is held.

= How many messages does the log keep? =

The newest 1,000. When a new message arrives past that, the oldest is removed.

= Does it work on a multisite network? =

Yes. Each site has its own switches and its own log, and deleting the plugin from
the network removes every site's data.

= Where do I find it? =

Hover the Holinator icon in the admin toolbar for the two switches, or open
Tools → Holinator for the log, the Tools tab and Get PRO.

== Screenshots ==

1. The email log: every message the site tried to send, held before it left, with search, sort and a CSV download.
2. The toolbar panel: Block and Log are one hover away from every wp-admin screen, and the icon turns red while mail is being held.
3. A held message opened in the reader, shown the way it would have arrived, with resend and print.
4. The Tools tab: what the two switches are doing right now, and a real test message sent through them with a step-by-step transcript.
5. Get PRO: what the paid add-on adds.

== Changelog ==

= 1.3.2 =

* First release.
* Block emails now holds outbound mail before it leaves the site — every message WordPress sends through wp_mail().
* Log emails records every message WordPress sends through wp_mail(), and the Holinator screen lists them with a reader that shows each one the way it would have arrived.
* Logged messages can be opened and deleted one at a time, and the log keeps the newest 1,000.
* The log screen can search, sort, and download its contents as a CSV file.
* A stored message can be resent exactly as it was sent, or opened in a print-friendly view.
* A new Tools screen shows what the two switches are doing right now, and can send a real test message through them to see exactly what happens.
* AIEH_PERMAHOLE and AIEH_PERMALOG, set in wp-config.php, force Block and Log on and lock the toolbar switches — for a dev site seeded from production data.
* Flipping a switch in the toolbar now confirms on screen that the change was saved.

== Test Analysis ==

| Suite                   | Metric             | v 1.3.2 |
|-------------------------|--------------------|---------|
| PHP (PHPUnit)           | Line coverage      | 99.36 % |
| PHP (PHPUnit)           | Tests              | 304     |
| JavaScript (Jest)       | Statement coverage | 98.48 % |
| JavaScript (Jest)       | Branch coverage    | 93.06 % |
| JavaScript (Jest)       | Tests              | 315     |
| End-to-end (Playwright) | Tests              | 203     |

Version 1.3.2 lints clean — zero errors, zero warnings, and zero suppressions — against
WordPress Coding Standards 3.4.1 on PHP_CodeSniffer 3.13.5, PHPCompatibilityWP 2.1.8
checked from PHP 7.4 upward, and @wordpress/eslint-plugin 22.22.0 on ESLint 8.57.1. Plugin
Check 2.1.0 reports no errors against the shipped files, across every check category; its
26 warnings are the direct-database-query notices on the one file that owns the log table
and two for reading WordPress's own mail filters, each reviewed and kept on purpose.
