def test_serialization(self): # standard pickle s_message = pickle.dumps(self.message) s_raw_message = pickle.dumps(self.raw_message) c_message = pickle.loads(s_message) c_raw_message = pickle.loads(s_raw_message) for key in ('tokens', 'alert', 'badge', 'sound', 'content_available', 'expiry', 'extra', 'priority', '_payload'): self.assertEqual(getattr(self.message, key), getattr(c_message, key)) self.assertEqual(getattr(self.raw_message, key), getattr(c_raw_message, key)) # custom s_message = self.message.__getstate__() s_raw_message = self.raw_message.__getstate__() # JSON/XML/etc and store/send s_message = json.dumps(s_message) s_raw_message = json.dumps(s_raw_message) # unserialize s_message = json.loads(s_message) s_raw_message = json.loads(s_raw_message) # reconstruct c_message = Message(**s_message) c_raw_message = Message(**s_raw_message) for key in ('tokens', 'alert', 'badge', 'sound', 'content_available', 'expiry', 'extra', 'priority', '_payload'): self.assertEqual(getattr(self.message, key), getattr(c_message, key)) self.assertEqual(getattr(self.raw_message, key), getattr(c_raw_message, key))
def test_pushkit(sandbox): f = open("imdemo_pushkit.p12", "rb") p12 = f.read() f.close() print "p12", len(p12) token = "144c67f2fde4b72de8ed4203e9672c064e12376ed340d55f8e04430e15ad5a47" apns = IOSPush.connect_apns_server(sandbox, p12, "", 0) extra = {"voip": {"channel_id": "1", "command": "dial"}} message = Message([token], extra=extra) try: result = apns.send(message) for token, (reason, explanation) in result.failed.items(): # stop using that token logging.error("failed token:%s", token) for reason, explanation in result.errors: # handle generic errors logging.error( "send notification fail: reason = %s, explanation = %s", reason, explanation) time.sleep(2) extra = {"voip": {"channel_id": "1", "command": "hangup"}} message = Message([token], extra=extra) result = apns.send(message) time.sleep(1) except OpenSSL.SSL.Error, e: err = e.message[0][2] print "certificate expired" in err print "ssl exception:", e, type(e), dir(e), e.args, e.message raise e
def send_apple_push_notification(user, alert, **extra_data): if not connection and not dbx_connection: logging.error( "Attempting to send push notification, but no connection was found. This may be because we could not find the APNS Certificate file." ) return devices = PushDeviceToken.objects.filter(user=user, kind=PushDeviceToken.APNS) # Plain b64 token kept for debugging purposes tokens = [(b64_to_hex(device.token), device.ios_app_id, device.token) for device in devices] logging.info("APNS: Sending apple push notification to devices: %s" % (tokens, )) zulip_message = Message([ token[0] for token in tokens if token[1] in (settings.ZULIP_IOS_APP_ID, None) ], alert=alert, **extra_data) dbx_message = Message([ token[0] for token in tokens if token[1] in (settings.DBX_IOS_APP_ID, ) ], alert=alert, **extra_data) _do_push_to_apns_service(user, zulip_message, connection) _do_push_to_apns_service(user, dbx_message, dbx_connection)
def test_send(self): # success, retry + include-failed, don't-retry + include-failed backend = DummyBackend(push=(None, 1, 3)) session = Session(pool=backend) msg = Message(["0123456789ABCDEF", "FEDCBA9876543210"], alert="my alert", badge=10, content_available=1, my_extra=15) push_con = session.get_connection("push_production", cert_string="certificate") srv = APNs(push_con) res = srv.send(msg) self.assertEqual(len(res.failed), 0) self.assertEqual(len(res.errors), 0) self.assertFalse(res.needs_retry()) push_con2 = session.get_connection("push_production", cert_string="certificate") srv = APNs(push_con2) self.assertEqual(session.pool.push_result_pos, 0) session.pool.push_result_pos += 1 res = srv.send(msg) self.assertEqual(len(res.failed), 0) self.assertEqual(len(res.errors), 1) self.assertTrue(res.needs_retry()) # indeed, we have used the cache self.assertEqual(session.pool.new_connections, 1) push_con = session.new_connection("push_production", cert_string="certificate") srv = APNs(push_con) res = srv.send(msg) self.assertEqual(len(res.failed), 0) self.assertEqual(len(res.errors), 1) self.assertFalse(res.needs_retry()) # indeed, new connection, we haven't used the cache self.assertEqual(session.pool.new_connections, 2)
def test_alert(sandbox): f = open("imdemo_dev.p12", "rb") p12 = f.read() f.close() token = "b859063a8ad75b7f07ada8da9743d9589ddf6bc3954e2b3ee85afc865f0819ea" alert = "测试ios推送" badge = 1 sound = "default" print "p12", len(p12) extra = {"test": "hahah"} apns = IOSPush.connect_apns_server(sandbox, p12, "", 0) message = Message([token], alert=alert, badge=badge, sound=sound, extra=extra) try: result = apns.send(message) print result time.sleep(1) except OpenSSL.SSL.Error, e: err = e.message[0][2] print "certificate expired" in err print "ssl exception:", e, type(e), dir(e), e.args, e.message raise e
def _push(self, _app_uuid, _body, _config): _apns = get_apns(self.application, _app_uuid) if _apns == None: logging.error("no apns inited for ios push") return _title = push_title(_body.get("mt"), _body.get("ms"), _body.get("bo"), _config.get("user_language")) _sound = None if not _config.get("user_silence_notification"): _sound = "beep.wav" _count = _config.get("unacked_notification_count") _m = Message(_config.get("device_ios_token"), alert=_title, sound=_sound, badge=_count) _dev = _config.get("is_development") logging.info(_config) _real_apns = _apns.get("pro") if _dev != None and _dev == True: _real_apns = _apns.get("dev") _real_apns.publish_one(_m) return
def setUp(self): self.now = datetime.datetime.now() # Typical message self.message = Message( "0123456789ABCDEF", alert=u"Russian: \u0421\u0430\u0440\u0434\u0430\u0440", badge=10, sound="test.mp3", content_available=1, expiry=self.now + datetime.timedelta(days=3), priority=30, extra={'key': 'value'} ) # Message with a custom payload self.raw_message = Message( ["0123456789ABCDEF", "FEDCBA9876543210"], payload=self.message.payload, priority=5, expiry=datetime.timedelta(days=5) )
def setUp(self): self.now = datetime.datetime.now() # Typical message self.message = Message( "0123456789ABCDEF", alert=u"Russian: \u0421\u0430\u0440\u0434\u0430\u0440", badge=10, sound="test.mp3", content_available=1, expiry=self.now + datetime.timedelta(days=3), priority=30, extra={"key": "value"}, ) # Message with a custom payload self.raw_message = Message( ["0123456789ABCDEF", "FEDCBA9876543210"], payload=self.message.payload, priority=5, expiry=datetime.timedelta(days=5), )
def push_to_ios_devices_raw(devices=None, **kwargs): conn = Session.new_connection(settings.IOS_PUSH_SERVER, cert_file=settings.IOS_CERT) srv = APNs(conn) if devices is None: devices = APNSDevice.objects.filter(active=True).values_list( "registration_id", flat=True) message = Message(devices, **kwargs) res = srv.send(message) if res.needs_retry(): push_to_ios_devices_raw.delay(devices=res.retry().tokens, **kwargs)
def test_non_ascii(self): # meta-data size. ensure 'alert' is included. empty_msg_size = len(Message(tokens=[], alert="a").get_json_payload()) - 1 MAX_UTF8_SIZE = 3 # size of maximum utf8 encoded character in bytes chinese_str = ( u'\u5187\u869a\u5487\u6b8f\u5cca\u9f46\u9248\u6935\u4ef1\u752a' u'\u67cc\u521e\u62b0\u530a\u6748\u9692\u5c6e\u653d\u588f\u6678') chinese_msg_size = len(Message(tokens=[], alert=chinese_str).get_json_payload()) self.assertLessEqual( chinese_msg_size, empty_msg_size + len(chinese_str) * MAX_UTF8_SIZE) MAX_EMOJI_SIZE = 4 # size of maximum utf8 encoded character in bytes # emoji emoji_str = (u'\U0001f601\U0001f603\U0001f638\U00002744') emoji_msg_size = len(Message(tokens="", alert=emoji_str).get_json_payload()) self.assertLessEqual( emoji_msg_size, empty_msg_size + len(emoji_str) * MAX_EMOJI_SIZE)
def push(cls, appid, token, alert, sound="default", badge=0, content_available=0, extra=None): message = Message([token], alert=alert, badge=badge, sound=sound, content_available=content_available, extra=extra) for i in range(3): if i > 0: logging.warn("resend notification") apns = cls.get_connection(appid) try: logging.debug("send apns:%s %s %s", message.tokens, alert, badge) result = apns.send(message) for token, (reason, explanation) in result.failed.items(): # stop using that token logging.error("failed token:%s", token) for reason, explanation in result.errors: # handle generic errors logging.error( "send notification fail: reason = %s, explanation = %s", reason, explanation) if result.needs_retry(): # extract failed tokens as new message message = result.retry() # re-schedule task with the new message after some delay continue else: break except OpenSSL.SSL.Error, e: logging.warn("ssl exception:%s", str(e)) cls.apns_manager.remove_apns_connection(appid) err = e.message[0][2] if "certificate expired" in err: break except Exception, e: logging.warn("send notification exception:%s", str(e)) cls.apns_manager.remove_apns_connection(appid)
def send_message(self, tokens, alert=None, badge=None, sound=None, content_available=None, expiry=None, payload=None, **extra): """ Send a message. This will not retry but will call the failed_callback in case of failure .. seealso:: :py:class:`apnsclient.apns.Message` for a better description of the parameters :param tokens: The tokens to send to :param alert: The alert message :param badge: The badge to show :param sound: The sound to play :param expiry: A timestamp when message will expire :param payload: The payload :param extra: Extra info """ connection = self.get_connection() if connection is None: return None if not tokens: return False message = Message(tokens, alert, badge, sound, expiry, payload, content_available, **extra) srv = APNs(connection) res = srv.send(message) if res.failed and self.failed_callback: for key, reason in res.failed.iteritems(): self.failed_callback(key, reason) return res
def test_content(sandbox): f = open("imdemo_dev.p12", "rb") p12 = f.read() f.close() print "p12", len(p12) token = "b859063a8ad75b7f07ada8da9743d9589ddf6bc3954e2b3ee85afc865f0819ea" extra = {"xiaowei": {"new": 1}} apns = IOSPush.connect_apns_server(sandbox, p12, "", 0) message = Message([token], content_available=1, extra=extra) try: result = apns.send(message) print result time.sleep(1) except OpenSSL.SSL.Error, e: err = e.message[0][2] print "certificate expired" in err print "ssl exception:", e, type(e), dir(e), e.args, e.message raise e
def send_notification(self, list_tokens, message_title="", message_body="", badge=1): """ push notifications to apns server, used only with push_connection=True :param message_body: :param message_title: :param list_tokens: all tokens to send notifications :param badge: number of something new in server """ service = APNs(self.connection) try: res = service.send(Message(list_tokens, alert={"title": message_title, "body": message_body}, badge=badge)) except: print "Can't connect to APNs, looks like network is down" else: for token, reason in res.failed.items(): code, errmsg = reason print "Device failed: {0}, reason: {1}".format(token, errmsg) for code, errmsg in res.errors: print "Error: {}".format(errmsg) if res.needs_retry(): res.retry()
class APNsClientMessageTest(Python26Mixin, unittest.TestCase): """ Test Message API. """ def setUp(self): self.now = datetime.datetime.now() # Typical message self.message = Message( "0123456789ABCDEF", alert=u"Russian: \u0421\u0430\u0440\u0434\u0430\u0440", badge=10, sound="test.mp3", content_available=1, expiry=self.now + datetime.timedelta(days=3), priority=30, extra={"key": "value"}, ) # Message with a custom payload self.raw_message = Message( ["0123456789ABCDEF", "FEDCBA9876543210"], payload=self.message.payload, priority=5, expiry=datetime.timedelta(days=5), ) def test_payload(self): payload = self.message.get_json_payload() self.assertIsInstance(payload, six.binary_type) unicode_src = payload.decode("utf-8") payload = json.loads(unicode_src) self.assertEqual( payload["aps"], { "alert": self.message.alert, "badge": self.message.badge, "sound": self.message.sound, "content-available": self.message.content_available, }, ) for k, v in self.message.extra.items(): self.assertEqual(payload[k], v) def test_serialization(self): # standard pickle s_message = pickle.dumps(self.message) s_raw_message = pickle.dumps(self.raw_message) c_message = pickle.loads(s_message) c_raw_message = pickle.loads(s_raw_message) for key in ( "tokens", "alert", "badge", "sound", "content_available", "expiry", "extra", "priority", "_payload", ): self.assertEqual(getattr(self.message, key), getattr(c_message, key)) self.assertEqual(getattr(self.raw_message, key), getattr(c_raw_message, key)) # custom s_message = self.message.__getstate__() s_raw_message = self.raw_message.__getstate__() # JSON/XML/etc and store/send s_message = json.dumps(s_message) s_raw_message = json.dumps(s_raw_message) # unserialize s_message = json.loads(s_message) s_raw_message = json.loads(s_raw_message) # reconstruct c_message = Message(**s_message) c_raw_message = Message(**s_raw_message) for key in ( "tokens", "alert", "badge", "sound", "content_available", "expiry", "extra", "priority", "_payload", ): self.assertEqual(getattr(self.message, key), getattr(c_message, key)) self.assertEqual(getattr(self.raw_message, key), getattr(c_raw_message, key)) def test_non_ascii(self): # meta-data size. ensure 'alert' is included. empty_msg_size = len(Message(tokens=[], alert="a").get_json_payload()) - 1 MAX_UTF8_SIZE = 3 # size of maximum utf8 encoded character in bytes chinese_str = ( u"\u5187\u869a\u5487\u6b8f\u5cca\u9f46\u9248\u6935\u4ef1\u752a" u"\u67cc\u521e\u62b0\u530a\u6748\u9692\u5c6e\u653d\u588f\u6678" ) chinese_msg_size = len(Message(tokens=[], alert=chinese_str).get_json_payload()) self.assertLessEqual(chinese_msg_size, empty_msg_size + len(chinese_str) * MAX_UTF8_SIZE) MAX_EMOJI_SIZE = 4 # size of maximum utf8 encoded character in bytes # emoji emoji_str = u"\U0001f601\U0001f603\U0001f638\U00002744" emoji_msg_size = len(Message(tokens="", alert=emoji_str).get_json_payload()) self.assertLessEqual(emoji_msg_size, empty_msg_size + len(emoji_str) * MAX_EMOJI_SIZE) def test_batch(self): # binary serialization in ridiculously small buffer =) b_message = list(self.message.batch(10)) b_raw_message = list(self.raw_message.batch(10)) # number of batches self.assertEqual(len(b_message), 1) self.assertEqual(len(b_raw_message), 2) # lets read stuff back. number of sent before ID's is of course 0. self.check_message(b_message[0], 0, self.message) self.check_message(b_raw_message[0], 0, self.raw_message) self.check_message(b_raw_message[1], 1, self.raw_message) def check_message(self, batch, itr, msg): sent, data = batch # we send batches of 1 token size self.assertEqual(sent, itr) # |COMMAND|FRAME-LEN|{token}|{payload}|{id:4}|{expiry:4}|{priority:1} command, frame_len = struct.unpack(">BI", data[0:5]) self.assertEqual(command, 2) self.assertEqual(frame_len, len(data) - 5) off = 5 restored = {} for itm in range(1, 6): hdr, length = struct.unpack(">BH", data[off : (off + 3)]) off += 3 value = data[off : (off + length)] off += length if hdr == 1: restored["token"] = binascii.hexlify(value).decode("ascii") elif hdr == 2: restored["payload"] = json.loads(value.decode("utf-8")) elif hdr == 3: restored["index"] = struct.unpack(">I", value)[0] elif hdr == 4: restored["expiry"] = struct.unpack(">I", value)[0] elif hdr == 5: restored["priority"] = struct.unpack(">B", value)[0] for key in ("token", "payload", "index", "expiry", "priority"): if key not in restored: self.fail("Binary message is missing: %s" % key) # check message self.assertEqual(msg.tokens[itr].lower(), restored["token"].lower()) self.assertEqual(msg.payload["aps"], restored["payload"]["aps"]) restored["payload"].pop("aps") self.assertEqual(msg.extra, restored["payload"]) self.assertEqual(restored["index"], itr) self.assertEqual(msg.expiry, restored["expiry"]) self.assertEqual(msg.priority, restored["priority"]) def test_retry(self): # include failed r_message = self.message.retry(0, True) for key in ("tokens", "alert", "badge", "sound", "content_available", "expiry", "priority", "extra"): self.assertEqual(getattr(self.message, key), getattr(r_message, key)) # nothing to retry, we skip the token self.assertEqual(self.message.retry(0, False), None) # include failed r_raw_message = self.raw_message.retry(0, True) for key in ("tokens", "alert", "badge", "sound", "content_available", "expiry", "priority", "extra"): self.assertEqual(getattr(self.raw_message, key), getattr(r_raw_message, key)) # skip failed r_raw_message = self.raw_message.retry(0, False) self.assertEqual(self.raw_message.tokens[1:], r_raw_message.tokens) for key in ("alert", "badge", "sound", "content_available", "expiry", "priority", "extra"): self.assertEqual(getattr(self.raw_message, key), getattr(r_raw_message, key))
class APNsClientMessageTest(Python26Mixin, unittest.TestCase): """ Test Message API. """ def setUp(self): self.now = datetime.datetime.now() # Typical message self.message = Message( "0123456789ABCDEF", alert=u"Russian: \u0421\u0430\u0440\u0434\u0430\u0440", badge=10, sound="test.mp3", content_available=1, expiry=self.now + datetime.timedelta(days=3), priority=30, extra={'key': 'value'} ) # Message with a custom payload self.raw_message = Message( ["0123456789ABCDEF", "FEDCBA9876543210"], payload=self.message.payload, priority=5, expiry=datetime.timedelta(days=5) ) def test_payload(self): payload = self.message.get_json_payload() self.assertIsInstance(payload, six.binary_type) unicode_src = payload.decode('utf-8') payload = json.loads(unicode_src) self.assertEqual(payload["aps"], { "alert": self.message.alert, "badge": self.message.badge, "sound": self.message.sound, "content-available": self.message.content_available }) for k, v in self.message.extra.items(): self.assertEqual(payload[k], v) def test_serialization(self): # standard pickle s_message = pickle.dumps(self.message) s_raw_message = pickle.dumps(self.raw_message) c_message = pickle.loads(s_message) c_raw_message = pickle.loads(s_raw_message) for key in ('tokens', 'alert', 'badge', 'sound', 'content_available', 'expiry', 'extra', 'priority', '_payload'): self.assertEqual(getattr(self.message, key), getattr(c_message, key)) self.assertEqual(getattr(self.raw_message, key), getattr(c_raw_message, key)) # custom s_message = self.message.__getstate__() s_raw_message = self.raw_message.__getstate__() # JSON/XML/etc and store/send s_message = json.dumps(s_message) s_raw_message = json.dumps(s_raw_message) # unserialize s_message = json.loads(s_message) s_raw_message = json.loads(s_raw_message) # reconstruct c_message = Message(**s_message) c_raw_message = Message(**s_raw_message) for key in ('tokens', 'alert', 'badge', 'sound', 'content_available', 'expiry', 'extra', 'priority', '_payload'): self.assertEqual(getattr(self.message, key), getattr(c_message, key)) self.assertEqual(getattr(self.raw_message, key), getattr(c_raw_message, key)) def test_non_ascii(self): # meta-data size. ensure 'alert' is included. empty_msg_size = len(Message(tokens=[], alert="a").get_json_payload()) - 1 MAX_UTF8_SIZE = 3 # size of maximum utf8 encoded character in bytes chinese_str = ( u'\u5187\u869a\u5487\u6b8f\u5cca\u9f46\u9248\u6935\u4ef1\u752a' u'\u67cc\u521e\u62b0\u530a\u6748\u9692\u5c6e\u653d\u588f\u6678') chinese_msg_size = len(Message(tokens=[], alert=chinese_str).get_json_payload()) self.assertLessEqual( chinese_msg_size, empty_msg_size + len(chinese_str) * MAX_UTF8_SIZE) MAX_EMOJI_SIZE = 4 # size of maximum utf8 encoded character in bytes # emoji emoji_str = (u'\U0001f601\U0001f603\U0001f638\U00002744') emoji_msg_size = len(Message(tokens="", alert=emoji_str).get_json_payload()) self.assertLessEqual( emoji_msg_size, empty_msg_size + len(emoji_str) * MAX_EMOJI_SIZE) def test_batch(self): # binary serialization in ridiculously small buffer =) b_message = list(self.message.batch(10)) b_raw_message = list(self.raw_message.batch(10)) # number of batches self.assertEqual(len(b_message), 1) self.assertEqual(len(b_raw_message), 2) # lets read stuff back. number of sent before ID's is of course 0. self.check_message(b_message[0], 0, self.message) self.check_message(b_raw_message[0], 0, self.raw_message) self.check_message(b_raw_message[1], 1, self.raw_message) def check_message(self, batch, itr, msg): sent, data = batch # we send batches of 1 token size self.assertEqual(sent, itr) # |COMMAND|FRAME-LEN|{token}|{payload}|{id:4}|{expiry:4}|{priority:1} command, frame_len = struct.unpack(">BI", data[0:5]) self.assertEqual(command, 2) self.assertEqual(frame_len, len(data) - 5) off = 5 restored = {} for itm in range(1, 6): hdr, length = struct.unpack(">BH", data[off:(off+3)]) off += 3 value = data[off:(off+length)] off += length if hdr == 1: restored['token'] = binascii.hexlify(value).decode('ascii') elif hdr == 2: restored['payload'] = json.loads(value.decode('utf-8')) elif hdr == 3: restored['index'] = struct.unpack(">I", value)[0] elif hdr == 4: restored['expiry'] = struct.unpack(">I", value)[0] elif hdr == 5: restored['priority'] = struct.unpack(">B", value)[0] for key in ('token', 'payload', 'index', 'expiry', 'priority'): if key not in restored: self.fail("Binary message is missing: %s" % key) # check message self.assertEqual(msg.tokens[itr].lower(), restored['token'].lower()) self.assertEqual(msg.payload['aps'], restored['payload']['aps']) restored['payload'].pop('aps') self.assertEqual(msg.extra, restored['payload']) self.assertEqual(restored['index'], itr) self.assertEqual(msg.expiry, restored['expiry']) self.assertEqual(msg.priority, restored['priority']) def test_retry(self): # include failed r_message = self.message.retry(0, True) for key in ('tokens', 'alert', 'badge', 'sound', 'content_available', 'expiry', 'priority', 'extra'): self.assertEqual(getattr(self.message, key), getattr(r_message, key)) # nothing to retry, we skip the token self.assertEqual(self.message.retry(0, False), None) # include failed r_raw_message = self.raw_message.retry(0, True) for key in ('tokens', 'alert', 'badge', 'sound', 'content_available', 'expiry', 'priority', 'extra'): self.assertEqual(getattr(self.raw_message, key), getattr(r_raw_message, key)) # skip failed r_raw_message = self.raw_message.retry(0, False) self.assertEqual(self.raw_message.tokens[1:], r_raw_message.tokens) for key in ('alert', 'badge', 'sound', 'content_available', 'expiry', 'priority', 'extra'): self.assertEqual(getattr(self.raw_message, key), getattr(r_raw_message, key))
@classmethod def start(cls): t = threading.Thread(target=cls.update_p12_thread, args=()) t.setDaemon(True) t.start() if __name__ == "__main__": f = open("imdemo_dev.p12", "rb") p12 = f.read() f.close() token = "86ac9703925375de83f0023b82f245371a9b58437bd9df441018558c99657b75" alert = "测试ios推送" badge = 1 sound = "default" #alert = None #badge = None #sound = None print len(p12) extra = {"xiaowei": {"new": 1}} apns = IOSPush.connect_apns_server(True, p12, "", 0) #message = Message([token], alert=alert, badge=badge, #sound=sound, extra=extra) message = Message([token], content_available=1, extra=extra) result = apns.send(message) print result time.sleep(1)
# from apnsclient import ( Session, Message, APNs ) from pprint import pprint # device token and private key's passwd deviceToken = '097271a3744d951fe233729b649b0d5bcdfbf7e0c8c10e11fa99d02e5cfa87ac'; invalid_deviceToken = '097271a3744d951fe233729b649b0d5bcdfbf7e0c8c10e11fa99d02e5cfa87ed'; passphrase = '1234'; # 使用session对象来创建一个连接池 session = Session() conn = session.get_connection("push_sandbox", cert_file="apns.pem", passphrase=passphrase) # 发送推送和得到反馈 tokenList = [] tokenList.append(deviceToken) #tokenList.append(invalid_deviceToken) msg = Message(tokenList, alert="use python send", badge=10) # send message service = APNs(conn) res = service.send(msg) pprint(vars(res)) print res.message.__dict__
def setUp(self): self.msg = Message(["0123456789ABCDEF", "FEDCBA9876543210"], alert="message")