Skip to content

Notify without Azure: desktop notifications by default, SMTP for email - #31

Open
terellison wants to merge 2 commits into
mainfrom
claude/notifications-without-azure
Open

Notify without Azure: desktop notifications by default, SMTP for email#31
terellison wants to merge 2 commits into
mainfrom
claude/notifications-without-azure

Conversation

@terellison

Copy link
Copy Markdown
Owner

Sending mail required provisioning an Azure Logic App, encrypting its endpoint with DPAPI, and pasting the result into appsettings.json. That's a lot of setup for someone who just wants to know a driver shipped.

The honest constraint first

Zero-configuration email isn't achievable, and not because of anything in this app. Delivering internet mail requires either an account to send through or a third-party sending service — that's precisely what email's anti-spam machinery exists to enforce. The alternative, sending direct-to-MX from a residential IP with no SPF or DKIM, gets rejected or filed as spam.

So this separates notifying you from sending email. Notification goes through INotificationChannel, with three implementations:

Channel Setup For
Toast none You're at the machine. The default.
Smtp host + app password Email, or headless/remote machines.
LogicApp unchanged Installations already using it.

With nothing configured, the dispatcher uses every channel that reports itself ready. Toast always is, so a fresh install notifies with no setup at all — that's the "out of the box" part. Naming channels in configuration selects them explicitly instead.

Existing EmailConfiguration settings are still read and mapped onto the LogicApp channel, so upgrading an enterprise install doesn't quietly stop the mail.

Channels are independent: one failing is logged and the rest still run. Nothing about notifying can fail the update check that found the driver — finding it is the valuable part.

Two dependency findings

  • Dropped CommunityToolkit.WinUI.Notifications. It's deprecated, and it drags in System.Drawing.Common 4.7.0 carrying a critical advisory (GHSA-rxg9-xrhp-64gj). Talking to WinRT directly needs no package at all.
  • MailKit 4.14.0 had a moderate advisory (GHSA-9j88-vvj5-vhgr), so it's pinned at 4.17.0. Build is 0 warnings, 0 advisories.

Target framework

Direct WinRT needs a Windows target. The notifications project multi-targets net10.0;net10.0-windows10.0.19041.0 — the toast channel exists only on the Windows target, and the plain net10.0 target keeps the dispatcher and SMTP channel testable off Windows. NotificationService moves to net10.0-windows10.0.19041.0.

Testing

Same shape as the WMI seam: the two pieces that can't be tested are humble. ToastNotificationChannel only posts a payload built by ToastPayload; MailKitSmtpTransport only puts an envelope composed by SmtpNotificationChannel on the wire. Both of those are tested, along with channel selection, casing, unknown/unconfigured names, and failure isolation.

18 new tests. 56 across the solution, all passing. Release build clean.

Not verified

Whether Windows actually renders the toast. That needs a Windows session. Unpackaged applications must declare an application identity before Windows will attribute a notification to them — this registers an AUMID under HKCU\Software\Classes\AppUserModelId, but the documented mechanism is a Start Menu shortcut carrying that ID, which the MSI would need to create. If toasts don't appear, that's the first thing to check. It fails safely: the dispatcher logs it and moves on rather than losing the update.


Generated by Claude Code

claude added 2 commits August 13, 2026 02:09
Sending mail required provisioning an Azure Logic App, encrypting its endpoint
with DPAPI, and pasting the result into appsettings.json. That is a lot of
setup for an individual who just wants to know a driver shipped.

Notifications now go through INotificationChannel, and three exist:

  Toast     a Windows desktop notification, needing no configuration at all
  Smtp      ordinary mail through any account, needing a host and app password
  LogicApp  the original relay, unchanged, for installations already using it

With nothing configured the dispatcher uses every channel that reports itself
ready. The toast channel always is, so a fresh install notifies without anyone
configuring anything - which is the point. Naming channels in configuration
selects them explicitly instead. One channel failing is logged and the rest
still run; nothing about notifying can fail the update check that found the
driver.

Worth being plain about the limit: no email channel can be configuration-free.
Delivering internet mail requires either an account to send through or a
sending service, because that is exactly what email's anti-spam machinery
exists to enforce. The toast is what genuinely needs no setup; SMTP is the
smallest amount of it, and replaces Azure with four settings.

Existing EmailConfiguration settings are still read and mapped onto the
LogicApp channel, so upgrading an enterprise install does not quietly stop the
mail.

The toast channel talks to WinRT directly rather than through
CommunityToolkit.WinUI.Notifications, which is deprecated and drags in a
System.Drawing.Common carrying a critical advisory. Direct WinRT needs no
package at all. It does need a Windows target framework, so the notifications
project multi-targets and NotificationService moves to
net10.0-windows10.0.19041.0; the plain net10.0 target keeps the dispatcher and
SMTP channel testable off Windows.

Like the WMI adapter, the two untestable pieces are humble: the toast channel
only posts a payload built by ToastPayload, and MailKitSmtpTransport only puts
an envelope composed by SmtpNotificationChannel on the wire. Both of those are
tested, along with channel selection and failure handling - 18 new tests.

Not verified here: whether Windows actually renders the toast. That needs a
Windows session, and unpackaged applications have to declare an application
identity before Windows will attribute a notification to them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JZshrskEUj58J4aS7Dz5WE
A notification only happens when NVIDIA publishes a driver newer than the one
installed, so there was no way to find out whether the configuration was right
short of waiting for a release. /TestNotification sends a sample through the
real dispatcher and prints which channels delivered it, so channel selection is
exercised rather than bypassed.

SMTP gains a Security setting: StartTls as before, SslOnConnect for implicit
TLS, and None. None is what makes it possible to point the application at a
local mail catcher and read what it actually sent, which is how the message
below was verified.

Also tidies argument handling, which threw IndexOutOfRangeException when
/EncryptEndpoint was given without an endpoint.

Verified against a mail catcher: the SMTP channel and the real MailKit
transport produce a well formed message - From with display name, To, subject
naming the driver, and a text/html body carrying the release notes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JZshrskEUj58J4aS7Dz5WE
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.

2 participants