Skip to content

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.

Terminal window
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.

  1. SES console, Configuration sets, create one (for example fromenance) or open the one you send with.
  2. Event destinations, Add destination. Event types: Send and Delivery. Destination: Amazon SNS, choose or create a topic.
  3. SNS console, that topic, Create subscription. Protocol HTTPS, endpoint the webhook_url from step 1. Leave Enable raw message delivery off; the adapter expects the SNS JSON envelope.
  4. Fromenance confirms the subscription automatically by fetching the SubscribeURL from the SubscriptionConfirmation message, provided its host ends in amazonaws.com. The subscription shows as Confirmed within a few seconds.
  5. Send every message with the configuration set: the ConfigurationSetName parameter, or the X-SES-CONFIGURATION-SET header for raw sends.

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
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.

  • 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.completed increments.

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.