github Notifuse/notifuse v36.0

6 hours ago
  • Feature: Transactional email attachments support a per-attachment content_id for inline images (e.g. per-recipient QR codes) — set disposition: "inline" plus content_id and reference the image from the template as <img src="cid:...">. Works across all email providers; inline images are assembled in a multipart/related MIME subtree on Amazon SES (previously they could show up as dangling attachments in Gmail/Outlook) and the SMTP provider now emits the RFC 2045 angle-bracketed Content-ID header that strict clients like Outlook require (#393)
  • Fix: SMTP connections on port 465 now use implicit TLS (SMTPS). Workspace SMTP integrations, the setup wizard's "Test SMTP Connection", and system emails (magic codes, invitations, alerts) always spoke plaintext-first SMTP — waiting for a greeting that an SMTPS server never sends before negotiating STARTTLS — so a port-465 + TLS configuration hung or timed out. With TLS enabled and port 465, the client now performs the TLS handshake immediately after connecting and skips STARTTLS. TLS on any other port still negotiates STARTTLS, and use_tls=false remains plaintext, including on port 465. The TLS handshakes in the raw SMTP sender (both implicit and STARTTLS) are also now bounded by the dial timeout instead of hanging indefinitely on an unresponsive server (#385)
  • Fix: OIDC sign-in no longer permanently fails with IdPs that omit the email_verified claim (Microsoft Entra ID, Cloudflare Access): an absent claim decoded as false and rejected every first login. Setting the new env-only OIDC_ALLOW_UNVERIFIED_EMAIL=true (default false) accepts first logins whose id_token omits the claim; an explicit email_verified=false is still always rejected, and the rejection log now names the flag to set (#388)
  • Fix: Enabling OIDC through the setup wizard persisted oidc_scopes="openid" (the wizard has no scopes field), and that stored value overrode the openid email profile default at boot — authorize requests then lacked the email/profile scopes, so IdPs returned tokens without an email. The wizard and the settings screen now persist the full default when scopes are left empty, and the v36 system migration heals existing rows still holding the bare legacy value (when a row is healed the server restarts once so the change takes effect immediately) (#389)
  • Feature: Segments and automation conditions can now target link clicks by broadcast and by URL. A "clicked email" timeline condition can be scoped to a specific broadcast and/or to a clicked link, where the link is matched as a case-insensitive substring of the destination URL (e.g. /pricing matches https://acme.com/pricing?utm_campaign=summer). This makes segments and automation filters like "clicked the pricing link in the Summer Sale broadcast" possible; it builds on the per-link click data already recorded in message_history.clicked_links, so no migration is needed (#339, #311).
  • Fix: Viewing the contacts of a segment no longer returns a server error. The segments.contacts endpoint ordered by a created_at column that contact_segments does not have, so every request failed; it now orders by matched_at (when the contact joined the segment).
  • Fix: Removed the "Photo URL" option from the automation contact updated trigger's field list — contacts have no photo-URL field, so an automation filtered on it could never fire.
  • Fix: Segment/automation conditions that filter contact-timeline events by a field value now work. The query builder referenced a non-existent metadata column on contact_timeline (event fields live in the changes JSONB as {field: {old, new}}), so any such condition failed at SQL execution; it now reads the field's new value from changes.
  • Fix / Change: The contact timeline now records email engagement events in the same dot notation as the rest of the timeline and the webhooks — email.opened, email.clicked, email.bounced, email.complained, email.unsubscribed, plus email.sent and email.updated — replacing the old open_email / click_email / insert_message_history / update_message_history names. This fixes automations triggered by an email engagement event, which previously never fired because the trigger listened for email.clicked while the timeline stored click_email. Workspace migration v36 renames existing timeline rows, rewrites stored segment definitions (both the tree and the compiled query) and regenerates the triggers of already-live automations, so segments and automations keep working without needing to be re-saved. The email.sent and email.delivered options were removed from the automation trigger list — they could never fire, and an email.sent trigger would loop an "every time" automation that sends email. (#339)
  • Security: golang.org/x/crypto is pinned to 0.52.0 in both Go modules, closing the SSH-related advisories (12 critical/high) flagged by Dependabot.
  • Fix: Automation email nodes now display the selected template's name on the canvas for non-marketing templates (e.g. welcome). The canvas resolved names from a reference list restricted to category: 'marketing', while the node picker lets you select an email template of any category — so a validly selected non-marketing template fell back to the generic "Template set" label; the reference list is no longer category-restricted (#391).
  • Change: Mailjet can now only be used as a transactional email provider, not a marketing one, because the Mailjet API overwrites unsubscribe links and breaks Notifuse's unsubscribe links. Newly assigning Mailjet as the marketing provider is rejected at settings-save, and marketing sends are refused at provider resolution — so workspaces that already had Mailjet assigned keep saving unrelated settings normally, but their broadcasts fail with a clear error until they switch the marketing provider.

Don't miss a new notifuse release

NewReleases is sending notifications on new releases.