Skip to content

Instantly share code, notes, and snippets.

@douglasmiranda
Created April 23, 2024 23:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save douglasmiranda/3d840007f4a1acb064ff2ecf0d62ae32 to your computer and use it in GitHub Desktop.
Save douglasmiranda/3d840007f4a1acb064ff2ecf0d62ae32 to your computer and use it in GitHub Desktop.
Mailgun Webhook: validate webhook request in Python
# https://documentation.mailgun.com/docs/mailgun/user-manual/tracking-messages/#webhooks
# Securing Webhooks
# To ensure the authenticity of event requests, Mailgun signs them and posts the signature alongside the webhook's event-data.
# A signature takes the following form:
# Parameter Type Description
# timestamp int Number of seconds passed since January 1, 1970.
# token string Randomly generated string with length of 50.
# signature string String with hexadecimal digits generated by an HMAC algorithm
# To verify the webhook originated from Mailgun, you will need to:
# Concatenate timestamp and token values together with no separator.
# Encode the resulting string with the HMAC algorithm, using your Webhook Signing Key as a key and SHA256 digest mode.
# Compare the resulting hexdigest to the signature. If they do not match then the webhook is not from Mailgun!
import hmac, hashlib
# Look for HTTP webhook signing key in your Mailgun panel
WEBHOOK_SIGNING_KEY = b"key-xxx"
def verify(token, timestamp, signature):
hmac_digest = hmac.new(
key=WEBHOOK_SIGNING_KEY,
msg="{}{}".format(timestamp, token).encode("utf-8"),
digestmod=hashlib.sha256,
).hexdigest()
return hmac.compare_digest(signature, hmac_digest)
# Mailgun's POST request will have "signature" in the payload, there you'll find
# "token", "timestamp" and "signature" fields, like so:
# {
# "token": "xxx",
# "timestamp": "yyy",
# "signature": "zzz"
# }
print(verify("xxx", "yyy", "zzz"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment