pyapns-client: Apple Push Notifications (HTTP/2)

2.0.6 · active · verified Sat Apr 11

pyapns-client is a Python library designed for sending Apple Push Notifications (APNs) to iOS, macOS, and Safari using the modern HTTP/2 Push provider API. It focuses on simplicity, flexibility, and speed, leveraging token-based authentication for enhanced security and avoiding certificate renewal hassles. The current version is 2.0.6, with a more recent async-enabled version (pyapns-client3) also available. This library is actively maintained, with the latest update for the 2.x series in June 2022.

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to send a basic push notification using token-based authentication with `pyapns-client`. It leverages environment variables for sensitive credentials and includes essential error handling for common APNs responses. Ensure you replace placeholder values with your actual Apple Developer details and a valid device token. The `topic` parameter must match your application's bundle ID.

import os
from pyapns_client import APNSClient, IOSPayloadAlert, IOSPayload, IOSNotification, APNSDeviceException, APNSServerException, APNSProgrammingException, UnregisteredException

# --- Environment Variables (Replace with your actual values or secure fetching) ---
# APNS_MODE: APNSClient.MODE_DEV or APNSClient.MODE_PROD
# APNS_AUTH_KEY_PATH: Path to your .p8 authentication key file
# APNS_AUTH_KEY_ID: Your 10-character Key ID from Apple Developer portal
# APNS_TEAM_ID: Your 10-character Team ID from Apple Developer portal
# APNS_ROOT_CERT_PATH: Path to Apple's root certificate (e.g., AppleWWDRCA.pem or AAACertificateServices.pem)
#                      Can be None if included in your system's trust store or not strictly required for token-based auth.

APNS_MODE = os.environ.get('APNS_MODE', APNSClient.MODE_DEV) # Use MODE_PROD for production
APNS_AUTH_KEY_PATH = os.environ.get('APNS_AUTH_KEY_PATH', 'path/to/AuthKey_YOURKEYID.p8')
APNS_AUTH_KEY_ID = os.environ.get('APNS_AUTH_KEY_ID', 'YOURKEYID')
APNS_TEAM_ID = os.environ.get('APNS_TEAM_ID', 'YOURTEAMID')
APNS_ROOT_CERT_PATH = os.environ.get('APNS_ROOT_CERT_PATH', None) # Or 'path/to/AAACertificateServices.pem'

device_token = os.environ.get('DEVICE_TOKEN', 'a_sample_device_token_hex_string')
APP_BUNDLE_ID = os.environ.get('APP_BUNDLE_ID', 'com.example.yourapp')

if APNS_ROOT_CERT_PATH and not os.path.exists(APNS_ROOT_CERT_PATH):
    print(f"Warning: APNS_ROOT_CERT_PATH '{APNS_ROOT_CERT_PATH}' not found. Set it correctly or None.")

if not os.path.exists(APNS_AUTH_KEY_PATH):
    print(f"Error: APNS_AUTH_KEY_PATH '{APNS_AUTH_KEY_PATH}' not found. Please provide a valid path to your .p8 key.")
    exit(1)

try:
    # Initialize the client using token-based authentication
    client = APNSClient(
        mode=APNS_MODE,
        auth_key_path=APNS_AUTH_KEY_PATH,
        auth_key_id=APNS_AUTH_KEY_ID,
        team_id=APNS_TEAM_ID,
        root_cert_path=APNS_ROOT_CERT_PATH # Optional, depends on your trust store setup
    )

    # Create the notification payload
    alert = IOSPayloadAlert(title='Hello from pyapns-client!', subtitle='New Message', body='This is a test push notification.')
    payload = IOSPayload(alert=alert, badge=1, sound='default')

    # Create the notification object
    notification = IOSNotification(payload=payload, topic=APP_BUNDLE_ID)

    print(f"Attempting to push notification to device: {device_token}")
    # Send the notification
    client.push(notification=notification, device_token=device_token)
    print("Notification sent successfully!")

except UnregisteredException as e:
    print(f"Device is unregistered: {e.device_token}. Remove from DB. Timestamp: {e.timestamp_datetime}")
except APNSDeviceException as e:
    print(f"Device error for {e.device_token}: {e.reason}. Flag device as invalid.")
except APNSServerException as e:
    print(f"APNs server error: {e.reason}. Try again later.")
except APNSProgrammingException as e:
    print(f"Programming error: {e.reason}. Check your code and APNs settings.")
except Exception as e:
    print(f"An unexpected error occurred: {e}")

view raw JSON →