One of the great things about working in the world of the web is the amount of e-mails I receive. Nothing motivates in the morning like a 3 figure unread email count… No, not really
For my personal email I use Gmail with an intricate array of filters to siphon messages off into different folders as they arrive. For the most part this works OK though some of these folders are effectively proxies for the bin but I can’t quite bring myself to admit it. However for my work email I use Outlook 2016 for Mac. It does support rules but I have found them to be somewhat lacking. The UI for setting them up is hard work, as is testing that they are working as expected. As a result I’ve never gotten beyond setting up a handful of basic rules that do little to stem the tide of email.
Recently I decided to try and sort it out once and for all. Once I had done my obligatory “surely rules must be able to do this… oh god I remember this now… yeah these really are useless…” routine I stared hunting round for better solutions.
This time I also had a specific class of email that I wanted to deal with. I get a lot of notifications from apps that we use at work. For example notifications of Jira updates; passing and failing CI builds; deploy notifications and so on. These emails can be extremely helpful but also have a pretty short lifespan. For example a CI build notification email can be handy for catching an unexpected failure or knowing that a run has finished. I also try and avoid constantly checking emails and instead prefer to periodically review my inbox so the notifications are good there to see what has happened since I last checked in. But they grow stale very quickly and if I haven’t seen them a couple of hours after they arrived I am probably never going to read them. My goal was for these kinds of emails to be automatically archived or deleted once they had been read or when they were more than a couple of hours old, whichever came first.
Clearly there was no way I was ever going to get this to work using rules. I already use Automator to start my work environment at the start of the day so AppleScript seemed like a good place to start trying to implement my rules. After much googling, doc reading and an above average amount of swearing I managed to find the correct incantation that allowed me to manipulate my inbox with ease.
To start with you need to write your script. OSX has a built-in script editor for editing AppleScript — cunningly named Script Editor — which also gives you access to the super-handy dictionary so it is worth getting to grips with just for that. First fire up Script Editor. It will ask you to choose or create a script. I created a new blank script and called it outlook-cleanup.scpt. Now if you go to the file menu you will see an “Open dictionary…” menu item. Click this and you will see a list of your installed applications. Find Microsoft Outlook and select it. You will then be able to browse the dictionary that describes all the elements, classes and properties available for working with Microsoft Outlook. The one I found most handy was the message class in the Mail Suite as this described the properties of the message that I could test against when creating my rules.
Before I could start writing individual rules though, it was necessary to write some initial code to iterate through the messages in my inbox. That looks something like this
I then extracted the properties I wanted to test against into separate variables. Since my key goal involved testing the age of the message I also stashed the current date in a variable along with 2 cut-off intervals that I would switch between depending on the type of message.
Finally I added a bit of logging so I could see that things were happening as expected.
Put all together this looks like this. I’ve added a couple of sample rules so you can see what they look like.
With the script in place the next step was figuring out how to run it on a day to day basis. The solution I settled on was to run the script every 5 minutes using launchd.
To make this work, I first needed to create a Launch Agent or Daemon. According to the docs, Launch Agents are to be run when logged in as a specific user whereas Daemons are system level and run outside of a specific user session. In my case a Launch Agent seemed more appropriate since all these rules are specific to my Outlook account.
I then needed to create a property list file in ~/Library/LaunchAgents. Here is what that looks like. All the other files in ~/Library/LaunchAgents were scoped to a particular domain so I decided to do the same with mine.
I then loaded the script from ~/Library/LaunchAgents using
launchctl load -w uk.co.29ways.outlook-cleanup.plist
Once loaded I tested the script using
launchctl start uk.co.29ways.outlook-cleanup
To tell if the script ran correctly, I used
launchctl list | grep outlook
The second column indicates the return code of the last run of the agent which all being well will be 0. If there was a problem then this will be non-zero and hopefully there will be an indicator in the log of what went wrong
So there we have it. I now I have a self-tidying inbox based on a programmable set of filters that are flexible, easy to update, version controlled and run automatically.
Having got everything up and working I switched from using the Script Editor to using my normal Atom editor. Since AppleScript is a compiled language you need to decompile it before editing and recompile afterwards. Fortunately there is a handy Atom package that will take care of that for you.
I also moved the script and plist into my dotfiles repo and created a symlink for the plist from ~/Library/LaunchAgents to the file in my dotfiles. This way whenever I move to a new Mac my inbox cleansing will move along with all the rest of my configuration.