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
| 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"},
}
}
)