Mail store size - Extension attribute?

macmanmk
Contributor

Trying to find a way to measure the mail store size via an extension attribute that could then be viewed in inventory. The mail store is for Apple Mail, not Outlook. The potential complication is that there are several different operating systems in the environment and Apple changed the mail database directory in each iteration of the OS, so it could be in any of the following three locations...

~/Library/Mail/V4 (Sierra)
~/Library/Mail/V3 (El Capitan)
~/Library/Mail/V2 (Yosemite and prior)

Has anyone seen an EA that can display these totals?

1 ACCEPTED SOLUTION

mm2270
Legendary Contributor III

@macmanmk That's odd that it would be showing only Not Available. I assume you meant you used the one I posted since that's one of the outputs I included in my script.
I guess you could do like @thoule shows and simply calculate the size of the entire ~/Library/Mail/ directory and not worry about V2, V3, etc. folders inside that. Maybe it's not liking theV* I had in the script.

I wanted to provide another option, if this is something you really want to run across all your Macs, but maybe don't want it consuming time and resources during recons. Have it run once per day as a policy that writes values out to a local file. Then have an Extension Attribute that would pick up that information, which would be as simple as cat'ing the file for example, so it will be near instant on recons.

Here's an example of how I might do it if I was tasked with this. The script I would run, as a policy, maybe just once per day, etc.

#!/bin/bash

while read Acct; do
    if [ -d "/Users/$Acct/Library/Mail" ]; then
        MailDirSize=$(du -sh "/Users/$Acct/Library/Mail" | awk '{print $1}')
        MailSizes+=("${Acct}:  $MailDirSize")
    fi
done < <(ls /Users/ | egrep -v "Shared|Deleted Users")

if [[ ! -z "${MailSizes[@]}" ]]; then
    printf '%s
' "${MailSizes[@]}" > /Users/Shared/MailSizes
else
    echo "No Mail Accounts" > /Users/Shared/MailSizes
fi

A little explanation. This loops over each home directory in /Users/ excluding "Shared" and any possible "Deleted Users" folders. Feel free to add to that egrep line for anything else you see that should be excluded.
It looks for a /Library/Mail/ directory in each home, and if it finds one, calculates the size, and drops the info into an array called "MailSizes" When it exits the loop it checks to see if MailSizes has any data, and if it does, it prints that, with line breaks as the final information into a local plain text file in /Users/Shared/ called "MailSizes"

Then you can have an Extension Attribute pick up the info from that file:

#!/bin/bash

if [ -e /Users/Shared/MailSizes ]; then
    echo "<result>$(cat /Users/Shared/MailSizes)</result>"
else
    echo "<result>Not Available</result>"
fi

Combining these 2 like that will mean you can get that information but not cause every single inventory collection to do a full calculation. It would only happen on the schedule you set for the policy that runs the script above.

Hope that helps.

View solution in original post

6 REPLIES 6

mm2270
Legendary Contributor III

OS version shouldn't matter. You can just direct the du command at a folder in that path that has a V* in it. Keep in mind the only logical way to capture this would be to run the du command on it, which can take some time, depending on how large that folder is. Since this would be happening during inventory collection as an EA, it means your inventory scans will lengthen.

But see if the below as a basis gets you what you're looking for. It shows the size in MBs.

#!/bin/bash

loggedInUser=$(stat -f%Su /dev/console)

if [ -e /Users/$loggedInUser/Library/Mail/V* ]; then
    mailSizeMB=$(du -sm /Users/$loggedInUser/Library/Mail/V* | awk '{print $1}')
    if [ ! -z "$mailSizeMB" ]; then
        echo "<result>$mailSizeMB</result>"
    else
        echo "<result>Unknown</result>"
    fi
else
    echo "<result>Not Available</result>"
fi

If there are multiple accounts on each machine that could have a mail directory, you can change the above to loop over all local accounts and look for those and calculate the sizes. Of course, if it has to calculate several mail directories, it will take even longer to run.

thoule
Valued Contributor II

@mm2270 is right about it taking time. And it'll update at every recon which could be a lot of burnt CPU power. Another option is to put the script into a Casper script and then run it via policy as needed. Then to see results, view policy logs and click 'show'. That may be better if you're going to rarely use this info or only need it for a couple machines.

BTW- Here's a version that shows all users and adds them up at the end.

#!/bin/sh                                                                                                                                                                                                                                                                                                                                                                

spaceUsed=0
re='^[0-9]+$'
cd /Users
for i in *; do
    if [ "$i" != "Deleted Users" ]; then
        if [ "$i" != "Shared" ]; then
            spaceHere=$(du -k /Users/$i/Library/Mail/ |tail -1|awk '{print $1}')
            if [[ $spaceHere =~ $re ]] ; then
                spaceUsed=$(($spaceUsed + $spaceHere))
                echo "<result>$i - $spaceHere
"
            fi
        fi
    fi
done

echo "Total - $spaceUsed k</result>"

macmanmk
Contributor

Thanks for your responses and the warnings about increased CPU drain. I tried the extension attribute script and the output is just being listed as "Not available" for some reason, even though users are logged in at the time of inventory collection.

Running the policy script seemed to work okay, although it may be a bit tedious having to show the results if we do it on each of our 500 machines. One question...I assume the "human readable" (-h) flag doesn't work in scripts? When I tried to modify it, the script would just stop and display no output at all.

mm2270
Legendary Contributor III

@macmanmk That's odd that it would be showing only Not Available. I assume you meant you used the one I posted since that's one of the outputs I included in my script.
I guess you could do like @thoule shows and simply calculate the size of the entire ~/Library/Mail/ directory and not worry about V2, V3, etc. folders inside that. Maybe it's not liking theV* I had in the script.

I wanted to provide another option, if this is something you really want to run across all your Macs, but maybe don't want it consuming time and resources during recons. Have it run once per day as a policy that writes values out to a local file. Then have an Extension Attribute that would pick up that information, which would be as simple as cat'ing the file for example, so it will be near instant on recons.

Here's an example of how I might do it if I was tasked with this. The script I would run, as a policy, maybe just once per day, etc.

#!/bin/bash

while read Acct; do
    if [ -d "/Users/$Acct/Library/Mail" ]; then
        MailDirSize=$(du -sh "/Users/$Acct/Library/Mail" | awk '{print $1}')
        MailSizes+=("${Acct}:  $MailDirSize")
    fi
done < <(ls /Users/ | egrep -v "Shared|Deleted Users")

if [[ ! -z "${MailSizes[@]}" ]]; then
    printf '%s
' "${MailSizes[@]}" > /Users/Shared/MailSizes
else
    echo "No Mail Accounts" > /Users/Shared/MailSizes
fi

A little explanation. This loops over each home directory in /Users/ excluding "Shared" and any possible "Deleted Users" folders. Feel free to add to that egrep line for anything else you see that should be excluded.
It looks for a /Library/Mail/ directory in each home, and if it finds one, calculates the size, and drops the info into an array called "MailSizes" When it exits the loop it checks to see if MailSizes has any data, and if it does, it prints that, with line breaks as the final information into a local plain text file in /Users/Shared/ called "MailSizes"

Then you can have an Extension Attribute pick up the info from that file:

#!/bin/bash

if [ -e /Users/Shared/MailSizes ]; then
    echo "<result>$(cat /Users/Shared/MailSizes)</result>"
else
    echo "<result>Not Available</result>"
fi

Combining these 2 like that will mean you can get that information but not cause every single inventory collection to do a full calculation. It would only happen on the schedule you set for the policy that runs the script above.

Hope that helps.

sean
Valued Contributor

You can use Applescript to return accounts and paths to accounts if you wanted to

tell application "Mail"
    get name of every account
end tell

You can get the directory (and you could grab the size of a directory), e.g. for an account called "iCloud":

tell application "Mail"
    set a to (account directory of account "iCloud")
    get size of (info for a)
end tell

Throw in a loop for each account, if required.

Alternatively, you can just use find to grab all the relevant folders and return the folder size of each.

find /Users/*/Library/Mail -maxdepth 1 -mindepth 1 -exec bash -c 'du -h -d 0 {} | cut -f 1' ;

As mentioned above, you are better off writing the output to a file by a trigger and then using the EA to read that file to reduce frequency.

macmanmk
Contributor

@mm2270 Thanks very much for that suggestion. I think that is exactly what I am looking for and appreciate your solution. I modified the script slightly to ignore our local admin account and now the EA is showing just the user data I was seeking.