Ben Dodson

Freelance iOS, Apple Watch, and Apple TV Developer

Syncing Apple Music with Spotify

Before Apple Music launched in April 2015 I was a longtime Spotify user and subscriber. I maintained a playlist I affectionately called Ben Dodson’s Definitive Hits Collection which contained nearly 45 hours of songs I thought were particularly good1. On most Tuesday nights, my friend and podcast co-host John Wordsworth and I play a few rounds of Rocket League and we will regularly have the Definitive Hits on whilst we play. There are two issues with this:

  1. As I use Apple Music now, I don’t pay for a Spotify premium account and so I have to put up with adverts (which are utterly terrible).
  2. They aren’t in sync so we might be humming (or badly singing) along to a song that the other person isn’t listening to.

Now I could just recreate the playlist in Apple Music to solve the Spotify ads issue but we still wouldn’t be in sync. As we’re both developers, we decided to remedy this problem with a fairly convoluted solution…

The basic idea is that John acts as the host with the playlist on Spotify (on macOS) playing into his headphones. He has written an app that checks if the track has changed and, if it has, sends the track information to my server. I then use the iTunes Search API to look up the song and find the correct identifier which is then sent to an app on my iPhone via push notification to start the song playing on Apple Music.

I’ll run through each piece and go over the challenges that were encountered.

Retrieving track details from Spotify

I hadn’t heard of it before but Apple has provided a tool called Scripting Bridge since macOS 10.5 which allows you to interface with AppleScript from other programming languages such as Python and Ruby. With this, John was able to write an app that polls Spotify regularly2 to see if the track has changed. If a change is detected, the title, artist name, and album name are all sent to my server so I can begin the process of matching the song on iTunes. In future, we may add more information (track number on the album, duration, etc) in order to try and match better but this is working well enough currently.

Finding a track on Apple Music

The next step is for the server to take the information that has been sent and use the iTunes Search API to try and find a match. This is fairly straightforward and a first draft would send a request like this:

https://itunes.apple.com/search?entity=song&term=never+gonna+give+you+up+rick+astley&country=gb

Unfortunately the iTunes API does not allow you to search multiple terms (i.e. artist=rick+astley title=never+gonna+give+you+up) so everything has to be concatenated together which leads to an issue; sometimes the song you expect is not the one you get. For example, consider the song She Looks So Perfect by “5 Seconds of Summer”; If you search for this, the first result on the iTunes API will actually be a the “Ash Demo Vocal” version of the song which is not the one we want. To resolve this, we started sending the album information (in addition to title and artist name) so I could match that manually by iterating through the results; I then only choose the first result if there isn’t a song in the list with the same title and album name.

The next issue I encountered involves the Romanization of Belarusian; the track Solayoh is rightly attributed to Alyona Lanskaya on Spotify but Apple Music uses Romanization so it becomes Alena Lanskaya. If you search term=solayoh+alyona+lanskaya then you get no results. To fix this issue, if no results are returned from the iTunes API then I then do a search for the title alone and return the first result as that works in 99% of cases.

The final issue on the API side revolves around remastered tracks. The song A Horse with No Name is listed as A Horse with No Name - 2006 Remastered Version on Spotify but Apple Music doesn’t include that suffix even though they have the exact same version of the album. To fix this, if there are no results returned (again) then I split the string by non-alphanumeric characters and just try the first part in the lookup. Again, this seems to work in 99% of cases.

Once I have a track, I take the identifier and send it within a push notification along with the server time before I started making API calls (you’ll see why shortly). I use a silent push notification via the content_available flag as I want to wake the app up and run some code but not actually display anything to the end user.

The iOS App

The final piece of the puzzle is an iOS app with a fairly minimal interface3

The key thing for the iOS app to do is to play the track that comes from the push notification. This is fairly easy with an MPMusicPlayerController but we run into problems when the app is in the background as whilst the app will wake up from the silent push it isn’t allowed to play music.

That said, we can enable the background audio capability that allows us to control audio from the background but it only works if audio is already playing. To remedy this, I play a 5 minute track from the album “Silent Tracks of Various Useful Lengths” (id #366737838) on repeat so that the app is continuously playing music… it just happens to be silent music4.

Once a silent push is received, it starts to play the track but it also adds the 5 minute silent track to the queue. This is important as it prevents the background audio from terminating should I have a different length of music to Spotify or if a push is delayed due to network reasons. In essence, a normal track will be played followed by a track of silence whilst it waits for the next notification.

The final issue to solve is one of latency; there is a lot of latency inherent in this setup as we are polling Spotify, sending data to a server, doing one or more lookups against the iTunes API, relying on a push notification, and finally buffering the song in Apple Music! In order to keep us roughly in sync, the app will connect with my server when enabled and fetch the server time so that it can keep time5. When the push notification comes in, it contains a timestamp from when the server was first hit by the macOS app and I can then calculate the offset in order to skip into the track a bit.

For example, lets suppose John starts listening to C’est La Vie by B*Witched6 and his app hits my server at 1485359762 seconds from the unix epoch. This is recorded and sent in the push notification along with ID #298026101. If that process takes 3 seconds, then the iPhone app will know the server time is now 1485359765 and can work out that it needs to skip forward 3 seconds in the song in order to keep me in sync.

Amazingly, this crazy system actually works and we are able to have our playlist synced and ad free on two completely separate streaming services. I built my portion of the project as an iOS app as Windows does not have access to Apple Music yet I play Rocket League on the PC; in order to actually hear the audio, I wear a single AirPod in my right ear underneath my Turtle Beach X10 Headset so I can hear the music but still get the audio from the game and Skype.

It was only after we’d got it working that we realised we could have just set up some form of streaming radio server but that likely wouldn’t have been as much fun…

  1. The actual criteria to add songs is simple; I either have to use the phrase “it’s a classic” to be able to describe the song or it has to be “catchy as f**k”. ↩︎

  2. An improvement would be to hook into some sort of notification so that the app can be told when Spotify changes track rather than polling every second but this works well enough for now. ↩︎

  3. The switch simply activates the app as I’m using various background modes and don’t want my phone to randomly start playing music if John is listening to Spotify whilst we aren’t gaming! ↩︎

  4. I was originally planning on using the track 4′33″ until I found the album of silent audio. ↩︎

  5. Originally I would get the timestamp and then start counting it up with an uptime C method. This had some issues when the device was in standby so I made it simpler and I just work out the offset between the system clock and the server date; then, when I want to know what time it would be on the server, I can just add the offset to the system clock. ↩︎

  6. It’s a classic. ↩︎

Some thoughts on Apple's new Alternative Tier A and B pricing strategy for apps

Apple increased their prices for apps in the UK yesterday due to the current changes in the GBP vs USD exchange rate. One of the interesting changes that came with this were two new “alternate tiers” which would allow developers to maintain the previous 79p price point or drop it down to 49p. I was asked about this by BBC News and gave this quote:

I don’t think many publishers will respond to that change. It’s just throwing money away and there’s no reason to give people in the UK a discount. I certainly won’t be discounting my own apps.

I stick by that today as I don’t see why developers should be penalised for Apple adjusting to economic conditions; it is a change in price that UK users will get used to in the same way they did when the lowest tier changed from 59p to 69p and then again to 79p. This is especially true bearing in mind that the US App Store doesn’t have sales tax included whereas the UK does have VAT (so at current exchange rates a $0.99 app would work out around £0.96).

The key thing though, and something I didn’t clock onto fully until looking again at the charts today, is that Alternative Price Tier A and B doesn’t apply just to the UK; they change prices in many places such as China, Australia, and Canada but maintain them in other places such as Japan and Denmark. If you went for Tier A you’d be reducing the price of your app by 50% in the UK but reducing it by a whopping 83% in China! There are also a few odd choices such as Canada’s pricing being $1.39 at Tier 1 (which is $0.99 in the USA) but it drops to $0.99 for both the A and B Alternate Tiers.

If you are a worldwide developer wondering about which tier to choose, I would urge you to stick with the basic Tier 1 pricing. If you choose something like Alternate Tier B to maintain the old price for the UK, you could be dropping prices dramatically in other regions as well. I’m not sure why Apple decided to introduce these tiers but they are not helpful to developers, especially at a time when we should be trying to get away from the bargain basement $0.99 apps that are so prevelant.

If Apple want to reduce prices further, perhaps they should start by lowering their 30% cut?

Sporta 2.0

I’m pleased to announce the release of a new client app I worked on late last year: Sporta.

Sporta is an app to keep football fans up to date with the latest matches via local notifications in advance of a game. You simply select which teams you are interested in from the Premier League, Sky Bet Championship, The FA Cup, the Scottish Premiership, or international matches featuring England, Scotland, Wales, or Ireland. You can then choose a reminder time prior to the match (from 5 minutes up to 1 week) and the app will automatically send you a local notification to remind you about the match with details of kick off time, the teams involved, and the venue.

I was originally contacted by the creator to update the existing version of Sporta but I found that the code wasn’t suitable for me to work with due to a combination of out-dated code and offshore developers with poor documentation. Instead, I proposed that re-building the app from scratch with Swift 3 and modern iOS updates (such as AutoLayout to work on all sizes of iPhone and the new permissions systems for notifications introduced in iOS 10) would actually be faster than trying to untangle what was there. I was quickly able to recreate the app and scale it for different iPhone sizes whilst adding an intelligent system for keeping the app constantly up to date; the API for the match updates is called periodically using a combination of Background App Refresh and silent push notifications to ensure that data is always up to date and notifications will always fire at the right time even if the phone happens to be offline1. Finally, I used the Realm mobile database in order to store the match data and be able to quickly execute queries such as “fetch all fixtures that contain teams x, y, and z as either the home or away team”.

This was a really fun project to work on and I’m particularly pleased with how reliable the notifications are. If you are a football fan, you can download Sporta on the App Store.

  1. The naïve way of doing this would have been to use standard push notifications from a server at the appropriate times but these are not guaranteed to be delivered quickly or at all. Also, you’d need to send data from the phone if you changed your team selection or notification period whereas with the local database system I created you can do that entirely offline and it’ll just work (as I store all upcoming fixtures locally on the device). ↩︎

Booktrim for iPhone

I’m very pleased to announce the launch of a recent client app I developed; Booktrim.

Booktrim is a hassle-free app that allows customers to quickly browse barbershops, book a haircut, and pay right from their iPhone. I built the app in Swift and made use of AutoLayout to ensure that everything scales beautifully across the various iPhone Sizes and I worked closely with Trim Ventures’ API developer in order to ensure best practices. I was also instrumental in the design of the application and making sure that the user experience was optimised for making quick appointments on the go.

Once the app was completed, I was asked to build TRIMbook, an app for barbers which allows them to manage their appointments and availability. Once again, the app was built with Swift and I was key in both designing the UI and ensuring the API was being used efficiently. I worked closely with the Trim Ventures team to publish both apps on the App Store and also to run wider beta tests via TestFlight prior to launch.

This was an interesting project to work on and I think the end product works well. You can download Booktrim from the App Store or learn more on their website.

Don't be the idea person

I’ve been a fan of Dilbert since the mid-‘90s1 and this week a lot of my friends (and some clients) sent me this strip from November 13th:

Like most things, it’s funny because it’s true. I get several of these types of pitches per week and they never fail to amuse me. I’ve written about this in detail previously but I still get people who believe they have the next big idea and that it is worth something.

Ideas are worth nothing. Absolutely nothing. It is implementation that is worth something.

The analogy that I always like to use is that of an architect and a builder. Most software developers are builders that take some detailed plans and create to that specification. The “idea person” should be an architect with a clear vision and enough knowledge to know what can and can’t be done. Unfortunately this is rarely the case. Your typical “build my app idea” guy will have no knowledge of what can and can’t be done and therefore no understanding of the time and complexity there is in turning it into a reality. They just assume that they were the first person to think of a life changing idea and that it will be easy money for whoever builds it. It would be like delivering your kids drawing of a house to a builder and expecting them to have it built, for free, by next week2.

If you want to be taken seriously, do your research. Speak to developers and find out what is and what isn’t possible as the vast number of ideas I receive just aren’t possible given the constraints of software on iOS3. Then, once you’ve understood the process, either pay a developer for a basic MVP4 or pitch to investors to get enough funding to build one.

Don’t ever be “the idea person” and don’t ever expect other people to work for you for free. The world does not work that way.

  1. I have around 14 compendium books of the strips; my favourite is entitled “Still Pumped From Using The Mouse” (a reference to a calendar they were making about software developers). ↩︎

  2. “Oh, and by the way, there is a pool at the back and another floor but I didn’t draw that part” ↩︎

  3. “Can you give me the details for Apple then as this should really be installed by default on every phone - it’s a billion dollar idea”. Genuine email I received when I pointed out an idea wasn’t possible. ↩︎

  4. “Minimum Viable Product”, basically a step above a prototype that you can use to gauge interest from consumers and investors. The bare minimum you need to launch. ↩︎

Updates to iTunes Artwork Finder

Last week, my iTunes Artwork Finder script stopped working due to some changes by Apple with regards to rate limiting. In the past, searching for something on my site would cause my server to send a request to Apple and get the data back but with so many people using it my server would get blocked within a few seconds.

After a brief shutdown1, I’m happy to say that my iTunes Artwork Finder is now back up and running again thanks to a few tweaks. Now, instead of sending all requests from my server, it works like this:

  1. When you enter a search term (i.e. “Fall out boy” albums in United Kingdom), that is sent to my server where I’ll generate the correct URL that is needed for Apple’s servers
  2. Your browser then takes that URL to make the request directly to Apple
  3. When the data is returned from Apple, the browser then sends it to my server for processing
  4. Results are then displayed!

This means that there are now 3 network requests instead of 1 but the crucial part is that all requests to Apple’s servers are now made from your own browser so the rate limiting shouldn’t be a problem2.

Whilst not an ideal solution, it does work and means I can keep everything running for a bit longer. I’m hopeful that Apple will alter how their rate limiting works as at the moment it seems a bit broken, especially with it being required for several apps with the new Apple Music APIs.

The code for the artwork finder is available on GitHub although this uses the old PHP request system rather than my new version as that should be more than good enough for personal usage3.

If you run into any problems, please get in touch.

  1. During which I received around 80 emails hoping that it would come back online - thanks! It’s nice to know that so many people use the site; I have no analytics on my website so seeing so many people get in touch made me realise how big it has become. ↩︎

  2. Unless you try and do around 50 searches in short succession in which case you’ll need to wait a bit before you can make more requests. ↩︎

  3. And if you want to do more than just personal usage you should speak to me first as I don’t really want people to create entire duplicates of my own project. ↩︎

Vortech

Update (9th Nov 2016): I’ve updated this article to reflect the new name for the app, Vortech. Whilst submitting a v1.0.1 update (adding support for some extra figures), Apple took issue with the name Dimensions so I had to change it…

I’m very happy to announce that my latest self-published app, Vortech, is now available on the App Store.

Vortech is a character and ability tracker for the videogame LEGO Dimensions. It allows you to easily see all 52 currently available characters (waves 1-6) and 73 abilities and track them in your own collection. Whilst there are other tracking apps available (namely the official LEGO Dimensions app), these tend not to be as easy to use and they don’t allow you to cross-reference the special abilities and powers of characters.

I built the app as I would occassionally come across something that required a special ability and the game might show me a character with that ability. However, as I have a fairly large collection already, it is likely I have a character with the ability and just need to look up which one has it. For example, I might find an area in a level which requires the Sonar Smash ability and the game might show me the character Benny (from The LEGO Movie) as someone with this ability; with my app, I can quickly see who else has that abilty and find I have Marty McFly (from Back To The Future) who will do just as well!

The entire app is built using Swift 3.0 and I use Realm as a mobile database containing all of the character information that I scraped from the official LEGO Dimensions website1. I added a few nice touches such as Peek & Pop support for 3D Touch enabled devices and taptic feedback for the iPhone 7 models. The app is completely free and contains no in-app purchases, adverts, or analytics tracking – it doesn’t even require an internet connection!

You can download Vortech on the App Store and learn more about it on my Dodo Apps website.

If you find Vortech useful, I’m always grateful for a review on the App Store. If you run into any issues or have feature requests, you can contact me directly.

  1. I built a custom scraper using PHP to periodically check the LEGO website and extract the image, abilities, and other information about each character. This then sends me a Slack notification at which point I can regenerate a JSON file and image bundle which I then include within the app. I’d thought about doing push notifications and remote updates for the app but as this is just a free hobby app (and the information only updates every few months) I figured doing it through the App Store will be fine for now. ↩︎

Kylo Ben

I have three main hobbies; coding, video games, and LEGO. With the first, I’m fortunate to have a flexible job that allows me to code on tons of different and varied projects every day. With the last, I’ve literally run out of space for the models I already have (most of which are over 2000 bricks in size). Video games, then, are really my main hobby. In the last year I’ve started a podcast on co-operative gaming, built a powerful gaming PC, and spent somewhere in the region of 900 hours playing games. Today I’m happy to announce a new website I’ve been working on dedicated to my gaming hobby; it’s called Kylo Ben:

Kylo Ben is divided into several different sections:

Articles

I’m currently varying between reviews, things I’m excited about, and general thought pieces on the industry. So far, I have published:

I’m trying to write new pieces every couple of days and it has proven to be a good way to practice my writing and get some long form thoughts out that don’t fit neatly into a 140 character tweet. It also means I can keep these game centric pieces away from my more work-oriented blog here at bendodson.com.

About

I’ve listed a few things about my current gaming setups on my about page. It details the components in my gaming PC, my current console and mobile gaming systems, and a look through the various consoles I’ve owned since I started gaming in 1991.

Games

I have a single page which lists all of the games I currently own on both Steam and my Xbox One. Each game has more details including purchase date, last played, total gaming time, and a short note about where I’m currently at with the game. I also list any articles related to that game for easy reference (and vice versa). For example, here is the entry for Mini Metro.

Gaming Time

This is perhaps my biggest achievement; a complete log of time spent on each game. The page updates daily and will list each game I’ve played over the last 2 months along with duration and a link through to more details. This is done through a combination of two custom scripts I wrote to scrape both my Steam library and Xbox Live / Windows 10 account periodically for changes. It’s been fascinating for me to see exactly how long I’ve spent on certain games (*cough* Peggle 2 *cough*) and will allow me to easily write a regular piece on games I’ve played over the previous month.

I’m really excited to be writing regularly about my biggest hobby and I’m looking forward to posting frequently for the foreseeable future. I have a few extra things to announce soon including some apps and game mods so follow me on Twitter for the latest updates. Alternatively, there is an RSS feed available for Kylo Ben which will keep you up to date on any new articles. If you have any thoughts or suggestions for improvements, please get in touch.

Working Remotely

I was recently asked by Remote.co to take part in a new Q&A section about remote workers. You can read the full Q&A on their website but I’ve put some of their questions and my answers below:

What advice would you give someone considering going remote?

Discipline. It takes a lot of discipline to work remotely as you’ll find that it is very easy to put off a piece of work when you’re sitting at home. There are no firewalls stopping you from accessing Facebook and Twitter, the Xbox might be sat saying “just one more game”, and before you know it a month has passed and you’ve done nothing.

How do you avoid becoming distracted when working remotely?

I have a pair of noise-cancelling headphones that I bought for working in an open-plan office but they work at home for me as the act of putting them on puts me into “work mode”. The only problem was that if the doorbell went (sidenote: great advantage of working from home is you never miss an Amazon delivery) I wouldn’t hear it; I fixed that by hooking it up to a Philips Hue lightbulb on my desk so I get a visual alert.

Do you have a dedicated home office?

I do have a dedicated room for work. I have a small desk with a 5k iMac and an external 1080p monitor in portrait mode (I find this better for webpages and iPhone simulators). Apart from the computer, my desk only has space for my tea and water and a Blue Yeti microphone I use for podcasting and Skype. I have lots of bookshelves (mainly full of LEGO) and a small orchid by the window.

What’s the hardest part about working with a traditional team while you’re remote? How do you overcome it?

I find the hardest thing is that traditional teams will want to have meetings all the time. They also want you to pop into the office fairly frequently for reasons unknown to me. I’m pretty good at telling prospective clients that I only work remotely and that I don’t do daily catch up calls; I get a good handle for the project and then do a week or two of work before sending over a build for feedback.

MailRoute blacklisting via email

I’ve been using MailRoute on and off for the past few years1 in an effort to reduce the amount of spam in my inbox but there is one missing feature that always drives me nuts; there is no way to blacklist an email address or domain without going to their website. Whilst you can whitelist domains easily from the daily digest of caught spam, there is no feature that lets you forward spam to them in order to have it blacklisted (despite people, including me, requesting it since 2013). After having a look at the MailRoute API, I decided it was time to fix this myself.

There are several components in getting this working.

  1. I created a new email address with Gmail which will catch my forwarded spam2.
  2. I set up an account with Context.io and connected it to the gmail account3.
  3. I put the following code available on GitHub on a 15 minute CRON job
<?php

require_once 'OAuth.php';

define('CONTEXT_KEY', 'your-contextio-consumer-key');
define('CONTEXT_SECRET', 'your-contextio-consumer-secret');
define('CONTEXT_USER_ID', 'your-contextio-user-id');
define('CONTEXT_TRASH_NAME', '[Gmail]/Trash'); // change if not using Gmail

define('MAILROUTE_USER', 'your-mailroute-username'); // should be your email address
define('MAILROUTE_API_KEY', 'your-mailroute-api-key');
define('MAILROUTE_EMAIL_ACCOUNT_ID', 'your-mailroute-email-id'); // numeric - can be found in admin.mailroute.net network traffic

$whitelist = ['sending@example.com']; // add the email address you are forwarding from or you'll blacklist yourself...

$inbox = performOAuthRequest('GET', 'https://api.context.io/lite/users/'.CONTEXT_USER_ID.'/email_accounts/0/folders/inbox/messages');
foreach ($inbox as $message) {
    $id = $message->{'message_id'};
    $body = performOAuthRequest('GET', 'https://api.context.io/lite/users/'.CONTEXT_USER_ID.'/email_accounts/0/folders/inbox/messages/'.$id.'/body');
    $content = str_replace('<', '', str_replace('>', '', $body->bodies[0]->content));
    $emails = extractEmailAddresses($content);
    foreach ($emails as $email) {
        if (!in_array($email, $whitelist)) {
            performRequest('POST', 'https://admin.mailroute.net/api/v1/wblist/', ['email_account' => '/api/v1/email_account/'.MAILROUTE_EMAIL_ACCOUNT_ID.'/', 'email' => $email, 'wb' => 'b'], ['Authorization: ApiKey '.MAILROUTE_USER.':'.MAILROUTE_API_KEY]);
        }
    }
    performOAuthRequest('PUT', 'https://api.context.io/lite/users/'.CONTEXT_USER_ID.'/email_accounts/0/folders/inbox/messages/'.$id, ['new_folder_id' => CONTEXT_TRASH_NAME]);
}

echo 'DONE!';



// CURL

function performOAuthRequest($httpMethod, $url, $params=[], $headers=[]) {
    $signatureMethod = new OAuthSignatureMethod_HMAC_SHA1();
    $oauthConsumer = new OAuthConsumer(CONTEXT_KEY, CONTEXT_SECRET, NULL);
    $oauthRequest = OAuthRequest::from_consumer_and_token($oauthConsumer, NULL, $httpMethod, $url, $params);
    $oauthRequest->sign_request($signatureMethod, $oauthConsumer, NULL);
    return performRequest($httpMethod, $oauthRequest, $params);
}

function performRequest($httpMethod, $url, $params=[], $headers=[]) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 20);

    $headers[] = 'Content-Type: application/json';
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    if (!in_array($httpMethod, ['GET', 'POST'])) {
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $httpMethod);
    }
    if ($httpMethod != 'GET') {
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
    }
    $output = curl_exec($ch);
    $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    return json_decode($output);
}



// Email parsing

function extractEmailAddresses($string) {
   $emails = array();
   $string = str_replace("\r\n",' ',$string);
   $string = str_replace("\n",' ',$string);

   foreach(preg_split('/ /', $string) as $token) {
        $email = filter_var($token, FILTER_VALIDATE_EMAIL);
        if ($email !== false) { 
            $emails[] = $email;
        }
    }
    return array_unique($emails);
}

Now all you need to do is forward any spam you receive to the Gmail account you set up. Every 15 minutes, the CRON job will run and check the inbox for any emails. When it finds some, it will parse them for email addresses and blacklist them with MailRoute before deleting them.

In an ideal world, MailRoute would implement a custom email address for blacklisting but this seems to be working for now.

  1. I stopped using MailRoute a while back and was using the black hole feature of Sanebox but I’ve just stopped using them as found the free service FollowUpThen - I was getting a lot of spam after the switch off so decided to re-activate MailRoute this week. I use Fastmail for my email in case you were wondering. ↩︎

  2. As you’ll be forwarding emails to Gmail, you’ll want to disable its spam filter as otherwise your emails won’t end up in the inbox for processing by Context. To do this, you’ll need to set up a new rule which matches the email ‘@’ and ensures it never goes to spam. ↩︎

  3. Whilst I could connect Context to my personal email and just move things into a folder for blacklisting, I don’t trust services with access to my email account, certainly not services that are free and are using the data. ↩︎

« Older Entries Newer Entries »