You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: cross-platform mailto handler with cold-start deep-link fix
Add native mailto: default handler check and registration for the
Tauri desktop app across all platforms:
- macOS: CoreServices LSCopyDefaultHandlerForURLScheme (read) and
LSSetDefaultHandlerForURLScheme (write). Falls back to opening
Apple Mail settings with user instructions when the App Sandbox
blocks the write call (error -54).
- Windows: tauri-plugin-deep-link register()/is_registered() via
Windows registry.
- Linux: tauri-plugin-deep-link register()/is_registered() via
xdg-mime.
- Web: navigator.registerProtocolHandler() (explicit opt-in only).
Fix cold-start race condition where clicking a mailto: link to launch
the app would open the window but silently drop the URL because the
webview JS listeners were not yet registered:
- Capture initial deep-link URL via deep_link().get_current() during
Rust setup() into a PendingDeepLinks mutex queue.
- Add get_pending_deep_links IPC command to drain the queue.
- initTauriBridge() drains pending URLs after registering listeners.
- Move app:deep-link and app:single-instance event listeners before
initTauriBridge() call so they are ready when URLs are replayed.
Remove silent auto-registration of the web app as Chr
/// Result of attempting to set the default mailto handler.
222
+
#[derive(Clone,Serialize)]
223
+
structSetMailtoResult{
224
+
/// "registered" | "open_mail_settings" | "error"
225
+
method:String,
226
+
/// Human-readable message for the user
227
+
message:String,
228
+
}
229
+
230
+
/// Attempt to set this app as the default mailto: handler.
231
+
#[cfg(desktop)]
232
+
#[tauri::command]
233
+
asyncfnset_default_mailto_handler(
234
+
app: tauri::AppHandle,
235
+
) -> Result<SetMailtoResult,String>{
236
+
set_default_mailto_handler_impl(&app).await
237
+
}
238
+
239
+
#[cfg(all(desktop, target_os = "macos"))]
240
+
asyncfnset_default_mailto_handler_impl(
241
+
_app:&tauri::AppHandle,
242
+
) -> Result<SetMailtoResult,String>{
243
+
use core_foundation::base::TCFType;
244
+
use core_foundation::string::CFString;
245
+
246
+
unsafe{
247
+
let scheme = CFString::new("mailto");
248
+
let bundle_id = CFString::new("net.forwardemail.mail");
249
+
250
+
let result = LSSetDefaultHandlerForURLScheme(
251
+
scheme.as_concrete_TypeRef(),
252
+
bundle_id.as_concrete_TypeRef(),
253
+
);
254
+
255
+
if result == 0{
256
+
// noErr \u{2014} success (works for non-sandboxed builds)
257
+
returnOk(SetMailtoResult{
258
+
method:"registered".to_string(),
259
+
message:"Forward Email is now your default email app.".to_string(),
260
+
});
261
+
}
262
+
263
+
// Error -54 (or any error): App Sandbox blocks this call.
264
+
// Open Apple Mail so the user can change the setting manually.
265
+
log::info!(
266
+
"LSSetDefaultHandlerForURLScheme returned {}, falling back to Mail.app settings",
267
+
result
268
+
);
269
+
270
+
let open_result = std::process::Command::new("open")
271
+
.arg("-b")
272
+
.arg("com.apple.mail")
273
+
.output();
274
+
275
+
match open_result {
276
+
Ok(_) => Ok(SetMailtoResult{
277
+
method:"open_mail_settings".to_string(),
278
+
message:"Apple Mail has been opened. Please go to Mail \u{2192} Settings \u{2192} General \u{2192}\"Default email reader\" and select Forward Email.".to_string(),
279
+
}),
280
+
Err(e) => Ok(SetMailtoResult{
281
+
method:"open_mail_settings".to_string(),
282
+
message:format!(
283
+
"Please open Apple Mail, then go to Mail \u{2192} Settings \u{2192} General \u{2192}\"Default email reader\" and select Forward Email. (Could not open Mail automatically: {})",
0 commit comments