Send Apple Push Notifications with Python 2.7

Yosemite has Python 2.7.6 built in but for many reasons (one of them is sudo) we prefer a clean up-to-date install.

pytInstall Python (on OS X Yosemite)

Yosemite has Python 2.7.6 built in but for many reasons (one of them is sudo) we prefer a clean up-to-date install.

1. brew install python

Make sure the newly installed Python is in the path:

vi ~/.zshrc
PATH=$PATH:/usr/local:/usr/local/bin: # Add Python to PATH
source ~/.zshrc

Double check we have the latest version:

python -V

Virtual environments is a must to keep all the dependencies in check:

pip install virtualenv

Create a new virtual environment called pyenv and activate it:

virtualenv pyenv
source pyenv/bin/activate

Install Python APN library:

pip install apns

Now it is a good idea to make our installation easily repeatable:

pip freeze > requirements.txt

Later we can restore all the required libraries:

pip install -r requirements.txt

Or even update them all:

pip freeze --local | grep -v '^\-e' | cut -d = -f 1  | xargs pip install -U

From download “APNs Production iOS” certificate, aps_production.cer.

Now, this is the tricky part. We have to convert it to a .p12 certificate.

To do that, double-click on the certificate so that it is added to the keychain.

Open “Keychan Access” and right-click on the certificate to export it as .p12 certificate.

It is very important to export the certificate and not the private key!

Lets export it into a PEM certificate that either contains both the private key and the certificate:

openssl pkcs12 -in aps_production.p12 -out aps_production_olinguito.pem -nodes

Or into two separate files, one with the key and the other one with the certificate (preferred method):

openssl pkcs12 -nocerts -in aps_production.p12 -out aps_prod_key.pem -nodes
openssl pkcs12 -nokeys -in aps_production.p12 -out aps_prod_cert.pem -nodes

A very simple script to test our notifications:

import time
from apns import APNs, Frame, Payload

apns = APNs(use_sandbox=False, cert_file='aps_prod_cert.pem', key_file='aps_prod_key.pem', enhanced=True)

# Send a notification
token_hex = 'dd6b492f92546f8a02d9a36e689b4be28b0c663db7b6c278379866a7e1behell'
payload = Payload(alert="Hello World!", sound="default", badge=1)
apns.gateway_server.send_notification(token_hex, payload)

Subscribe to The infinite monkey theorem

Get the latest posts delivered right to your inbox