Get highlighted email in preview pane

In Apple Mail 16.0, with the 3 pane view (mailboxes, mailbox, preview) I can’t seem to get the email currently in focus in AppleScript.

So for example, with Mail looking like this:

I have a mailbox (“Miscellaneous”) selected in the left most pane, an email thread (“Hello Steve”) selected in the middle pane, and an individual email (from “Andre Galvão”) selected in the rightmost pane.

Results in AppleScript are:

tell application "Mail"
	count of selection -- "3"
	tell message viewer 1
		count of visible messages -- error "Mail got an error: AppleEvent handler failed." number -10000
		count of selected messages -- "3"
	end tell
end tell

It seems visible messages is broken, while selected messages always gives the selection in the middle pane, which is a list of all the emails in the thread. I can’t see anything in the dictionary that refers to the email that has focus - the one that will apply if any of the message actions like “Reply” are invoked.

In case it matters, I just want its message id. Any ideas?

Hi @liteyear. Welcome to MacScripter.

It doesn’t look as if the selected message can be directly identified in this situation. A workaround, if it’s not too kludgy for you, would be to use Command-o to open the message in a new window — causing the contents of Mail’s selection property to change to just that message — get the message specifier, and close the window. Getting the correct result depends on just one message in a conversation being selected, but the script hasn’t hung so far when I’ve deliberately selected the wrong things.

tell application "Mail" to activate

-- Assuming a single message in a single grouped conversation is selected,
-- open it in a new window using the Command-o keystroke.
tell application "System Events"
	set application process "Mail"'s frontmost to true
	keystroke "o" using {command down}
end tell

tell application "Mail"
	-- Wait for Mail's 'selection' to reduce to just the opened message.
	set sel to selection
	repeat until ((count sel) = 1)
		delay 0.2
		set sel to selection
	end repeat
	-- Get the message specifier and close the opened window.
	set selectedMessage to sel's item 1
	close window 1
	
	selectedMessage
end tell

You can use GUI scripting like so…

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

tell application "Mail" to activate
tell application "System Events" to tell application process "Mail"
	set myUI to group 1 of scroll area 2 of splitter group 1 of splitter group 1 of window 1
	set value of attribute "AXFocused" of myUI to true
end tell
delay 5

Wow, thank you both!

Funnily enough, opening the email in a new window manually first is how I work around it at the moment. Doing it programmatically is a great idea! Lots of edge cases to manage, and the flickering of the window opening/closing could be considered a bug or a feature (it makes it explicit which message was captured). But in my limited testing it actually seemed to work quite well.


GUI scripting is also an interesting idea, but even then I couldn’t get the “AXFocused” attribute to reveal the already focused email. For example, in the scenario I described in the OP with one email highlighted in a thread of three, here’s what I get:

value of attribute "AXFocused" of groups of scroll area 2 of splitter group 1 of splitter group 1 of window 1
-- {false, false, false, false}

Note there’s 4 groups because in addition to the 3 emails in the thread there’s one “found email” from my Sent mailbox that appears as well a scroll bar.

Alas, even going down a few more levels didn’t reveal a unique trait:

value of attribute "AXFocused" of group 1 of group 1 of scroll area 1 of groups of scroll area 2 of splitter group 1 of splitter group 1 of window 1
-- {false, false, false, false}

This is despite the fact that the set value example you provide does work to change the focus! And after executing it on, for example group 4, the result above changes to {false, false, false, true}. Maybe there’s there’s a distinctive attribute for the user-selected email somewhere in the GUI hierarchy, but I couldn’t find it.

value of attribute “AXFocused” of groups of scroll area 2 of splitter group 1 of splitter group 1 of window 1

Your email must have 4 groups then. a scroll bar is not a group so it won’t be part of what’s returned
One of the groups might be very small or a blank one-liner

also I get
{false, false, false, true}
The main part of the email seems to be the last group index-wise in the email I’m testing

Oh you’re right sorry. I got confused by Accessibility Inspector listing the scroll bar, but I see what you say now:

So the 4th group is probably the email from the Sent mailbox (the explanation I struck out in my previous post!).

Anyway, more significantly:

Today I was able to achieve the same!! After much confusion, it seems if I click just inside the rounded rectangle of the email, I get {false, false, false, false}. But, if I click just outside the rounded rectangle (which visually produces the same effect), I get {false, false, false, true}!

So I hacked this together (I’m sure my newbie-ness is on full display!) to find the focused element:

	set uiElems to entire contents of scroll area 2 of splitter group 1 of splitter group 1 of window 1
	repeat with uiElem in uiElems
		try
			if value of attribute "AXFocused" of uiElem is true then
				log uiElem
				exit repeat
			end if
		end try
	end repeat

In the latter case (click outside the rounded rect) this returns group 4 as expected. In the former case (click inside the rounded rect) it finds nothing, despite searching some 189 elements!! So I’m still stumped.