AWS SES ExecModule
Overview
AwsSesModule brings governed Amazon Simple Email Service delivery into ValkyrAI workflows. It follows n8n's AWS SES email and template model while adding verified IntegrationAccount enforcement, operation-specific validation, bounded recipients and content, opaque pagination, read-only retry, single-attempt delivery and template writes, explicit deletion confirmation, normalized receipts, provider-error redaction, and annotation-backed Workflow Studio discovery.
The connector implements nine operations:
send_emailsends one plain-text, HTML, or multipart-alternative transactional message.send_templated_emailsends one existing SES template with flat bounded JSON data.list_templates,get_template,create_template,update_template, and confirmeddelete_templatemanage reusable SES templates.list_identitiesdiscovers sender identities by email address or domain.get_send_quotareturns the current regional sending quota and usage snapshot.
The connector does not send raw MIME, accept attachments, create or verify identities, manage suppression lists, configure event destinations, create configuration sets, or expose SES SMTP credentials. Those operations are deliberately deferred to narrower reviewed modules.
Usage
- Verify the sending domain or email address in the exact SES region used by the workflow.
- If the account is still in the SES sandbox, verify every recipient or request production access before customer delivery.
- Create an AWS IAM principal restricted to the SES actions, regions, identities, and templates the workflow needs.
- Store its access key ID and secret access key in an AWS
IntegrationAccount, verify the account, and keep it inREADYstatus. - Add
AwsSesModuleto a workflow and bind that account throughExecModuleConfig.authConfig.integrationAccount. - Choose one documented operation and provide only its accepted fields. Unexpected fields fail before provider access.
- Gate send and template-mutation operations with the workflow's normal outbound approval and reconciliation policy.
Never place AWS access keys, SMTP credentials, or session tokens in module input. Credential-shaped input fields are rejected before any SES request.
Inputs
| Name | Type | Required for | Default | Constraints |
|---|---|---|---|---|
operation | string | Every execution | None | One of the nine documented operations. |
region | string | Every execution | None | AWS region such as us-west-2; custom endpoints are not accepted. |
source | string | Both send operations | None | Plain verified sender email; no display-name or header syntax. |
toAddresses | array | Both send operations | None | One or more unique email addresses. |
ccAddresses | array | Optional send field | [] | Unique across To, CC, and BCC. |
bccAddresses | array | Optional send field | [] | Unique across To, CC, and BCC. |
replyToAddresses | array | Optional send field | [] | Bounded plain email addresses. |
returnPath | string | Optional send field | SES default | Verified bounce/complaint forwarding address. |
subject | string | send_email | None | Non-blank UTF-8, no control characters, at most 998 code points. |
textBody | string | Optional send_email body | None | Plain text; either this or htmlBody is required. |
htmlBody | string | Optional send_email body | None | HTML body; either this or textBody is required. |
templateName | string | Template send/get/create/update/delete | None | 1-64 letters, digits, underscores, or hyphens. |
templateData | object | Optional send_templated_email data | {} | At most 100 flat scalar values and 100,000 serialized JSON bytes. |
subjectPart | string | Required for create; optional update | None | Template subject, at most 998 code points. |
textPart | string | Template create/update | None | Plain-text template body. |
htmlPart | string | Template create/update | None | HTML template body. |
configurationSetName | string | Optional send field | None | Existing SES configuration-set name using the bounded name format. |
paginationToken | string | Optional list field | None | Opaque SES token, at most 4,096 characters. |
limit | integer | Optional list field | 100 | From 1 through 1,000. |
returnAll | boolean | Optional list field | false | Follow pages until limit or provider exhaustion. |
identityType | string | Optional list_identities filter | all | all, email_address, or domain. |
confirmDelete | boolean | delete_template | false | Must be exactly true before permanent deletion. |
The combined To, CC, and BCC audience is capped at 50 recipients. Subject plus content, or the combined template parts, is capped at 9 MiB before SES encoding so the connector stays below the provider's classic API envelope limit. The module rejects duplicate recipients case-insensitively and rejects nested template data rather than silently flattening it.
Outputs
Every execution returns stable status, operation, and attempts fields.
| Name | Type | When present | Description |
|---|---|---|---|
status | string | Always | success or error. |
operation | string | Always | Normalized operation. |
attempts | integer | Always | Provider calls, including list pages and retry-safe read attempts. |
resultType | string | Success | message, templates, template, identities, or quota. |
items | array | List success | Bounded normalized template metadata or identity values. |
count | integer | List success | Number of returned items. |
hasMore | boolean | List success | Whether SES returned another continuation token. |
paginationToken | string | Another page exists | Opaque SES continuation token. |
data | object | Non-list success | Message receipt, template content/mutation receipt, or quota values. |
requestId | string | AWS supplies one | Bounded provider reference for reconciliation and support. |
error | object | Failure | Safe {code, message, httpStatus?, retryable} details. |
Successful sends return only the SES messageId, recipient count, and template name when applicable. Email bodies and template data are not echoed. Template reads can return bounded subject/text/HTML parts and must remain in an ACL-scoped workflow.
IntegrationAccount Requirements
Bind one AWS IntegrationAccount through the normalized ExecModule authentication relationship:
| Field | Requirement |
|---|---|
| Provider | Amazon Web Services / Simple Email Service |
status | Must be READY. |
verified | Must be true. |
apiKey SecureField | AWS access key ID. |
password SecureField | AWS secret access key. |
Grant only the actions enabled in the workflow:
- Delivery:
ses:SendEmailand, for template sends,ses:SendTemplatedEmail. - Templates:
ses:ListTemplates,GetTemplate,CreateTemplate,UpdateTemplate, andDeleteTemplateas needed. - Discovery:
ses:ListIdentitiesandses:GetSendQuota.
Use IAM conditions such as ses:FromAddress, ses:Recipients, and ses:FromDisplayName where they fit the delivery policy. The current connector supports a long-lived access-key pair. Temporary session credentials, STS role assumption, workload identity, custom endpoints, and explicit sending-authorization ARNs are deferred.
Configuration
The awsAccount relationship is the only credential configuration. Operation, region, sender, audience, and content fields belong in mapped input or module parameters.
{
"version": "1.0.0",
"authConfig": {
"authStrategy": 1,
"integrationAccount": "integration-account:aws-ses-production"
},
"payloadConfig": {
"parameters": "{\"operation\":\"send_templated_email\",\"region\":\"us-west-2\",\"templateName\":\"OrderReady\"}"
}
}
The relationship value is illustrative. Persisted workflows bind the generated IntegrationAccount relationship, never plaintext credentials.
Operations
| Operation | Provider behavior | Side effect and retry behavior |
|---|---|---|
send_email | Sends one UTF-8 message with text and/or HTML. | External side effect, exactly one provider attempt, no automatic replay. |
send_templated_email | Renders and sends an existing SES template. | External side effect, exactly one provider attempt; rendering failures may be asynchronous. |
list_templates | Returns bounded template metadata and an opaque token. | Read-only; each page retries transient failures up to three attempts. |
get_template | Retrieves one exact template and bounded content parts. | Read-only; bounded retry. |
create_template | Creates one named template. | Single attempt; reconcile by exact template name before replay. |
update_template | Replaces supplied template parts. | Single attempt; read the exact template before replay. |
delete_template | Permanently deletes one template after confirmDelete=true. | Destructive, single attempt, no automatic replay. |
list_identities | Returns bounded verified/pending identity names by optional type. | Read-only; bounded pagination and retry. |
get_send_quota | Returns regional daily maximum, rate, and last-24-hour usage. | Read-only; bounded retry. |
Errors and Failure Modes
| Code | Typical cause | Retryable | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Missing/malformed region, sender, recipient, content, template, pagination field, identity filter, or confirmation; unexpected operation field. | No | Correct the named input; no provider request was sent. |
UNSUPPORTED_OPERATION | Unknown operation. | No | Select a documented operation. |
INTEGRATION_ACCOUNT_ERROR | Account missing, unverified, not READY, or missing key material. | No | Repair and bind the AWS account. |
AWS_SES_HTTP_400 | Address not verified, sandbox recipient restriction, invalid template data, rendering setup, or provider constraint. | Usually no | Inspect exact region, identity, sandbox state, template, and recipient policy. |
AWS_SES_HTTP_403 | IAM denies the selected action, identity, or region. | No | Grant only the missing SES action under the intended conditions. |
AWS_SES_HTTP_404 | Referenced template no longer exists. | No | Reconcile the exact template name before creating or stopping. |
AWS_SES_HTTP_429 / 500 / 503 | Throttle or transient provider pressure. | Reads retry; sends/writes report ambiguity | Inspect provider events and exact resource state before any replay. |
NETWORK_ERROR | DNS, TLS, timeout, or connectivity failure. | Reads retry; sends/writes report ambiguity | Treat delivery or mutation acceptance as unknown until reconciled. |
EXECUTION_ERROR | Unexpected bounded runtime failure. | No automatic replay | Preserve the operation and request evidence for investigation. |
Provider exception text is never copied into workflow output, preventing AWS credentials, recipient data, email content, or unbounded provider payloads from leaking through error handling.
Example
Send a reviewed template after an order reaches the approved fulfillment state:
{
"operation": "send_templated_email",
"region": "us-west-2",
"source": "billing@example.com",
"toAddresses": ["buyer@example.com"],
"replyToAddresses": ["support@example.com"],
"templateName": "OrderReady",
"templateData": {
"orderNumber": "A-1042",
"downloadCount": 3
},
"configurationSetName": "transactional"
}
Expected result shape:
{
"status": "success",
"operation": "send_templated_email",
"attempts": 1,
"resultType": "message",
"data": {
"messageId": "provider-message-id",
"recipientCount": 1,
"templateName": "OrderReady"
},
"requestId": "aws-request-reference"
}
The receipt means SES accepted the submission; it does not prove inbox delivery. Correlate the message with SES event publishing, bounce, complaint, and delivery telemetry outside this connector.
Notes
- Pagination:
list_templatesandlist_identitiesreturn one page unlessreturnAll=true. The connector follows opaque tokens only with unchanged filters and stops atlimit. - Rate limits: SES quotas vary by account, production/sandbox state, region, and action. Read calls use at most three attempts with short bounded backoff. Sends and template mutations never retry automatically.
- API limits: the module caps list output at 1,000 items, combined recipients at 50, template data at 100 keys/100,000 JSON bytes, each body at five million characters, and message/template content at 9 MiB.
- Idempotency: reads are replay-safe.
send_email,send_templated_email, and all template mutations can have side effects and are single-attempt. - Ambiguous sends: if transport fails after SES accepts a message, use SES event telemetry, workflow correlation data, and the provider request/message identifiers before deciding whether to replay. Never assume a timeout means no delivery.
- Template rendering: SES can accept a templated message and later emit a rendering failure. Configure event publishing and monitor rendering-failure events for delivery-critical workflows.
- Sandbox behavior: SES sandbox accounts can send only from and to verified identities and have reduced quotas. Production access is an account/region control outside the module.
- Suppression and reputation: account/global suppression, hard bounces, complaints, recipient-provider rejection, and reputation controls can prevent delivery after acceptance.
- Destructive behavior:
delete_templatepermanently removes the named template and requiresconfirmDelete=true. The connector never deletes identities or configuration sets. - Security: recipients and template content may contain personal or confidential data. Keep outputs within ACL-scoped workflows and do not log whole template reads.
- Deferred operations: raw MIME, attachments, bulk sends, custom verification email templates, identity verification/deletion, suppression-list management, sending-authorization ARNs, configuration-set lifecycle, SMTP credentials, and event-destination configuration are not implemented.
- Provider verification boundary: deterministic tests cover validation, recipient deduplication, bounded pagination, template operations, flat data, retry boundaries, deletion confirmation, credential/provider-error redaction, registration, and metadata. Live SES behavior remains unverified until an authorized SES account, verified test identities, and reviewed non-production recipients are supplied.
- Functional reference: n8n's AWS SES node exposes direct/template sends plus template lifecycle and custom-verification workflows. ValkyrAI covers the high-value direct/template and discovery surface with stronger account, scope, replay, output, and deletion controls.
- Runtime boundary: merged source and published documentation do not update the deployed Workflow Studio catalog until a ValkyrAI backend release exposes
AwsSesModulethrough/v1/modules/metadata.