Using Amazon SNS to build good habits with daily SMS reminders

#
By Jeff Gould

Here at Delicious Brains Inc., the entire team enjoys the perks of remote work. Personally, I love having the freedom to start and end my day pretty much whenever I want, but there are some downsides to that lack of structure in my day: I find it hard to remember to do things that would otherwise be a part of a more structured daily routine such as walking my dogs or going to the gym.

I’m sure that a number of readers are shouting at their monitors something like “JUST USE CLEAR!” or, “HAVEN’T YOU HEARD OF SIRI!?” But here’s the thing: traditional reminders or todo apps just don’t seem to work for me. They’re too easy to ignore, or quickly become a part of the noise of reminders, banners, alerts, and notifications that my devices seem to throw at me every few minutes. On the other hand, checking my text messages is already habit for me and I can leverage it to create some new, healthier habits.

I could probably find an app to just email [email protected] every day and be done with it, but ever since work started on WP Offload S3 we’ve been working with Amazon Web Services quite a bit, so I’ve decided to take this opportunity to look into one of the other AWS services: Amazon SNS.

Getting Started

If you haven’t already, you’ll want to sign up for AWS and SNS.

We’ll be writing a PHP script using version three of Amazon’s AWS SDK for PHP, so let’s get started by setting up a new project folder and using Composer to require the SDK. If you need a quick introduction to installing and using Composer, check out the first part of Gilbert’s article Using Composer to Manage Themes and Plugins or the AWS guide.

First, let’s create a project folder called sns-reminders and open it. I’m working on the command line so I’ll use the following command:

$ mkdir sns-reminders && cd sns-reminders

Next, we’ll create a composer.json file, paste in the following, and save it:

{
    "require": {
        "aws/aws-sdk-php": "3.*"
    }
}

Now we just need to install the dependencies by opening the folder in the command line and running the following command:

$ composer install

We’re almost ready to start using the AWS SDK, but we first need to set up credentials. For our purposes, the easiest way will be to create a credentials file at ~/.aws which will be automatically loaded by the SDK. You can find full instructions in Amazon’s docs, but here’s the rundown:

Create a new folder in your HOME directory (~/ on Linux/Mac or C:UsersUSERNAME on Windows) called .aws and then create a text file in that folder called credentials without any extension. Now add the following text to that file:

[sns-reminders]
aws_access_key_id = YOUR_AWS_ACCESS_KEY_ID
aws_secret_access_key = YOUR_AWS_SECRET_ACCESS_KEY

For a bit of extra security you can lock down the credentials file’s permissions to 600:

$ chmod 600 credentials

Now you’ll want to head over to your IAM console and in the users tab, click “Create New Users”, add a user called “sns-reminders”, make sure that “Generate an access key for each user” is checked and then click “Create”.

You should then be brought to a screen that looks like this:

User Created Screen

Click “Show User Security Credentials” and then you can copy and paste the aws_access_key_id and aws_secret_access_key to replace their placeholders in your ~/.aws/credentials file.

Finally, you’ll need to grant this new user permission to use SNS by clicking on your new user in the list of users, clicking “Attach Policy” and attaching the AmazonSNSFullAccess policy.

Setting up SNS

Now that we’ve got our environment set up, we’ll also need to set up SNS. First, we’ll create a new topic and then subscribe our mobile number to that topic, so head over to the SNS Home Page and click “Create Topic”. For “Topic Name” I set sns-reminders, and for the “Display Name” I set REMINDERS – now click “Create Topic”.

create-topic

You should have been taken to your new topic’s Details page where you can copy the “Topic ARN” and “Region” to a scratch text file somewhere as we’ll be using it in our PHP script in a bit. In an application with any scale, you’d probably add subscriptions via the API, but since it’s only us we can just subscribe ourselves manually. Click the “Create Subscription” button, leave the “Topic ARN” alone, select SMS as the protocol, and add your mobile phone number (including the country code) as the endpoint. Shortly after you click “Create Subscription” you should receive a text message at the number you subscribed; reply “yes” from your mobile and you should be good to go!

create subscription

Sending Text Messages with PHP

Now we’re ready to actually start writing some code! Create a new file in your sns-reminders folder called send.php and paste in the following code:

<?php
require dirname( __FILE__ ) . '/vendor/autoload.php';
use AwsSnsSnsClient;

$client = SnsClient::factory(
    array(
        'profile' => 'sns-reminders',
        'region'  => 'us-east-1',
        'version' => '2010-03-31',
    )
);

Here we’re requiring Composer’s autoload.php file which is a helper provided by Composer to load the correct PHP files as we use them, which we’re doing on the next line where we bring in the SNS client library.

After that, we’re creating a new SNS client using Amazon’s SnsClient class. The profile argument is referring to the profile we created in the AWS access credential file (~/.aws/credentials) we created earlier, region should be changed to the region that you created your SNS topic in, and version specifies the API version that we’d like to use (no need to change that).

Next, we’ll want to set up our message. Since we’ll be using this as a command line utility, we can array_pop() the message off of $argv by adding the following line:

$message = array_pop( $argv );

Now we’ll set up our message payload and use the SNS client’s publish method to actually send our message. Paste in the following code, replacing the TopicArn value with the actual value that you copied from your Topic’s detail page earlier:

$payload = array(
    'TopicArn' => 'arn:aws:sns:us-east-1:1234567890:sns-reminders',
    'Message' => $message,
    'MessageStructure' => 'string',
);

try {
    $client->publish( $payload );
    echo 'Sent message: "' . $message . '"';
} catch ( Exception $e ) {
    echo “Send Failed!n" . $e->getMessage();
}

You’ll notice that we’ve wrapped the call to $client->publish() in a try...catch statement and provided some user feedback in the form of success or failure messages.

Now let’s send our first message! Open the project folder in your command line and type the following command:

$ php send.php "Walk your dogs now!"

If everything went well, you should have received a text message from the same number that asked you if you wanted to subscribe to the topic. If you’ve received an error, double check that you’ve filled in the correct values for TopicArn and region and that you’ve properly set up and saved your credentials file.

Cron Your Way to Good Habits

All that’s left to do now is to set up some reminders using our system’s cron. Personally, I like to be reminded to walk my dogs after I’ve been working for a few hours so I’ll open my Crontab for editing:

$ crontab -e

And add the following entry to send myself a text message every morning at 10am:

 0  10  *   *   *   php ~/sns-reminders/send.php "Walk your dogs now!" >> ~/sns-reminders/cron.log 2>&1

You can change ~/sns-reminders to the actual path to your project, and you’ll also notice that any output from this command is being appended to a file called cron.log in the project’s folder which will allow you to debug any issues if you don’t receive your reminder.

Wrapping Up

I like this method of getting habit-building reminders because the message is pushed to me at the same time every day and I receive it on my phone and in iMessage. Also, if I don’t mark the message as read, it will keep reminding me every time I check my messages and that really seems to work for me. It also doesn’t hurt that it’s something I coded myself, for some reason this seems to make me want to use it more and to complete the task every morning when I get the message.

I might make this script a bit more robust in the future, possibly modifying the cron entry to call the script every 5 minutes or so and moving the actual scheduling of messages into the PHP script. Doing this would enable me to vary the time the message is sent, vary the message, and more easily handle multiple reminders with different schedules without stuffing my crontab full of reminder entries. Until then, this has actually been working quite well for me and I’ve been successful in adding healthy habits to my daily routine.

What habits will you be building with your SNS reminders?

About the Author

Jeff Gould

Jeff is a problem solver at heart who found his way to the web at an early age and never looked back. Before Delicious Brains, Jeff was a freelance web developer specializing in WordPress and front-end development.