From 915743acccc33eecbb0ba38d8aba7ebab6f99c8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Romero?= Date: Fri, 6 Nov 2026 00:45:20 +0100 Subject: [PATCH] feat: report received mail links on stderr --- src/mailto_links.rs | 34 +++++++++++++++++++++++++------- src/main.rs | 4 ++-- src/reader_validation.rs | 6 +++++- src/renderer_input_controller.rs | 2 +- 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/mailto_links.rs b/src/mailto_links.rs index d56a3caa..78ff6b23 100644 --- a/src/mailto_links.rs +++ b/src/mailto_links.rs @@ -105,23 +105,43 @@ pub(super) fn receive_from_macos(app: &AppWindow) { return; }; window_controller::activate(&app, None); - open(&app, [url]); + open(&app, "apple-event", [url]); }); } -/// Open mailto links in the composer as soon as it can take them. -pub(super) fn open>(app: &AppWindow, uris: impl IntoIterator) { - let mut unreadable = false; +/// Open mailto links in the composer as soon as it can take them. `source` +/// says how they arrived ("message", "launch", "forwarded" or +/// "apple-event") for the diagnostic line. +pub(super) fn open>( + app: &AppWindow, + source: &'static str, + uris: impl IntoIterator, +) { + let (mut received, mut unreadable) = (0_usize, 0_usize); LINKS.with(|links| { let mut links = links.borrow_mut(); for uri in uris { match mailto::parse(uri.as_ref()) { - Some(message) => links.pending.push_back(message), - None => unreadable = true, + Some(message) => { + links.pending.push_back(message); + received += 1; + } + None => unreadable += 1, } } }); - if unreadable { + if received + unreadable > 0 { + // Whether a link reached the application, without any of its + // content, like the FLECTAR_RENDERER lines. + eprintln!( + "FLECTAR_MAIL_LINKS {}", + serde_json::json!({ + "event": "received", "source": source, + "links": received, "unreadable": unreadable, + }) + ); + } + if unreadable > 0 { app.set_render_status(UiMessage::plain("This email link is too long to open.")); } open_pending_soon(app); diff --git a/src/main.rs b/src/main.rs index 65d052fe..33496a8c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1806,13 +1806,13 @@ pub fn run(platform: PlatformContext) -> Result<(), Box> instance.serve(&runtime, move |activation| { let _ = app.upgrade_in_event_loop(move |app| { window_controller::activate(&app, activation.activation_token); - mailto_links::open(&app, activation.links); + mailto_links::open(&app, "forwarded", activation.links); }); }); } // They open once the mail store is ready and the composer connected. #[cfg(desktop)] - mailto_links::open(&app, launch_links.unwrap_or_default()); + mailto_links::open(&app, "launch", launch_links.unwrap_or_default()); // The launcher's token was meant for this window: it lets the desktop // focus it (Wayland) and ends the launch feedback (X11). #[cfg(desktop)] diff --git a/src/reader_validation.rs b/src/reader_validation.rs index 802cb115..36899eb2 100644 --- a/src/reader_validation.rs +++ b/src/reader_validation.rs @@ -842,7 +842,11 @@ fn mailto_links_open_without_losing_the_draft( app.set_compose_subject("My own subject".into()); // The reader's link handler was replaced by a recorder above; open the // link the way it does. - mailto_links::open(app, ["mailto:second@example.com?attach=/etc/passwd"]); + mailto_links::open( + app, + "message", + ["mailto:second@example.com?attach=/etc/passwd"], + ); frame(); assert_eq!( *saved.borrow(), diff --git a/src/renderer_input_controller.rs b/src/renderer_input_controller.rs index f64b6f5d..a6850ea9 100644 --- a/src/renderer_input_controller.rs +++ b/src/renderer_input_controller.rs @@ -116,7 +116,7 @@ pub(super) fn register_renderer_input_callbacks( return; } if flectar_mail_core::mailto::is_mailto(&url) { - crate::mailto_links::open(&app, [url.as_str()]); + crate::mailto_links::open(&app, "message", [url.as_str()]); return; } if let Err(error) = open_email_link(&opener, &url) {