amazon ses smtp python usage
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Amazon SES can send email either through its API or through a standard SMTP interface. If you want to use Python's built-in mail libraries or an existing SMTP-based mail workflow, SES SMTP works well, but you must use the correct regional endpoint, SMTP credentials, and TLS settings.
SES SMTP Is Not The Same As The SES API
A common source of confusion is that SES offers two different access styles:
- the SES API, typically used through
boto3 - the SES SMTP interface, used through
smtplibor any SMTP-capable client
If you use SMTP, you connect to an SES SMTP hostname and authenticate with SMTP credentials. That is different from calling AWS APIs with boto3 and IAM request signing.
A Minimal Python Example
This is the basic pattern:
- connect to the SES SMTP endpoint for your region
- start TLS
- authenticate with SES SMTP credentials
- send the message
Use The Right Credentials
Do not assume your normal AWS access key and secret key are valid as raw SMTP username and password. SES SMTP credentials are a separate concept and must be created or derived appropriately for the SMTP interface.
Also note that temporary AWS security credentials are not the usual answer for SES SMTP authentication.
If the login fails, the first things to verify are:
- SMTP username and password
- region-specific endpoint
- whether the credentials were created for SES SMTP use
Region Matters
SES SMTP endpoints are regional. If your verified identity and sending setup live in one region but your code connects to another region's SMTP endpoint, you can get authentication or sending failures.
That means the hostname in the example is not arbitrary. It needs to match the SES region you intend to use.
Sandbox And Identity Verification
New SES accounts often start in a sandbox-like state where sending is restricted. In that mode, you may need verified sender and recipient identities before messages will be accepted.
Even outside restricted sending mode, verify:
- sender identity or domain is configured correctly
- DKIM and related email authentication are set up when needed
- quotas and sending limits are not being exceeded
SMTP code can be correct and still fail because SES account configuration is incomplete.
Use TLS And A Reasonable Port
Port 587 with STARTTLS is the normal default. Port 465 is possible for implicit TLS in some SMTP clients, but 587 is the common starting point.
Avoid plain-text SMTP submission. Even when testing, use TLS.
Build Proper MIME Messages For Real Email
For production mail, you will usually need multipart bodies, HTML, attachments, or explicit character encoding. Python's email package handles that cleanly.
That is usually better than trying to handcraft raw SMTP message strings.
Common Pitfalls
The most common mistake is mixing up SES API credentials and SES SMTP credentials.
Another mistake is connecting to the wrong regional SMTP endpoint.
Developers also often forget SES account restrictions such as sender verification or sandbox limitations and then debug the Python code unnecessarily.
Finally, do not skip TLS setup. SES SMTP is an authenticated mail submission service, not a local development mail relay.
Summary
- Use Python's
smtplibwith the SES regional SMTP endpoint. - Authenticate with SES SMTP credentials, not arbitrary AWS credentials.
- Use
STARTTLSon port587unless you have a specific reason not to. - Make sure sender identity and account configuration are ready in SES.
- If sending fails, check credentials, region, and SES account restrictions before changing the code.

