Skip to content

IONOS(sharebymail): add BeforeShare*MailSentEvent dispatched before each mail send (HDNEXT-1010)#262

Open
printminion-co wants to merge 3 commits into
ionos-dev-v30from
HDNEXT-1010-add-share-mail-event
Open

IONOS(sharebymail): add BeforeShare*MailSentEvent dispatched before each mail send (HDNEXT-1010)#262
printminion-co wants to merge 3 commits into
ionos-dev-v30from
HDNEXT-1010-add-share-mail-event

Conversation

@printminion-co

@printminion-co printminion-co commented Jun 12, 2026

Copy link
Copy Markdown

Summary

Introduces a PSR-14 event hook inside ShareByMailProvider that allows app-layer listeners to replace the native Nextcloud SMTP path for share-by-mail notifications.

New event classes in apps/sharebymail/lib/Event/

  • AbstractBeforeShareMailSentEvent — abstract base carrying the fully-prepared IMessage, validated recipient list, pre-computed mail data, and a markMailHandled() flag
  • BeforeShareMailSentEvent — fired by sendEmail() before the share-link notification send
  • BeforeSharePasswordMailSentEvent — fired by sendPassword() and sendPasswordToOwner() before password emails
  • BeforeShareNoteMailSentEvent — fired by sendNote() before note-update emails

How the replacement mechanism works

When a listener calls $event->markMailHandled(), the native mailer->send() is skipped. If the listener's own send throws, the exception propagates — native send is also skipped. No silent fallback. When no listener is active, native SMTP runs as before.

mailData array

Each send method passes the data it already computed before building the IMessage. Listeners read $event->getMailData() instead of re-deriving from the share, avoiding duplicate user/node lookups.

BeforeShareMailSentEvent carries: senderUserId, fileName, resourceUrl, note, expiration (\DateTime|null).

Dispatch point

Events fire inside each private send method immediately before mailer->send() — covering both Manager::createShare() and sendShareEmail() Controller paths without touching either.

Related PRs

Test plan

  • apps/sharebymail/ unit tests pass
  • E2E: file request → send email via UI → IONOS API called; no native SMTP
  • E2E: regular share by email → IONOS API called once; no double-send
  • E2E: disable nc_ionos_processes → native SMTP resumes without code changes

@printminion-co printminion-co force-pushed the HDNEXT-1010-add-share-mail-event branch 2 times, most recently from 0dfb4f0 to 05ca5da Compare June 12, 2026 12:45
@printminion-co printminion-co force-pushed the HDNEXT-1010-add-share-mail-event branch from 05ca5da to e5d9cd6 Compare June 15, 2026 13:46
@printminion-co printminion-co changed the title feat(files_sharing): dispatch BeforeShareMailNotifiedEvent from sendShareEmail IONOS(sharebymail): add BeforeShare*MailSentEvent dispatched before each mail send (HDNEXT-1010) Jun 15, 2026
…ateData variables

Extract the inline array literals passed to each createEMailTemplate() call
into named $templateData variables. For sendNote(), which previously passed no
data array, add a minimal array so all four send methods are consistent.

Zero behaviour change — $templateData is passed straight through to
createEMailTemplate() with identical contents.
@printminion-co printminion-co force-pushed the HDNEXT-1010-add-share-mail-event branch 2 times, most recently from 1083f45 to 450ed8c Compare June 15, 2026 14:45
…ach mail send

Dispatch a typed PSR-14 event immediately before every mailer->send() call
in ShareByMailProvider so that external listeners can intercept and replace
Nextcloud's native SMTP delivery.

Event hierarchy:
  AbstractBeforeShareMailSentEvent (base: share, resolvedEmails, message,
    markMailHandled / isMailHandled)
  ├── BeforeShareMailSentEvent   – sendEmail()
  ├── BeforeSharePasswordMailSentEvent – sendPassword() + sendPasswordToOwner()
  └── BeforeShareNoteMailSentEvent – sendNote()

Each concrete class holds its own typed $templateData (psalm array-shape)
and exposes named getters (getSenderUserId(), getFileName(), …) instead of
a generic getMailData(): array<string,mixed>.  This avoids defensive
is_string() / null guards in listeners.

$templateData reuses the array already passed to createEMailTemplate(), with
one extra key added for sendEmail(): senderUserId (the raw user ID, distinct
from the display name stored under 'initiator').

The native mailer->send() is skipped when a listener calls markMailHandled().
If the listener's own send throws, the exception propagates and the native
send is also skipped — no silent SMTP fallback.

sendEmail() and sendPassword() are flattened from nested
if (!isMailHandled()) { ... } pyramids to early-return style.

Signed-off-by: Misha M.-Kupriyanov <kupriyanov@strato.de>
…etters)

Signed-off-by: Misha M.-Kupriyanov <kupriyanov@strato.de>
@printminion-co printminion-co force-pushed the HDNEXT-1010-add-share-mail-event branch from 450ed8c to ccc0f83 Compare June 15, 2026 15:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant