Skip to content

AWS SES (Email)

Stelvio supports creating and managing Amazon SES (Simple Email Service) identities using the Email component. This allows you to send emails from your applications.

Sandbox Mode

Your AWS account might be sandboxed and thus, only allows validated email recipients.

You can request production access for your account.

Creating an Email Identity

You can create an email identity by instantiating the Email component in your stlv_app.py.

from stelvio.aws.email import Email
from stelvio.aws.function import Function

@app.run
def run() -> None:
    # Create an email identity
    email = Email(
        "stlv_email",
        "sender@example.com",
    )

    # Link it to a function
    linked_function = Function(
        "MyFunctionA",
        handler="functions/api.handler",
        url="public",
        links=[email],
    )

Sending Emails

Using the linking mechanism, you can easily access the SES identity in your Lambda functions using the regular boto3 library.

The Email component exposes the sender identity and its ARN through stlv_resources.

import boto3
from stlv_resources import Resources

def handler(event, context):
    client = boto3.client('sesv2')

    # Access the linked resource properties
    resources = Resources.stlv_email
    SENDER = resources.email_identity_sender
    RECIPIENT = "recipient@example.com"

    body = "Hello from Stelvio!"

    response = client.send_email(
        FromEmailAddress=SENDER,
        Destination={
            'ToAddresses': [RECIPIENT]
        },
        Content={
            'Simple': {
                'Subject': {'Data': 'Test Subject'},
                'Body': {'Text': {'Data': body}}
            }
        }
    )

    return {"statusCode": 200, "body": "Email sent!"}

Domain Identities

If you provide a domain name instead of an email address as the sender, Stelvio will create a domain identity.

    email = Email(
        "myDomainEmail",
        "example.com",
        dmarc="v=DMARC1; p=none;",
    )

When using a domain identity, Stelvio automatically handles:

  • DKIM (DomainKeys Identified Mail) records
  • DMARC (Domain-based Message Authentication, Reporting, and Conformance) records

Note that for domain identities, you must have a DNS provider configured in your Stelvio app context, or pass one explicitly to the Email component. If you want to manage DNS yourself (see DNS Configuration below), pass dns=False.

DMARC Configuration

The dmarc parameter is only valid for domain identities and accepts the following values:

Value Behavior
None Uses the default DMARC policy: "v=DMARC1; p=none;"
str Uses your custom DMARC policy string
False Explicitly disables DMARC record creation
    # Default DMARC policy
    email = Email("myEmail", "example.com")
    email = Email("myEmail", "example.com", dmarc=None)

    # Custom DMARC policy
    email = Email("myEmail", "example.com", dmarc="v=DMARC1; p=reject; rua=mailto:dmarc@example.com")

    # Disable DMARC
    email = Email("myEmail", "example.com", dmarc=False)

DNS Configuration

The dns parameter controls how Stelvio manages DNS records for domain identities:

Value Behavior
None Uses the DNS provider configured in StelvioAppConfig. Raises if none is configured.
Dns instance Uses the given provider for this Email only. Useful when the email sender domain lives on a different DNS provider than your app's main domain.
False Opts out of Stelvio managing DNS for this email entirely.

When you pass dns=False, Stelvio still creates the SES email identity, configuration set, and any event destinations. It skips DKIM record creation, DMARC record creation, and the domain verification resource (which would otherwise block deploy waiting on records that don't exist).

Use this when:

  • Your DNS provider isn't supported by Stelvio.
  • DKIM/DMARC records already exist for the domain from a previous setup.
  • DNS is managed by a separate team or system.

SES won't verify the domain until DKIM records exist in DNS

Stelvio's deploy completes successfully with dns=False, but emails won't send until you add the required DNS records yourself.

After deploy, retrieve the DKIM tokens from the AWS Console (SES → Verified Identities → your domain), or expose them as Pulumi stack outputs:

from stelvio import export_output
from stelvio.aws.email import Email

email = Email("alerts", "example.com", dns=False)
export_output("alerts_dkim", email.resources.identity.dkim_signing_attributes)

Run stlv outputs after deploy to see the three DKIM tokens, then add three CNAME records to your DNS provider:

<token1>._domainkey.example.com  CNAME  <token1>.dkim.amazonses.com
<token2>._domainkey.example.com  CNAME  <token2>.dkim.amazonses.com
<token3>._domainkey.example.com  CNAME  <token3>.dkim.amazonses.com

Optionally add a DMARC TXT record at _dmarc.example.com. SES will verify the domain (usually within minutes) and emails can send.

Sandbox Mode

AWS accounts start in SES sandbox mode, which restricts sending to verified email addresses only. Stelvio provides a sandbox parameter to configure permissions accordingly.

    email = Email(
        "stlv_email",
        "sender@example.com",
        sandbox=True,
    )

When sandbox=True, the linked Lambda function receives broader permissions ("*" resource) for sending emails, which is required when your account is in sandbox mode. Once you have requested production access, you can set sandbox=False (the default) to use more restrictive permissions.

Event Destinations

You can configure SNS event destinations to receive notifications about email events such as bounces, complaints, and deliveries.

    email = Email(
        "stlv_email",
        "sender@example.com",
        events=[
            {
                "name": "bounce-handler",
                "types": ["bounce", "complaint"],
                "topic_arn": "arn:aws:sns:us-east-1:123456789012:email-bounces",
            },
            {
                "name": "delivery-tracker",
                "types": ["delivery", "send"],
                "topic_arn": "arn:aws:sns:us-east-1:123456789012:email-deliveries",
            },
        ],
    )

Supported Event Types

See official AWS docs

Event Type Description
send Email send initiated
delivery Email successfully delivered
bounce Email bounced
complaint Recipient marked email as spam
reject SES rejected the email
open Recipient opened the email
click Recipient clicked a link
delivery-delay Temporary delivery delay
rendering-failure Template rendering failed
subscription Subscription preference change

Customization

The Email component supports the customize parameter to override underlying Pulumi resource properties. For an overview of how customization works, see the Customization guide.

Resource Keys

Resource Key Pulumi Args Type Description
identity EmailIdentityArgs The SES email identity
configuration_set ConfigurationSetArgs SES configuration set
dkim_records Plain dict (no Pulumi Args — DNS records are provider-agnostic) DKIM DNS records (for domains)
dmarc_record Plain dict (no Pulumi Args — DNS records are provider-agnostic) DMARC DNS record (for domains)
verification DomainIdentityVerificationArgs Domain verification (for domains)
event_destinations ConfigurationSetEventDestinationArgs Event destination (when configured)

Example

email = Email(
    "my-email",
    "notifications@example.com",
    customize={
        "identity": {
            "tags": {"Service": "notifications"},
        }
    }
)