AWS SES webhook verifier via Amazon SNS.
Implements Mailglass.Webhook.Provider for SES events delivered through
SNS HTTP subscriptions. Handles all three SNS message types on the same
endpoint:
Notification— SES event payload; returns:okfor the ingest pipelineSubscriptionConfirmation— auto-confirms after verification; returns{:ok, :control_plane, :subscription_confirmed}UnsubscribeConfirmation— verifies and no-ops; returns{:ok, :control_plane, :unsubscribe_confirmed}
Verification algorithm
- Parse raw body as JSON (SNS delivers
text/plainbut body is valid JSON) - Validate
SigningCertURLwithTrustPolicy.valid_cert_url?/1before network I/O - Fetch X.509 public key from
CertCache(ETS hit) or:httpc(cache miss) - Build canonical string from message fields (byte-sorted per AWS spec)
- Verify RSA-SHA1 (SignatureVersion 1) or RSA-SHA256 (SignatureVersion 2) signature
- Dispatch on
MessageType:Notification→ return:okSubscriptionConfirmation→ validate SubscribeURL, construct ConfirmSubscription URL from TopicArn + Token, :httpc GET with redirects disabledUnsubscribeConfirmation→ log telemetry, return control-plane no-op
Inbound-reuse seam
verify_envelope!/2 exposes steps 1-5 (the SNS X.509 verification) as a public
seam so mailglass_inbound's SES ingress can reuse the byte-identical SNS
envelope verification without reinventing cryptography (-01). verify!/3
calls it, then dispatches on MessageType; its public return and behavior are
unchanged.
Configuration (Application env)
config :mailglass, :ses,
cert_cache_ttl_seconds: 86_400 # default 24 hours
Summary
Functions
Verify the SNS envelope's X.509 signature and trust policy, returning the decoded SNS payload.
Functions
Verify the SNS envelope's X.509 signature and trust policy, returning the decoded SNS payload.
This is the inbound-reuse seam (-01): the SNS JSON envelope is
byte-identical for outbound webhooks and mailglass_inbound SES ingress, so
the crypto primitive (decode → TrustPolicy.valid_cert_url? → CertCache
public-key fetch → canonical-string build → :public_key.verify) is factored
out for mailglass_inbound.Ingress.Providers.SES to call directly, then drive
its own MessageType dispatch (S3 fetch / inline content / control-plane).
Raises Mailglass.SignatureError on any verification failure — identical
behavior to the steps previously inlined in verify!/3. The outbound
verify!/3 return and behavior are unchanged.