This release includes breaking changes for platform teams planning a safe upgrade.
✓ No known CVEs patched in this version
Topics
Affected surfaces
ReleasePort's take
Light signalReleasePort 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 summaryUpdates 6.1] — 2026-06-15, Compatibility, and ✨ What's new across a mixed release.
Changes in this release
| Type | Severity | Summary | CVE |
|---|---|---|---|
| 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, nolang.phpstrings 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
notifiedcounter (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") andexpired_clean("Expired and removed") — with dedicated, properly worded Italian/English subject, body and HTML heading, plus distinct accent colors (amber forexpired_open, slate forexpired_clean).view.php: when an already-expired secret is accessed via the unlock request, anexpired_opennotification is sent (deferred, after the response) before returning the standard "link invalid" error.cleanup.php: sends anexpired_cleannotification for each expired-and-never-opened secret that carries a validnotify_email, and reports a newnotifiedcounter 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. Thesnm_send_notification()/snm_send_notification_deferred()signatures are unchanged; any unknown event value still falls back todestroyedfor backward compatibility.view.php: the notification fields (notify_email,lang, short ID) are now captured before the expiry check so the newexpired_openevent can use them. The existingreadanddestroyedflows are unchanged.
Notes / Upgrade
- New dependency:
cleanup.phpnowrequire_oncesmail.php(which in turn requireslang.php). Previously it was fully standalone. In a normal installation all files are present, so nothing to do — but if you deploycleanup.phpon its own, keepmail.php,lang.phpand (optionally)mailconfig.phpalongside it. Includingmail.php→lang.phpfrom CLI is side-effect free (lang.phponly defines functions). - No data migration: the secret payload format is unchanged. Existing secrets keep working; the
notify_email/langfields are read as before. - Notifications stay opt-in: with
'enabled' => false(or nomailconfig.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.phpremoves expired secrets without sending the "Expired and removed" email. Only the croncleanup.phpsends 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
readanddestroyednotification emails are byte-for-byte unchanged; the successful read flow (HTTP 200 +iv/ct, one-time consumption) is unaffected;cleanup.phpruns warning-free in CLI withmailconfig.phpabsent.
⚙️ 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
About Leproide/SayNoMore
All releases →Beta — feedback welcome: [email protected]