Skip to content

Instantly share code, notes, and snippets.

@rajephon
Forked from ndfred/push.py
Last active August 20, 2017 06:49
Show Gist options
  • Save rajephon/76d2e2528ba59124465c8ea0af877749 to your computer and use it in GitHub Desktop.
Save rajephon/76d2e2528ba59124465c8ea0af877749 to your computer and use it in GitHub Desktop.
A simple standalone script to test an Apple Push Notification setup
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
A simple standalone script to test an Apple Push Notification setup.
Uses the feedback packets to provide the best information on how to fix things.
Steps to send a push notification:
* set up push certificates on your app on the developer portal and regenerate
your provisioning profiles to make them push ready
* build your app with the new provisioning profile and enable push notifications
in you app delegate
* run the app on your device and use NSLog to get its push token on
the Xcode console
* select your push private key and certificate in Keychain and export them
without a password as a p12 file
* run this command to convert your p12 file to a pem file:
`$ openssl pkcs12 -nodes -in Push.p12 -out Push.pem`
* run this command to make sure your certificates are valid:
`$ openssl s_client -tls1 -cert Push.pem -connect gateway.push.apple.com:2195`
(use gateway.sandbox.push.apple.com if you have a dev push certificate)
if they certificates are valid, the server should not hang up
* change the parameters at the end of the script and run it
* you should see the push notification come through or a helpful error message
* you may alter the JSON payload as you wish to test badges and meta data
"""
import socket
import ssl
import json
import binascii
import struct
def send_push(pem_file_path, token, message, production=True):
"""Send a push notification to the device."""
# Prepare the binary payload
token = token.strip().strip('<>').replace(' ','').replace('-', '')
binary_token = binascii.unhexlify(token)
payload = json.dumps({'aps': {'alert': message}})
binary_payload = struct.pack(
'!BiiH%dsH%ds' % (len(binary_token), len(payload)),
1, 1337, 0,
len(binary_token), binary_token, len(payload), payload
)
# Send the payload and wait 1 second for an error message
print 'Connecting'
apns_socket = ssl.wrap_socket(socket.socket(), certfile=pem_file_path, ssl_version=ssl.PROTOCOL_TLSv1)
apns_socket.settimeout(1)
apns_socket.connect((production and 'gateway.push.apple.com' or 'gateway.sandbox.push.apple.com', 2195))
print 'Sending message "%s"' % message
apns_socket.write(binary_payload)
try:
print 'Waiting for feedback'
binary_response = apns_socket.recv(6)
if len(binary_response) != 6:
print 'The server hung up, please check your certificates and production mode setting'
else:
command, status, identifier = struct.unpack('!BBi', binary_response)
if command != 8 or identifier != 1337:
print 'Error receiving the feedback packet'
else:
status_messages = [
'Message successfully sent',
'Processing error',
'Missing device token',
'Missing topic',
'Missing payload',
'Invalid token size',
'Invalid topic size',
'Invalid payload size',
'Invalid topic size',
'Invalid token',
]
if status >= 0 and status < len(status_messages):
print '%s (status %d)' % (status_messages[status], status)
else:
print 'Unknown error (%d)' % status
except ssl.SSLError, exc:
if str(exc) == 'The read operation timed out':
print 'Message succesfsfully send!'
apns_socket.close()
if __name__ == '__main__':
send_push(
'Push.pem',
'd274c466 16bb3ee5 07332af6 2f2b7474 b8c0e2ca 43fbe846 8287256b a71862db',
u'Hello World!',
production=False,
)
@rajephon
Copy link
Author

Apple dropped support for SSLv3.0 on their APNS servers on October 29th 2014.
use TLSv1 instead of SSL3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment