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 connect_apns_server(cls, sandbox, p12, secret, timestamp): pub_key, priv_key = cls.gen_pem(p12, secret) session = Session(read_tail_timeout=1) address = 'push_sandbox' if sandbox else 'push_production' conn = session.get_connection(address, cert_string=pub_key, key_string=priv_key) apns = APNs(conn) return apns
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 get_ios_device_feedback(): conn = Session.new_connection(settings.IOS_FEEDBACK_SERVER, cert_file=settings.IOS_CERT) srv = APNs(conn, tail_timeout=10) for token, since in srv.feedback(): print token try: obj = APNSDevice.objects.get(registration_id=token) obj.active = False obj.save() except APNSDevice.DoesNotExist: pass
def check_feedback_services_for_tokens(self): """ used only for feedback connection on schedule, remove not available tokens """ services = APNs(self.connection) try: for token, when in services.feedback(): last_update = self.get_last_update_of_token(token) if last_update and last_update < when: self.remove_token(token) except: print "Can't connect to APNs, looks like network is down"
def check_apns_feedback(): feedback_connection = session.get_connection( settings.APNS_FEEDBACK, cert_file=settings.APNS_CERT_FILE) apns_client = APNs(feedback_connection, tail_timeout=20) for token, since in apns_client.feedback(): since_date = timestamp_to_datetime(since) logging.info("Found unavailable token %s, unavailable since %s" % (token, since_date)) PushDeviceToken.objects.filter(token=hex_to_b64(token), last_updates__lt=since_date, type=PushDeviceToken.APNS).delete() logging.info("Finished checking feedback for stale tokens")
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 _do_push_to_apns_service(user, message, apns_connection): # type: (UserProfile, Message, Connection) -> None if not apns_connection: logging.info( "Not delivering APNS message %s to user %s due to missing connection" % (message, user)) return apns_client = APNs(apns_connection) ret = apns_client.send(message) if not ret: logging.warning( "APNS: Failed to send push notification for clients %s" % (message.tokens, )) return for token, reason in ret.failed.items(): code, errmsg = reason b64_token = hex_to_b64(token) logging.warning( "APNS: Failed to deliver APNS notification to %s, reason: %s" % (b64_token, errmsg)) if code == 8: # Invalid Token, remove from our database logging.warning( "APNS: Removing token from database due to above failure") PushDeviceToken.objects.get(user=user, token=b64_token).delete() # Check failures not related to devices. for code, errmsg in ret.errors: logging.warning("APNS: Unknown error when delivering APNS: %s" % (errmsg, )) if ret.needs_retry(): logging.warning("APNS: delivery needs a retry, trying again") retry_msg = ret.retry() ret = apns_client.send(retry_msg) for code, errmsg in ret.errors: logging.warning("APNS: Unknown error when delivering APNS: %s" % (errmsg, ))
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()
def connect_apns(cls, appid): logging.debug("connecting apns") p12, secret, timestamp = cls.get_p12(appid) if not p12: return None if sandbox: pem_file = "/tmp/app_%s_sandbox_%s.pem" % (appid, timestamp) address = 'push_sandbox' else: pem_file = "/tmp/app_%s_%s.pem" % (appid, timestamp) address = 'push_production' if not os.path.isfile(pem_file): pem = cls.gen_pem(p12, secret) f = open(pem_file, "wb") f.write(pem) f.close() session = Session(read_tail_timeout=1) conn = session.get_connection(address, cert_file=pem_file) apns = APNs(conn) return apns
# 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 test_feedback(self): backend = DummyBackend(feedback=5) session = Session(pool=backend) feed_con = session.new_connection("feedback_production", cert_string="certificate") srv = APNs(feed_con) self.assertEqual(len(list(srv.feedback())), 5)