Broken Mail scripts, how to find object's parent

Well, it seems that AppleScript support for Mail 2.0.2 in Mac OS X Tiger is broken. Here’s an example…


tell application "Mail"
	set the_selection to selection
	if the_selection = {} then return
	set the_message to last item of the_selection
	set selected_mailbox to the_message's mailbox
	display dialog selected_mailbox as string
end tell

Select a message (just click on it so it is highlighted in the list) in “Mail” and then run this script. It should put the name of the mailbox in which that message is filed into a dialog box. Instead it fails because “The variable selected_mailbox is not defined.” Keep the event log open while running this script and you will see something like this (depends on what you have selected)…

This makes it pretty clear that Mail’s AppleScript support is broken. There is a mailbox element in the message, but we can’t get at it when we ask for it. Similar problems for other elements of messages (try “content” for example). Let’s hope this gets fixed soon.

Now, for my question: can I get at the mailbox name some other way? Specifically, the event log shows the name (!) so AppleScript must have some sort of access to it. Can I somehow navigate to the “parent” object of the message (i.e. the mailbox) and then query it for its name directly.

How do you get to the “parent of the_message” in AppleScript?

I’m new to AppleScript (or newly returned after 12 years away), so please forgive me if I’ve got some of the technical terms wrong.

Thanks,
…Eric

AppleScript: 1.10
Browser: Safari 412.2
Operating System: Mac OS X (10.4)

Hi Eric,

If I’m right you want just the name of the mailbox.

This is harder than it should be because the mailbox property of messages always returns ‘missing value’ (very helpful - I’d call it a bug). This script gets the message id and loops through the mailboxes of each account, and then the mailboxes that are not attached to accounts. Hmm.

Best wishes

John M

tell application "Mail"
	set the_selection to selection
	if the_selection = {} then return
	--get id of message
	set the_message to id of last item of the_selection
	--Loop through accounts
	repeat with myAccount in accounts
		--loop through mailboxes of account
		repeat with myMailbox in mailboxes of myAccount
			set myList to id of messages of myMailbox
			if myList contains the_message then set selected_mailbox to myMailbox
		end repeat
	end repeat
	--loop through local mailboxes
	repeat with myMailbox in mailboxes
		set myList to id of messages of myMailbox
		if myList contains the_message then set selected_mailbox to myMailbox
	end repeat
	--get name from mailbox reference
	set mailboxName to name of selected_mailbox
end tell

display dialog mailboxName

John, thanks for that idea. I do, indeed, want to find out the mailbox of the message and am frustrated by the “bug” that leaves this value undefined. This method worked with earlier versions of Mail, I think it was broken by Tiger and I hope it is fixed again soon.

In the meantime, while your method may work with smaller collections of mail, it fails in mine. The problem is that I have over 120,000 messages in over 200 mailboxes. Extreme, but true! I tried your script and it timed out, not to mention left Mail itself hanging due to the aborted AppleScript.

I’ve got to believe that since the event log does display the mailbox associated with the message there must be a way for a script to get this information as well. After all, how does it make its way to the event log? Most object oriented languages (which AppleScript seems to be, at heart) offer a way to trace back to the parent of an object. Since in Apple’s Mail model messages are contained in mailboxes (see the event log entry "message id 138732 of mailbox “Orgs…/DLF/DLF-DODL” as an example), all I need is the equivalent of “set mailbox to parent of message” or “set mailbox to container of message”. Of course, both “parent” and “container” have other meanings in AppleScript, so they don’t work like this. My question is, does anything? Is there any way for me to step back through the set of objects that are “of” each other?

Still curious,
…Eric

Hi Eric,

If you want this bug fixed I suggest you report it to Apple. the ADC Bug Reporter http://bugreport.apple.com needs an ADC membership, there is a free membership.

Best wishes

John M

Thanks, John. I’ve gone ahead and reported to Apple even though I’ve seen this bug documented on other sites and even seen notes of bug reports about this marked “duplicate”. It is clearly a known problem at Apple.

Still wondering if there is any way to reference “parent” objects in a generic way, though. Maybe this is just impossible in AppleScript?

…Eric

After a bit of hunting I came up with a workaround for the bug in Mail’s AppleScript handling. Remember, the bug was that Mail does not fill in the mailbox property of messages. I’ve found a way to misuse some error handling to get me the information I need:


tell application "Mail"
	set the_selection to selection
	if the_selection = {} then return
	try -- we will force an error here
		set the_list to the_selection as string
	on error msg -- so that we can generate this error string
		set selected_mailbox to my error2mailbox(msg)
	end try
	display dialog selected_mailbox
end tell

on error2mailbox(error_msg)
	-- this is a workaround for Mail's failure to fill in the mailbox property of messages
	-- "set mailbox_name to mailbox of the_selection" should work, but does not
	set old_delimiters to AppleScript's text item delimiters
	set AppleScript's text item delimiters to ASCII character 34 -- the quote
	set mailbox_path to second text item of error_msg
	set AppleScript's text item delimiters to "/"
	set mailbox_name to last text item of mailbox_path
	set AppleScript's text item delimiters to old_delimiters
	return mailbox_name
end error2mailbox

I hope this helps someone else stuck with this dilemma!

Have fun,
…Eric

Here is a slightly cleaner version of the workaround. This one will work more gracefully when Apple fixes the bug in Mail.


tell application "Mail"
	set the_selection to selection
	if the_selection = {} then return
	set selected_mailbox to my mailboxOfMessage(the_selection)
	display dialog selected_mailbox
end tell

on mailboxOfMessage(the_selection)
	try
		-- should work, but a bug in Mail fails to set the mailbox of a message
		set mailbox_name to mailbox of last item of the_selection
	on error error_msg
		-- so we workaround by parsing the error itself
		set old_delimiters to AppleScript's text item delimiters
		set AppleScript's text item delimiters to ASCII character 34 -- the quote
		set mailbox_path to second text item of error_msg
		set AppleScript's text item delimiters to "/"
		set mailbox_name to last text item of mailbox_path
		set AppleScript's text item delimiters to old_delimiters
	end try
	return mailbox_name
end mailboxOfMessage

…Eric