CM Email Webhook Verification SDK (Python)
SDK for verifying the authenticity of webhooks sent by CM Email services.
Installation
pip install cm-email-webhook-verification
Usage
from cm_email_webhook_verification import WebhookValidator, WebhookVerificationError
# Initialize with your webhook secret key
validator = WebhookValidator("your-secret-key")
# Extract headers and payload from incoming request
headers = {
"svix-id": request.headers["svix-id"],
"svix-timestamp": request.headers["svix-timestamp"],
"svix-signature": request.headers["svix-signature"],
}
payload = request.body.decode("utf-8")
try:
data = validator.verify(payload, headers)
# Process verified webhook data
print(f"Received event: {data}")
except WebhookVerificationError as e:
# Handle verification failure
print(f"Webhook verification failed: {e}")
Flask Example
from flask import Flask, request, jsonify
from cm_email_webhook_verification import WebhookValidator, WebhookVerificationError
app = Flask(__name__)
validator = WebhookValidator("your-secret-key")
@app.route("/webhook", methods=["POST"])
def webhook():
headers = {
"svix-id": request.headers.get("svix-id"),
"svix-timestamp": request.headers.get("svix-timestamp"),
"svix-signature": request.headers.get("svix-signature"),
}
payload = request.get_data(as_text=True)
try:
data = validator.verify(payload, headers)
return jsonify({"status": "ok"}), 200
except WebhookVerificationError:
return jsonify({"error": "Invalid webhook"}), 401
FastAPI Example
from fastapi import FastAPI, Request, HTTPException
from cm_email_webhook_verification import WebhookValidator, WebhookVerificationError
app = FastAPI()
validator = WebhookValidator("your-secret-key")
@app.post("/webhook")
async def webhook(request: Request):
headers = {
"svix-id": request.headers.get("svix-id"),
"svix-timestamp": request.headers.get("svix-timestamp"),
"svix-signature": request.headers.get("svix-signature"),
}
payload = (await request.body()).decode("utf-8")
try:
data = validator.verify(payload, headers)
return {"status": "ok"}
except WebhookVerificationError:
raise HTTPException(status_code=401, detail="Invalid webhook")
Custom Tolerance
By default, webhooks are valid for 5 minutes. You can customize this:
# Accept webhooks up to 10 minutes old
validator = WebhookValidator("your-secret-key", tolerance_in_seconds=600)
Exceptions
| Exception | Description |
|---|---|
WebhookVerificationError |
Base exception for all verification errors |
InvalidSignatureError |
Signature does not match |
TimestampExpiredError |
Timestamp outside tolerance window |
MissingHeaderError |
Required headers missing |
Security
This SDK uses:
- HMAC-SHA512 for signature generation
- Constant-time comparison to prevent timing attacks
- Timestamp validation to prevent replay attacks
Metadata
Release files for cm-email-webhook-verification 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| cm_email_webhook_verification-1.0.0.tar.gz | 5.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cm_email_webhook_verification-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 11.1 kB
Release files / cm_email_webhook_verification-1.0.0.tar.gz
| Download URL | cm_email_webhook_verification-1.0.0.tar.gz |
|---|---|
| Size | 5.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
beda7764380e035e1f658e0205e969796e1342061ccd6fe6caa81de4a4f97b04
|
|
BLAKE2b-256 checksum How to use checksums |
d16fb9d3e47e31c516a6844c9a8ae50d220566f277f3fd748befe2d52190b675
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|
Release files / cm_email_webhook_verification-1.0.0-py3-none-any.whl
| Download URL | cm_email_webhook_verification-1.0.0-py3-none-any.whl |
|---|---|
| Size | 5.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
557bc2d7c4d95bd02c55f8e3c42947a30e184b63d481eeb99ffa4bf65ca1044a
|
|
BLAKE2b-256 checksum How to use checksums |
8c287e02416494c4d0a61440608a385bfc9aa5cdd11e2a732294f1eb6b2d7544
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|