Can Mail show a folder's total message count next to the folder name?

Apple Mail displays the number of unread messages in each folder in its sidebar:

enter image description here

Is there any way to make it display the folder's total message count (read plus unread) in addition to, or instead of, the unread message count?

Plugins/hacks welcome, as I’m guessing this won’t be a built-in option.


Solution 1:

Since hacks are welcome:

The idea is to use AppleScript to rename folders. For example:

@REPLY

will be renamed to something like

@REPLY (34)

where 34 is @REPLY's total message count.

A working implementation of such a script that renames mailboxes prefixed with @ is (tested on OS X 10.8.2 with Gmail and AIM accounts):

-- Check whether Mail is running
tell application "System Events"
    if not (exists (processes where name is "Mail")) then return
end tell

tell application "Mail"
    -- Loop over mail accounts
    repeat with myAccount in accounts
        -- Loop over mailboxes
        repeat with myMailbox in mailboxes of myAccount
            if name of myMailbox starts with "@" then
                set nameOfMyAccount to name of myAccount
                -- Help Mail.app's AppleScript suite cope with Gmail
                if nameOfMyAccount is "Gmail" then
                    set nameOfMyMailbox to "[Gmail]/" & name of myMailbox
                else
                    set nameOfMyMailbox to name of myMailbox
                end if
                set currentMessageCount to the (count of messages of mailbox nameOfMyMailbox of account nameOfMyAccount) as Unicode text
                set messageCountShownInMailboxName to (do shell script "echo '" & name of myMailbox & "' | /usr/bin/sed -E 's/.* \\(([0-9]+)\\)/\\1/'") as Unicode text
                if currentMessageCount is not equal to messageCountShownInMailboxName then
                    -- Strip message count: "@TODO (3)" -> "@TODO"
                    set strippedNameOfMyMailbox to do shell script "echo '" & name of myMailbox & "' | /usr/bin/sed -E 's/(.*) \\([0-9]+\\)/\\1/'"
                    -- Append current count: ""@TODO" -> "@TODO (4)"
                    set newMailboxName to strippedNameOfMyMailbox & " (" & currentMessageCount & ")"
                    -- Rename mailbox
                    set the name of mailbox nameOfMyMailbox of account nameOfMyAccount to newMailboxName
                end if
            end if
        end repeat
    end repeat
end tell

The effect of the script is shown in the following screenshots:

enter image description here

Another implementation that only renames mailboxes specified in a list would be (again, tested on OS X 10.8.2 with Gmail and AIM accounts)::

-- Append message count to these mailboxes
global mailboxesWithMessageCount
set mailboxesWithMessageCount to {"My To Do", "To Reply", "Very Important"}

-- Check whether Mail is running
tell application "System Events"
    if not (exists (processes where name is "Mail")) then return
end tell

tell application "Mail"
    -- Loop over mail accounts
    repeat with myAccount in accounts
        -- Mail.app's AppleScript suite gets confused with Gmail's [Gmail] folder
        if name of myAccount is "Gmail" then
            set mailboxPrefix to "[Gmail]/"
        else
            set mailboxPrefix to ""
        end if
        -- Loop over mailboxes
        repeat with myMailbox in mailboxes of myAccount
            -- Loop over mailboxes which should get the message count appended to their names
            repeat with mailboxWithMessageCount in mailboxesWithMessageCount
                if name of myMailbox starts with mailboxWithMessageCount then
                    set currentMessageCount to the (count of messages of mailbox (mailboxPrefix & name of myMailbox) of myAccount) as Unicode text
                    set messageCountShownInMailboxName to (do shell script "echo '" & name of myMailbox & "' | /usr/bin/sed -E 's/.* \\(([0-9]+)\\)/\\1/'") as Unicode text
                    if currentMessageCount is not equal to messageCountShownInMailboxName then
                        -- Strip message count: "@TODO (3)" -> "@TODO"
                        set strippedNameOfMyMailbox to do shell script "echo '" & name of myMailbox & "' | /usr/bin/sed -E 's/(.*) \\([0-9]+\\)/\\1/'"
                        -- Append current count: ""@TODO" -> "@TODO (4)"
                        set newMailboxName to strippedNameOfMyMailbox & " (" & currentMessageCount & ")"
                        -- Rename mailbox
                        set the name of mailbox (mailboxPrefix & name of myMailbox) of myAccount to newMailboxName
                    end if
                end if
            end repeat
        end repeat
    end repeat
end tell

The effect of the script is shown in the following screenshots:

enter image description here

Both scripts set the message count:

  • @REPLY -> @REPLY (34)

and, only if necessary, that is, when the message count has changed, update it:

  • @REPLY (34) -> @REPLY (29)

My original idea was to run one of the scripts above (or some variation thereof) every time a mail is received with a rule in Mail>Preferences>Rules:

enter image description here

but it can also be added to cron to run every 10 minutes like this (see crontab (5) man page for crontab syntax explanation):

  1. Save the script to /path/to/updateMailMessageCount.scpt.

  2. Open Terminal and type:

    crontab -e
    

    to open your crontab file.

  3. Move with the arrow keys to the end of the file, in case there are any other entries, and press o (lowercase letter o), which adds an empty line and goes into insert mode.

  4. Add this line (the 10 means "run every 10 minutes", change as necessary to match your needs):

    */10 * * * * osascript /path/to/updateMailMessageCount.scpt >/dev/null 2>&1
    
  5. Press esc.

  6. Save and close your crontab with :x!return (in case anything went wrong, type :q!, press return and start over).

(If you ever need to stop the cronjob, open your crontab file with crontab -e, position the cursor over the cronjob and type dd to delete it. Then save the file as explained above.)

You can use Launch Services, too (see this Apple developer document):

  1. Create a script named ~/Library/LaunchAgents/updateMailMessageCount.plist with contents (600 is the interval in seconds, that is, 10 minutes):

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Label</key>
        <string>updateMailMessageCount</string>
        <key>ProgramArguments</key>
        <array>
            <string>osascript</string>
            <string>/path/to/updateMailMessageCount.scpt</string>
        </array>
        <key>StartInterval</key>
        <integer>600</integer>
    </dict>
    </plist>
    
  2. Load the job with:

    launchctl load ~/Library/LaunchAgents/updateMailMessageCount.plist
    

(If you ever need to stop the job, do: launchctl unload ~/Library/LaunchAgents/updateMailMessageCount.plist.)

(My favorite as long time Linux sysadmin is cron, but note that, on OS X, cron has been deprecated in favor of launchd. Both methods worked on my Mac running OS X 10.8.2.)

If you wish to refresh the message count with a keyboard shortcut you can create a service (see http://www.macosxautomation.com/services/learn/index.html for more information):

  1. Close Mail.

  2. Open Automator in folder Applications and choose Service:

    enter image description here

  3. Select Utilities under Library and drag Run AppleScript to the empty pane on the right:

    enter image description here

  4. Configure the service to receive no input in Mail:

    enter image description here

  5. Replace the line (* Your script goes here *) with one of the scripts above.

  6. Save with a descriptive name like Refresh Message Count. The service will be saved to ~/Library/Services/.

Now set up the keyboard shortcut:

  1. Open System Preferences, select the Keyboard preference pane and then the Keyboard Shortcuts tab.

  2. Select Services, scroll down to the service you previously added and set the keyboard shortcut to whatever you want with the following restriction: your shortcut shouldn't conflict with an existing shortcut in Mail. I've chosen controloptionR:

    enter image description here

    enter image description here

  3. Open Mail. Note that there is a new service, accessible with controloptionR:

    enter image description here

(For the curious: if you are wondering where service Reply and Move Sent Message to Current Folder above comes from, see How to save sent messages in same folder as message being replied to? -- warning: shameless plug.)

Now press controloptionR, wait a few seconds and watch how the message count of the folders specified in the script get updated.

Caveats:

  1. Some folders can't be renamed, such as [Gmail]/All Mails or the Inbox folders.
  2. Folders are not renamed in real time. That means that the number you see is an approximate value. If you implement the service, you will be able to refresh it with controloptionR, though.
  3. It can be slow if you have many mailboxes, or if the mailbox has many mails
  4. If you specify a set of mailboxes to rename, be careful that they do not match other folders, for example, "To Reply" will match both "To Reply" and "To Reply Later".

Advantages:

  1. You will see the message count in any mail client, provided you use Mail.app on your Mac and one of these scripts.

Solution 2:

This doesn't answer the question, but as the question encourages hacks and speaks to power users someone may find this useful:

MailMate is a great (paid) OS X IMAP client that supports per folder counts out of the box and much more.

It doesn't have some of the UI polish of Mail.app and Sparrow.app but it makes up in powerful features and customisation.