I'm implementing a MEMessageActionHandler Mail extension on macOS 26.4.1 (Xcode 26.4). The extension is discovered by Mail and appears in Mail > Settings > Extensions, but Mail shows only an "Uninstall" button — no enable toggle. The MailKit consent dialog asking permission to process messages in the background has never appeared. Console logs show optedIn: NO /
userEnabled: Not Enabled.
Extension Info.plist (key parts):
<key>NSExtensionPointIdentifier</key>
<string>com.apple.email.extension</string>
<key>NSExtensionPrincipalClass</key>
<string>CheckThisMailExtension.MailExtension</string>
<key>MEExtensionCapabilities</key>
<array>
<string>MEMessageActionHandler</string>
</array>
Principal class:
class MailExtension: NSObject, MEExtension {
func handlerForMessageActions() -> any MEMessageActionHandler {
return MessageActionHandler()
}
}
Entitlements: app-sandbox: true, application-groups: [group.com.xxx]. App is Developer ID signed and notarized.
Has anyone successfully gotten the consent dialog to appear for MEMessageActionHandler on macOS 15/26? Is there something beyond the standard template configuration that enables it?
Any entitlement that needs to be provisioned separately?
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:
<key>XPCService</key>
<dict>
<key>JoinExistingSession</key>
<true/>
<key>RunLoopType</key>
<string>_NSApplicationMain</string>
<key>ServiceType</key>
<string>Application</string>
</dict>
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.