Mozilla Thunderbird supports having multiple "identities" on a single mail account, which is very helpful if you have your own domain and tend to use different email addresses for different vendors (to auto-sort mail into different folders and track the sources of spam).

Unfortunately the feature seems to have been developed with the idea that you would have two or three identities rather than 30 or so, and it becomes pretty unweildy to find the appropriate email address in a "sorted by date added" list.

Along with the "version inflation" the upgrade from Thunderbird 38 to Thunderbird 45 -- less than a year of development -- (finally!) brought the ability to edit the From: field manually. Which is insanely useful to handle the "one-off" email address use case (eg, when replying just once to something that you signed up with a vendor-specific email somewhere else). That alone allowed me to eliminate about half of the mess of identities I had accumulated over the last couple of years.

Spurred on by having a semi-managable list of identities again, I went looking for a way to make it fully useful -- or at least have the identities sorted in a meanginful order. It turns out that you can use the mail.account.accountN.identities in the prefs.js file to manually sort the identities, where N is the account number whose identities you want to sort (probably "2" for the first non-local account, ie mail.account.account2.identities). It contains a comma separated list of identities, to be precise a "comma separated list of identity ids". And it turns out you can sort it by hand.

To sort it by hand:

  • Quit Thunderbird

  • Go to the Thunderbird Profile Directory, which on OS X can be done with:

    cd
    cd Library/Thunderbird/$(awk -F = '/Path/ { print $2; }' Library/Thunderbird/profiles.ini)
    

    assuming you have only one profile (the normal case; it still escapes me why the normal case is to use a randomly generated profile folder, rather than eg, "Default" or numbering them).

  • In that folder prefs.js contains the identities in mail.identity.idN.* user_pref() key/value pairs, and the mail.account.account2.identities value that describes the order to display the identities.

  • In my case, I wanted to sort the identities by email address, as that is usually the only thing that varies, but to have the default identity (conveniently id1) at the start of the list, and omit the identities belonging to other accounts (which are in their own lists). Conveniently I have only one identity per account for the other accounts, but inconveniently they have "random" idN numbers, found only by:

    grep "\.useremail" prefs.js | awk -F . '/OTHER_ACCOUNT_EMAIL/ { print $3;}'
    

    So that gives me a prefix for my list:

    TB_ID_PREFIX="id1"
    

    and a list of "other account" identities to ignore:

    TB_ID_OTHER="id50,id56"
    

    From those two values we can make a regex to omit those "idN" values from our list with:

    echo "${TB_ID_PREFIX} ${TB_ID_OTHER}" | sed 's/[, ]/|/g; s/^/\./; s/|/\.|\./g; s/$/\./;'
    

    which gives us an answer like:

    \.id1\.|\.id50\.|\.id56\.
    

    and then we can get the remainder of the list with:

    grep "\.useremail" prefs.js | egrep -v "\.id1\.|\.id50\.|\.id56\."
    

    then using the sed expression:

    sed 's/^.*".*\.\(id[0-9][0-9]*\).*", "\(.*\)".*$/\2:\1/;'
    

    we can turn that into a list like:

    test7@example.com:id15
    test2@example.com:id7
    

    which we just need to sort, and turn into a comma separated list of IDs. Which we can do simply by passing the output through:

    sort | cut -f 2 -d : | tr '\012' ',' | sed 's/,$//;'
    

    giving a list like:

    id67,id42,id11,id6,id36,id16,id24,id26,id13,id69,id33,id25,id9,id21,id14,id32,id28,id8,id39,id12,id19,id47,id2,id68
    

    So the final list is our prefix ($TB_ID_PREFIX), and the list above:

    id1,id67,id42,id11,id6,id36,id16,id24,id26,id13,id69,id33,id25,id9,id21,id14,id32,id28,id8,id39,id12,id19,id47,id2,id68
    

    The whole thing looks something like:

    TB_OMIT_LIST=$(echo "${TB_ID_PREFIX} ${TB_ID_OTHER}" |
                   sed 's/[, ]/|/g; s/^/\\./; s/|/\\.|\\./g; s/$/\\./;')
    TB_ID_LIST=$(grep "\\.useremail" prefs.js |
                 egrep -v "${TB_OMIT_LIST}"   |
                 sed 's/^.*".*\.\(id[0-9][0-9]*\).*", "\(.*\)".*$/\2:\1/;' |
                 sort | cut -f 2 -d : | tr '\012' ',' | sed 's/,$//;')
    
    TB_FULL_LIST=$(echo "${TB_ID_PREFIX},${TB_ID_LIST}")
    
  • Make a backup of prefs.js, eg, with:

    cp -p prefs.js prefs.js-bkup-$(date '+%Y-%m-%d')
    
  • Then we just need to replace the value of mail.account.account2.identities in user.prefs with our calculated list:

    perl -i.bak -pne 'if (/account2.identities/) { s/"[^"]+"\);/"'"${TB_FULL_LIST}"'");/ }'
    
  • Check the replacement worked out as you hoped with:

    diff prefs.js.bak prefs.js
    

    and if not, restore the file from either prefs.js.bak or the backup made above. In particular the mail.account.account2.identities line should be the same length otherwise something has gone missing, which is not what we want as we are trying to change only the order.

  • If everything looks good, start up Thunderbird again, so it reads in the preferences file, and check everything works. If not, quick Thunderbird again (possibly declining to set up your accounts...), and restore the prefs.js file from the backup.

  • As a final check, start creating a new message and use the dropdown in the "From:" field to look for new addresses. Hopefully they are now in the sorted order you want.

Unfortunately this is a "one off" manual sort, which means that new identities you add will just be appended to the end (as before). For a few extra identities that's probably okay, but eventually it will probably be useful to re-do this manual sort (at least until Mozilla/Thunderbird decide to make the "Manage Identities" dialog box much more usable).

(The same process could also be used to sort the identities into some other order -- eg, most frequently used to least frqeuently used -- if you can define an automated way to calculate the order required.)