=== Stampy ===
Contributors: neudrino
Tags: newsletter, mailing list, email campaign, subscription, smtp
Requires at least: 7.0
Tested up to: 7.1
Requires PHP: 8.3
Stable tag: 1.0.0
License: GPLv3
License URI: https://www.gnu.org/licenses/gpl-3.0.html

Self-hosted mailing-list plugin with double opt-in, custom fields, block-editor campaigns, SMTP, tracking, import/export, and GDPR tools.

== Description ==

Stampy is a self-hosted mailing-list plugin for WordPress. No external email service required — connect your own SMTP server and send directly from your site.

**Features**

* **Double opt-in signup block** — a Gutenberg block with email, configurable custom fields, consent checkbox, and list selection. Spam protection via honeypot, rate limiting, optional quiz challenge, Cloudflare Turnstile, and Friendly Captcha.
* **Custom field management** — define custom subscriber attributes (text, textarea, number, date, select, checkbox) with a self-service admin UI. Fields are validated on signup and usable as merge tags in campaigns.
* **Subscriber management** — admin list table with search, status filtering, list membership filtering, bulk actions, and prominent count display. Full per-subscriber profile editor for all attributes.
* **List management** — create and manage multiple mailing lists with subscriber memberships and subscriber counts.
* **Block-editor campaign composer** — compose newsletters in the WordPress block editor. The campaign sidebar plugin provides subject, target list selection, tracking override, send/cancel, progress, and preview — all in one place. Campaign duplication for reusing existing content as a template.
* **SMTP connector** — configure any SMTP server with TLS/SSL encryption and authentication. Test-send from the settings page. Passwords encrypted with libsodium.
* **Batched background sending** — Action Scheduler-powered sending with per-recipient personalization via merge tags, RFC 8058 one-click unsubscribe headers, and stuck-send detection.
* **Open & click tracking** — optional tracking pixel and link rewriting with HMAC-signed URLs. Per-campaign override. Disabled by default for privacy.
* **Import & Export** — export all subscribers or a specific list to CSV or JSON. Import subscribers from CSV or JSON with live preview, delimiter auto-detection, and merge-policy upsert.
* **Submission log** — optional consent audit trail logging every signup submission (email, fields, list IDs, consent text, timestamp). Searchable admin viewer. GDPR export/erase covered.
* **GDPR compliance** — personal data exporters and erasers for subscriber profiles, attributes, list memberships, pending signups, campaign recipient history, click tracking data, and submission log entries. Physical address field for CAN-SPAM compliance.
* **Preference center** — subscribers can manage their list memberships and unsubscribe from a self-hosted preference page.
* **Uninstall cleanup** — all data (tables, options, cron events, campaigns) is removed on plugin deletion (toggle in settings).
* **Translation-ready** — ships with a .pot template; community translations available via translate.wordpress.org once the plugin is hosted on WordPress.org.

== Installation ==

1. Upload the plugin to the `/wp-content/plugins/stampy` directory, or install it through the WordPress plugins screen.
2. Activate the plugin through the "Plugins" screen in WordPress.
3. Navigate to **Stampy → Settings** to configure your SMTP server, physical address, tracking, anti-spam, and compliance settings.
4. Create a mailing list under **Stampy → Lists**.
5. Optionally define custom subscriber fields under **Stampy → Fields**.
6. Place the "Stampy Signup" block on any page or post.
7. Compose a campaign under **Campaigns** in the WordPress admin.

== Frequently Asked Questions ==

= Does Stampy require an external email service? =

No. Stampy connects directly to your own SMTP server. No Mailchimp, SendGrid, or third-party API is needed.

= Is tracking enabled by default? =

No. Open and click tracking is off by default. Nothing is tracked until you explicitly enable it globally in **Stampy → Settings** (individual campaigns can also override it).

= Does tracking show individual recipients? =

Only if you turn anonymous tracking off. While tracking is enabled, the default "Anonymous Tracking" setting records how many recipients opened a campaign email and how many clicked a link (including per-URL click counts), but never who: emails carry a keyed, non-reversible pseudonym instead of a recipient ID, and no per-recipient timestamps are stored. Disable anonymous tracking in **Stampy → Settings** to record per-recipient opens and clicks — after sending, use the **Recipients** row action on the campaign to see exactly who opened or clicked, including the clicked URLs. Both settings only apply while tracking is enabled — with tracking off, nothing is tracked regardless.

= What spam protection is available? =

Stampy includes honeypot and rate-limiting by default. You can optionally enable a question/answer quiz challenge, Cloudflare Turnstile, or Friendly Captcha in **Stampy → Settings**.

= Can I collect custom subscriber fields? =

Yes. Go to **Stampy → Fields** to define custom attributes (text, textarea, number, date, select, checkbox). Each field can be marked as required and toggled for admin visibility. Custom fields appear in the signup block and are usable as `{field:field_key}` merge tags in campaigns.

= Can I import existing subscribers? =

Yes. Go to **Stampy → Import / Export** to import subscribers from a CSV or JSON file. The import page shows a live preview, auto-detects the CSV delimiter, and creates a new list for the imported subscribers. You can also export all subscribers or a specific list to CSV or JSON.

= What is the submission log? =

The submission log is an optional audit trail that records every signup submission — the email, all field values, target list IDs, the exact consent text, and timestamp. It is enabled by default and can be toggled in **Stampy → Settings**. Entries are searchable by email and auto-deleted when the subscriber is deleted.

= What happens to subscriber data when the plugin is deleted? =

By default, all data is removed on uninstall (tables, options, campaigns, cron events). You can toggle this in **Stampy → Settings → Compliance**. Deactivating the plugin always preserves data.

= Is Stampy GDPR compliant? =

Stampy provides tools that help you meet GDPR requirements, but compliance depends on how you configure and use the plugin. Features include double opt-in consent, a submission audit log, and WordPress privacy-data export/erase integration (admin-initiated via **Tools → Export Personal Data** / **Erase Personal Data**). You are responsible for your privacy policy and lawful basis for processing.

= Can I use a different language? =

Stampy is translation-ready. Once hosted on WordPress.org, community translations are available via translate.wordpress.org.

== External Services ==

Stampy optionally integrates with two third-party captcha services to protect your signup form from automated bot submissions. Both are disabled by default and only activated when you configure site and secret keys in **Stampy → Settings**. No data is sent to any external service unless you explicitly enable and configure one of these captcha providers.

= Cloudflare Turnstile =

When enabled, the Cloudflare Turnstile widget script is loaded from Cloudflare's servers on pages containing the Stampy Signup block. The widget collects interaction data from the visitor's browser (including mouse movements, keyboard timing, and other behavioral signals) and sends it to Cloudflare for bot detection. When the form is submitted, the Turnstile token is verified server-side via Cloudflare's siteverify API, which sends the token, the configured secret key, and the visitor's IP address to Cloudflare.

- Service: https://developers.cloudflare.com/turnstile/
- Terms of Service: https://www.cloudflare.com/website-terms/
- Privacy Policy: https://www.cloudflare.com/privacypolicy/
- Turnstile Privacy Addendum: https://www.cloudflare.com/turnstile-privacy-policy/

= Friendly Captcha =

When enabled, the Friendly Captcha widget script is bundled and served locally from the plugin's `assets/vendor/friendly-captcha/` directory (no external CDN dependency). The widget generates a proof-of-work puzzle that is solved in the visitor's browser using its computing resources. When the form is submitted, the solution is verified server-side via Friendly Captcha's siteverify API, which sends the solution and the configured API key to Friendly Captcha.

- Service: https://friendlycaptcha.com/
- Terms of Service: https://friendlycaptcha.com/legal/terms
- Privacy Policy: https://friendlycaptcha.com/legal/privacy/

== Screenshots ==

1. Campaigns — list of all campaigns with status, progress, and tracking columns
2. Subscribers — admin list table with status filter, list filter, and bulk actions
3. Lists — manage mailing lists with subscriber counts
4. Fields — custom field definitions with type, required, and admin-visibility toggles
5. Settings — SMTP configuration, tracking toggle, compliance, anti-spam, and captcha settings
6. Submission Log — consent audit trail with searchable log entries
7. Import/Export — CSV/JSON import and export of subscriber data

== Changelog ==

= 1.0.0 =

* Fixed: pass tag input as VERSION to wporg deploy action
* Changed: generate GitHub release notes from conventional commits via git-cliff
* Changed: generate readme.txt changelog from conventional commits
* Changed: consolidate readme.txt features and drop hand-maintained changelog
* Changed: check PR titles against conventional commits
* Changed: add conventional commits note and reformat README with semantic line breaks
* Fixed: harden E2E, fix stale workflow refs, pin WP core in wp-env

= 0.0.6 =

* Added: add anonymous tracking and recipient stats view
* Changed: remove unnecessary GitHub files and Dependabot config
* Changed: bump composer dependencies
* Changed: bump npm dependencies
* Changed: bump wpcs from 3.4.0 to 3.4.1

= 0.0.5 =

* Fixed: self-host Friendly Captcha SDK instead of CDN
* Changed: bump wp-phpunit from 7.0.1 to 7.0.2

= 0.0.4 =

* Fixed: correct enqueued assets and nonce usage
* Fixed: resolve Plugin Check warnings

= 0.0.3 =

* Changed: drop unnecessary load_plugin_textdomain call
* Fixed: add nonces and capability checks to request handlers
* Fixed: include translation files
* Fixed: document external services and remove remote file calls
* Fixed: enqueue scripts and styles via wp_enqueue

= 0.0.2 =

* Fixed: resolve WordPress upload scanning errors

= 0.0.1 =

* Changed: pre-publish review cleanup
* Changed: rename release pipeline workflows
* Changed: add WP.org release pipeline
* Added: add submission log audit trail
* Added: add subscriber import and export
* Added: improve list management and campaigns
* Added: add field management and subscriber profiles
* Added: add Turnstile and Friendly Captcha spam guards
* Added: add native anti-spam quiz
* Added: add GDPR privacy hooks and data erasure
* Added: add sending engine and open/click tracking
* Added: add campaign post type and email renderer
* Added: add SMTP connector
* Added: add admin UI for subscribers and lists
* Added: add signup block
* Added: add headless opt-in core with signup, confirm and email
* Added: add data layer for subscribers, lists and fields
* Changed: set up test harness
* Added: scaffold plugin skeleton
* Changed: Initial (empty) commit

