I’m reting to display a list of Mail’s mailboxes with the choose list command and have them pick a mailbox. code is:
tell application "Mail" to set mboxList to the name of every mailbox
set usrchoice to choose from list mboxList with prompt "Choose mailbox" default items "Inbox"
The code works OK but doesn;t indicate the hierarchy of the mailboxes. For example if I have mailbox named “Green” inside a mailbox named “Colours”, the list only shows “Green” with no indication that it is contained by “Colours”
If I get a list of ever mailbox from Mail, it looks like:
{mailbox “Colours/Green” of application “Mail”, …}
How can I extract “Colours/Green” from this list instead of just “Green”?
As a secondary issue, once I’ve done that, I want to sort the resulting list. I know there’s a way to sort Finder itmes but is there a general sort routine for lists?
I think I’ve figured out how to do this with the use of a recursive subroutine. I’m sure the code is not as elegant as it could be but here it is if anyone would like to use it. I still need to sort the resulting list.
global master_mbox_list
global root_mbox_name
tell application "Mail" to set mboxList to every mailbox
using terms from application "Mail"
set master_mbox_list to {}
repeat with thisMbox in mboxList
set myContainer to container of thisMbox
try
set myClass to class of myContainer
on error
-- Trying to get the class of the container of a mailbox that doesn't have any containers causes an error so his means we have a top level mailbox
set root_mbox_name to name of thisMbox
my get_mailboxes(thisMbox)
end try
end repeat
end using terms from
set theMbox to choose from list master_mbox_list with prompt "Pick a mailbox"
on get_mailboxes(mbox)
using terms from application "Mail"
set end of master_mbox_list to root_mbox_name
set temp_mbox_name to root_mbox_name
set subordinate_mbox_list to every mailbox of mbox
repeat with this_subordinate_mbox in subordinate_mbox_list
set root_mbox_name to root_mbox_name & "/" & name of this_subordinate_mbox
my get_mailboxes(this_subordinate_mbox)
set root_mbox_name to temp_mbox_name
end repeat
end using terms from
end get_mailboxes
I ended up taking nearly the same approach. I choose to catch the error of getting the account object’s container instead of the error caused by getting the account object’s class. Here is my code, for what it is worth.
on run
tell application "Mail" to set mailboxListRef to a reference to every mailbox
set mailboxPaths to {}
set mismatches to {}
repeat with mailbox in mailboxListRef
set mailbox to contents of mailbox
set mailboxPath to computeMailboxPath(mailbox)
set mailboxByPath to missing value
try
tell application "Mail" to set mailboxByPath to mailbox mailboxPath
end try
if mailboxByPath is not equal to mailbox then
set end of mismatches to {mailbox, mailboxPath}
else
set end of mailboxPaths to mailboxPath
end if
end repeat
if length of mismatches is 0 then
mailboxPaths
else
{mailboxPaths, mismatches}
end if
end run
to computeMailboxPath(mailbox)
-- this is a bit slow
-- memoization might help for many calls for mailboxes in the same (sub)hierarchy(ies)
set pathComponents to {}
set theName to name of mailbox
-- backtrace the containers of the starting mailbox to collect the path components
-- eventually the container will be an account object, which has no container and will cause an error if we try to get it
-- using "class of container of |mailbox| equals account" also results in an error (trying to get the account object's class also throws an error)
repeat until theName is missing value
set beginning of pathComponents to theName
try
using terms from application "Mail"
set |mailbox| to container of |mailbox|
end using terms from
set theName to name of mailbox
on error
set theName to missing value
end try
end repeat
join("/", pathComponents)
end computeMailboxPath
to join(separator, components)
set {otid, text item delimiters} to {text item delimiters, {separator}}
try
set joined to components as Unicode text
set text item delimiters to otid
on error m
set text item delimiters to otid
error m
end try
joined
end join
If the code looks a bit odd, I was trying to minimize the extent of the tell blocks/statements and the using terms from blocks. I also refused to rename my mailbox variable (thus the bars around the name in the Mail-targeted block). I tested it with Mail Version 2.1.3 (753.1) on my 10.4.11 machine.
For your sorting needs, a simple bubble sort is a common recommendation around here. The search function should turn up several examples (and some more advanced sorts, like quick sort and maybe even a heap sort). If I remember correctly, someone posted a bubble sort example just in the last couple of days.
Thanks Chris, nice to know I’m kindof on the right track. I’ll search for the sort routines.
The code I used does eeem to be on the slow side but it’s part of a function to set up preferences for another process so it probably only gets executed at installation or perhaps once every few months so performance isn’t really a worry.