Amazon SES
Fromenance is a communication provenance platform, and the Amazon SES adapter turns Send and Delivery events, delivered through an SNS HTTPS subscription, into registrations. SES does not expose the rendered body, so the adapter uses the reserve flow: you fetch a code before the send, place it in the template, and send it as the message tag fromenance_code.
By the end you will have an SES source, a configuration set publishing Send and Delivery to an SNS topic subscribed to the source’s webhook URL, the reserve call in your send path, and completions showing on the source’s health panel.
1. Create the source
Section titled “1. Create the source”curl -X POST https://api.fromenance.com/v1/sending-sources \ -H "Authorization: Bearer fr_live_..." \ -H "Content-Type: application/json" \ -d '{"name":"SES notifications","kind":"ses","expected_daily_volume":100000}'The response includes webhook_url (https://api.fromenance.com/v1/hooks/esp/src_...). The secret returned is not used by SNS, which signs with Amazon’s certificate; keep it anyway, since the URL is the only thing that binds the topic to your source.
2. Publish events to SNS
Section titled “2. Publish events to SNS”- SES console, Configuration sets, create one (for example
fromenance) or open the one you send with. - Event destinations, Add destination. Event types: Send and Delivery. Destination: Amazon SNS, choose or create a topic.
- SNS console, that topic, Create subscription. Protocol HTTPS, endpoint the
webhook_urlfrom step 1. Leave Enable raw message delivery off; the adapter expects the SNS JSON envelope. - Fromenance confirms the subscription automatically by fetching the
SubscribeURLfrom theSubscriptionConfirmationmessage, provided its host ends inamazonaws.com. The subscription shows as Confirmed within a few seconds. - Send every message with the configuration set: the
ConfigurationSetNameparameter, or theX-SES-CONFIGURATION-SETheader for raw sends.
What SNS sends and how it is verified
Section titled “What SNS sends and how it is verified”Every SNS message carries SignatureVersion (1 for SHA1withRSA, 2 for SHA256withRSA), Signature, and SigningCertURL. Fromenance fetches the certificate only from https://sns.<region>.amazonaws.com, verifies the signature over the canonical string of the message, and rejects anything else with 401. Messages of type Notification whose SES eventType is Send or Delivery become registrations; everything else is acknowledged and ignored.
From each event, per address in mail.destination:
| Registration field | SES field |
|---|---|
message_id |
mail.messageId |
| recipient (hashed immediately, never stored) | each address in mail.destination |
sent_at |
mail.timestamp |
from_address |
mail.source |
| subject fingerprint | mail.commonHeaders.subject |
| verify code | message tag fromenance_code, else the X-Fromenance-Code header |
template_id |
tag template_id, else the ses:configuration-set tag |
campaign_id |
tag campaign_id |
| content fingerprint | not available from SES; add it later with PATCH /v1/communications/{id} if you render the body yourself |
3. Reserve, tag, send
Section titled “3. Reserve, tag, send”import { SESv2Client, SendEmailCommand } from "@aws-sdk/client-sesv2";import { Fromenance } from "@fromenance/sdk";
const fr = new Fromenance({ apiKey: process.env.FROMENANCE_API_KEY!, tenantSecret: process.env.FROMENANCE_TENANT_SECRET! });const ses = new SESv2Client({});
const reserved = await fr.reserve({ to: customer.email, template_id: "statement-ready-v4", provider: "ses" });
await ses.send( new SendEmailCommand({ FromEmailAddress: "statements@northfieldbank.example", Destination: { ToAddresses: [customer.email] }, ConfigurationSetName: "fromenance", EmailTags: [ { Name: "fromenance_code", Value: reserved.verify_code }, { Name: "template_id", Value: "statement-ready-v4" }, ], Content: { Template: { TemplateName: "statement-ready-v4", TemplateData: JSON.stringify({ first_name: customer.firstName, fromenance_code: reserved.verify_code }), }, }, }),);In the SES template footer use {{fromenance_code}} twice. Message tag values are limited to ASCII letters, digits, underscores, and hyphens, which a verify code satisfies.
4. Confirm
Section titled “4. Confirm”- Send test event on the source runs a synthetic Send event through the adapter.
- SES console, the configuration set, Send test email with the tag set. Within seconds
health.completedincrements.
Source health
Section titled “Source health”silent is raised when no event arrives within silence_alert_minutes. If events_last_hour is zero while you are sending, check the SNS subscription status and CloudWatch delivery failures on the topic. Because SES can publish one Send and one Delivery per message, the second event for the same message and recipient is ignored, not double counted. coverage_gaps counts reservations that expired without an event.