Skip to content

Leproide/SayNoMore

v6.1 Breaking

This release includes breaking changes for platform teams planning a safe upgrade.

✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →

✓ No known CVEs patched in this version

Topics

one-time-passwords one-time-secret password-share secret-shares secrets-management share-secrets

Affected surfaces

auth

ReleasePort's take

Light signal
editorial:auto 1d

ReleasePort v6.1 adds two new email notifications for secret expiry events and updates the notification builder layout while preserving existing API signatures.

Why it matters: The release introduces "Opened after expiry" and "Expired and removed" alerts, requiring developers to handle four explicit events; mail.php now depends on lang.php via cleanup.php.

Summary

AI summary

Updates 6.1] — 2026-06-15, Compatibility, and ✨ What's new across a mixed release.

Changes in this release

Feature Medium

Adds "Opened after expiry" email notification when a secret is accessed after it has expired.

Adds "Opened after expiry" email notification when a secret is accessed after it has expired.

Source: llm_adapter@2026-06-15

Confidence: high

Feature Medium

Adds "Expired and removed" email notification when a secret expires without ever being opened.

Adds "Expired and removed" email notification when a secret expires without ever being opened.

Source: llm_adapter@2026-06-15

Confidence: high

Feature Low

Documents the new expiry notifications in `README.md`.

Documents the new expiry notifications in `README.md`.

Source: llm_adapter@2026-06-15

Confidence: high

Dependency Low

`cleanup.php` now requires `mail.php` (and transitively `lang.php`).

`cleanup.php` now requires `mail.php` (and transitively `lang.php`).

Source: llm_adapter@2026-06-15

Confidence: high

Bugfix Low

Captures notification fields before expiry check in `view.php` to enable the new "Opened after expiry" event without altering existing flows.

Captures notification fields before expiry check in `view.php` to enable the new "Opened after expiry" event without altering existing flows.

Source: llm_adapter@2026-06-15

Confidence: high

Refactor Low

Changes notification builder layout from two‑state to explicit four‑event handling while keeping API signatures unchanged.

Changes notification builder layout from two‑state to explicit four‑event handling while keeping API signatures unchanged.

Source: llm_adapter@2026-06-15

Confidence: high

Full changelog

Release date: 2026-06-15

Release 6.1 extends the optional email-notification system to secret expiry. Until now the creator could only be notified when a secret was read or destroyed (too many failed attempts). Starting with 6.1, two new events cover the full lifecycle of a secret that is never successfully opened.


✨ What's new

Expiry notifications

When email notifications are enabled (mailconfig.php'enabled' => true) and the creator provided a notification address, SayNoMore now also sends an email for:

| Event | When it fires | Source |
| ----- | ------------- | ------ |
| Opened after expiry | Someone opens the link of a secret that has already expired. The content is not shown and the file is removed. | view.php (on the unlock request) |
| Expired and removed | The cron cleanup deletes a secret that expired without ever being opened. | cleanup.php |

Together with the existing Secret read and Secret destroyed events, the creator can now be informed of every terminal state of a secret.

  • Emails are localized in the language chosen at creation time (Italian / English) — handled inline in mail.php, no lang.php strings required.
  • Each email shows the short secret ID (first 8 hex characters of the token), plus date and time.
  • The cleanup CLI prints a new notified counter (number of "Expired and removed" emails sent during the run).

📝 Changelog

[6.1] — 2026-06-15

Added

  • mail.php: two new notification events — expired_open ("Opened after expiry") and expired_clean ("Expired and removed") — with dedicated, properly worded Italian/English subject, body and HTML heading, plus distinct accent colors (amber for expired_open, slate for expired_clean).
  • view.php: when an already-expired secret is accessed via the unlock request, an expired_open notification is sent (deferred, after the response) before returning the standard "link invalid" error.
  • cleanup.php: sends an expired_clean notification for each expired-and-never-opened secret that carries a valid notify_email, and reports a new notified counter in its output.
  • README.md: documented the expiry notifications (Email notifications + Expired secret cleanup sections).

Changed

  • mail.php: the notification builder moved from a two-state (read / destroyed) layout to an explicit four-event layout. The snm_send_notification() / snm_send_notification_deferred() signatures are unchanged; any unknown event value still falls back to destroyed for backward compatibility.
  • view.php: the notification fields (notify_email, lang, short ID) are now captured before the expiry check so the new expired_open event can use them. The existing read and destroyed flows are unchanged.

Notes / Upgrade

  • New dependency: cleanup.php now require_onces mail.php (which in turn requires lang.php). Previously it was fully standalone. In a normal installation all files are present, so nothing to do — but if you deploy cleanup.php on its own, keep mail.php, lang.php and (optionally) mailconfig.php alongside it. Including mail.phplang.php from CLI is side-effect free (lang.php only defines functions).
  • No data migration: the secret payload format is unchanged. Existing secrets keep working; the notify_email / lang fields are read as before.
  • Notifications stay opt-in: with 'enabled' => false (or no mailconfig.php) the behavior is identical to 6.0 — secrets are simply removed, no email is sent.
  • In-request cleanup is silent: the probabilistic in-request cleanup in index.php / view.php removes expired secrets without sending the "Expired and removed" email. Only the cron cleanup.php sends it. If you depend on expiry notifications, run the cron — and optionally disable the in-request cleanup (const CLEANUP_ENABLED = false;).

Compatibility

  • No breaking changes. Verified: the read and destroyed notification emails are byte-for-byte unchanged; the successful read flow (HTTP 200 + iv/ct, one-time consumption) is unaffected; cleanup.php runs warning-free in CLI with mailconfig.php absent.

⚙️ Configuration recap

Email notifications are configured entirely in mailconfig.php:

return [
    'enabled'   => true,
    'host'      => 'smtp.example.com',
    'port'      => 587,
    'secure'    => 'tls',          // 'ssl' | 'tls' | ''
    'username'  => '[email protected]',
    'password'  => 'your-smtp-password',
    'from'      => '[email protected]',
    'from_name' => 'SayNoMore',
    'site_url'  => 'https://your-site.example',
    'max_retries' => 3,
    'debug'     => false,
    'timeout'   => 10,
];

For the full configuration reference, SMTP profiles and debug logging, see the main README.md.


Files changed in 6.1

mail.php             # +2 events (expired_open, expired_clean)
view.php             # expired_open notification on expired access
cleanup.php          # expired_clean notification + notified counter
README.md            # documentation

License

This project is distributed under the GNU General Public License, version 2, consistent with the GPL v2 headers in every source file of the repository. No warranty is provided.

Author

Created by Leproide — https://github.com/Leproide
Repository: https://github.com/Leproide/SayNoMore

Full Changelog: https://github.com/Leproide/SayNoMore/compare/v6...v6.1

Weekly OSS security release digest.

The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.

No spam, unsubscribe anytime.

Share this release

Track Leproide/SayNoMore

Get notified when new releases ship.

Sign up free

About Leproide/SayNoMore

All releases →

Related context

Earlier breaking changes

  • v6 Creating and reading secrets now require JavaScript and a secure context (HTTPS or .onion).
  • v6 Secrets created with previous versions become unreadable after upgrade.

Beta — feedback welcome: [email protected]