Package: pyapns-client3
Simple, flexible and fast Apple Push Notifications on iOS, OSX and Safari using the HTTP/2 Push provider API.FeaturesUses the new Apple APNs HTTP/2 protocol with persistent connectionsSupports token-based authentication (no need to renew your certificates anymore) and certificate-based authenticationUses the httpx HTTP client librarySupports the new iOS 10 features such as Collapse IDs, Subtitles and Mutable NotificationsMakes the integration and error handling really simple with auto-retry on APNs errorsSupports asynchronous sending of notificationsCautionsWorks only with Python 3.6 and higherInstallationInstall using pip:pipinstallpyapns_client3UsageSyncfrompyapns_clientimportAPNSClient,TokenBasedAuth,IOSPayloadAlert,IOSPayload,IOSNotification,APNSDeviceException,APNSServerException,APNSProgrammingException,UnregisteredExceptiondevice_tokens=['device_token_1','device_token_2']alert=IOSPayloadAlert(title='Title',subtitle='Subtitle',body='Some message.')payload=IOSPayload(alert=alert)notification=IOSNotification(payload=payload,topic='domain.organization.app')# `root_cert_path` is for the AAACertificateServices root cert (https://apple.co/3mZ5rB6)# with token-based auth you don't need to create / renew your APNS SSL certificates anymore# you can pass `None` to `root_cert_path` if you have the cert included in your trust store# httpx uses 'SSL_CERT_FILE' and 'SSL_CERT_DIR' from `os.environ` to find your trust storewithAPNSClient(mode=APNSClient.MODE_DEV,authentificator=TokenBasedAuth(auth_key_path='/path/to/auth_key.p8',auth_key_id='AUTHKEY123',team_id='TEAMID1234'),root_cert_path='/path/to/root_cert.pem',)asclient:fordevice_tokenindevice_tokens:try:client.push(notification=notification,device_token=device_token)exceptUnregisteredExceptionase:print(f'device is unregistered, compare timestamp{e.timestamp_datetime}and remove from db')exceptAPNSDeviceException:print('flag the device as potentially invalid and remove from db after a few tries')exceptAPNSServerException:print('try again later')exceptAPNSProgrammingException:print('check your code and try again later')else:print('everything is ok')Asyncfrompyapns_clientimportAsyncAPNSClient,TokenBasedAuth,IOSPayloadAlert,IOSPayload,IOSNotification,APNSDeviceException,APNSServerException,APNSProgrammingException,UnregisteredExceptiondevice_tokens=['device_token_1','device_token_2']alert=IOSPayloadAlert(title='Title',subtitle='Subtitle',body='Some message.')payload=IOSPayload(alert=alert)notification=IOSNotification(payload=payload,topic='domain.organization.app')# `root_cert_path` is for the AAACertificateServices root cert (https://apple.co/3mZ5rB6)# with token-based auth you don't need to create / renew your APNS SSL certificates anymore# you can pass `None` to `root_cert_path` if you have the cert included in your trust store# httpx uses 'SSL_CERT_FILE' and 'SSL_CERT_DIR' from `os.environ` to find your trust storeasyncwithAsyncAPNSClient(mode=APNSClient.MODE_DEV,authentificator=TokenBasedAuth(auth_key_path='/path/to/auth_key.p8',auth_key_id='AUTHKEY123',team_id='TEAMID1234'),root_cert_path='/path/to/root_cert.pem',)asclient:fordevice_tokenindevice_tokens:try:awaitclient.push(notification=notification,device_token=device_token)exceptUnregisteredExceptionase:print(f'device is unregistered, compare timestamp{e.timestamp_datetime}and remove from db')exceptAPNSDeviceException:print('flag the device as potentially invalid and remove from db after a few tries')exceptAPNSServerException:print('try again later')exceptAPNSProgrammingException:print('check your code and try again later')else:print('everything is ok')3.03.0.6Changedallow to usestras alert for notification payload (by @tartansandal)Addedsome tests with Python version 3.6-3.11some payload serialization tests (by @tartansandal)some type annotationssome docstrings3.0.5Fixedhaveauth.pyuse theDicttype hint from the typing module by @tinycogio3.0.0Refactoredextract authentication classes2.12.1.0Addedasync/await support withAsyncAPNSClient2.02.0.7Addedusage as context managercertificate-based authentication