UPDATE — Got it working. Here's everything we found.
Thanks to those who replied. We eventually solved it through extensive debugging. Posting the full findings here in
case it helps anyone else — macOS 26 changed some things that aren't documented anywhere yet.
The symptom: Extension showed "Uninstall" in Mail → Settings → Extensions (meaning it was registered), but
decideAction(for:completionHandler:) never fired. No errors, no logs, nothing.
Root cause #1: The Mail checkbox
Mail keeps its own enable state for extensions, separate from the OS-level pluginkit state. Even with pluginkit
showing + (enabled), Mail internally tracks userEnabled: Not Enabled. The fix is simply ticking the checkbox next to
your extension in Mail → Settings → Extensions. It's unchecked by default. Every new user must enable it manually, and
it resets every time you replace the app binary during development.
Root cause #2: Missing XPCService block in Info.plist
Your extension's Info.plist needs both the standard NSExtension block AND an XPCService block:
XPCService
JoinExistingSession
RunLoopType
_NSApplicationMain
ServiceType
Application
Without this, the extension process can't start correctly on macOS 26.
macOS 26 change: ExtensionFoundation
MailKit switched its internal discovery mechanism to ExtensionFoundation/ExtensionKit on macOS 26. Your Swift code
doesn't change — NSObject + MEExtension + MEMessageActionHandler still works exactly as documented. But the enable
toggle moved: it's no longer in System Settings → Privacy & Security. It's only inside Mail's own Settings panel.
EXSettingsEnablementUIHidden = true in MailKit's SDK definition is why it doesn't appear in System Settings.
The app must be in /Applications
Mail won't discover extensions from apps anywhere else. Not your home folder, not the Desktop. /Applications only.
Verifying registration:
pluginkit -m -A -i com.your.bundle.extension
Should show + prefix. If it shows -, force-enable with:
pluginkit -e use -i com.your.bundle.extension
Testing:
The extension XPC process only spawns when Mail processes incoming mail — not at launch. Send yourself a test email,
then check ps aux | grep YourExtensionName to confirm it's running.
The actual Swift code is fine as documented. All the pain is in the plumbing above. Hope this saves someone else the
same weeks of debugging.
Topic:
UI Frameworks
SubTopic:
General
Tags: